Can anyone please check out my code here, trying to hide selected components with proselectbuffer here, it worked just before it crushed, can anyone help me out, thanks.
ProError ShowMessageText(ProModelitem *modelitem)
{
/*********************************************************/
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ProError status,err1,err2,err3;
ProSelection *sels;
ProAsmcomppath comppath;
ProMdl mdl;
status = ProSelbufferSelectionsGet(&sels);
// status = ProSelectionModelitemGet(sels[0],modelitem);
status = ProSelectionAsmcomppathGet(sels[0], &comppath);
status= ProAsmcomppathMdlGet(&comppath,&mdl);
if(status == PRO_TK_NO_ERROR)
{
AfxMessageBox(_T("get mdl"));
status=ProMdlToModelitem(mdl,modelitem);
if(status == PRO_TK_NO_ERROR)
{ AfxMessageBox(_T("pass")); }
modelitem->type = PRO_FEATURE;
modelitem->owner = comppath.owner;
modelitem->id = comppath.comp_id_table[0];
err2 = ProModelitemHide(modelitem);
if(err2 == PRO_TK_NO_ERROR)
{ AfxMessageBox(_T("done")); }
ProSelectionarrayFree(sels);
}
return PRO_TK_NO_ERROR;
}
Solved! Go to Solution.
Hello JC,
by providing the tiny code snippet my goal was just to illustrate the role of different contents in the selection buffer. It was not intended to be a real world code ready to go live, of course 🙂
Here I provide a function that should suit your requirement to hide parts or subassemblies that are in active selection buffer:
auto HideSelectedPartsAndSubAssemblies() -> void
{
ProSelection *selbufferSelections = nullptr;
if (ProSelbufferSelectionsGet(&selbufferSelections) != PRO_TK_NO_ERROR)
return;
int nSels;
CHECKVOID(ProArraySizeGet(selbufferSelections, &nSels));
for (int i = 0; i < nSels; ++i)
{
ProModelitem modelItem;
CHECKVOID(ProSelectionModelitemGet(selbufferSelections[i], &modelItem));
if (modelItem.type != PRO_PART && modelItem.type != PRO_ASSEMBLY)
continue;
ProAsmcomppath acp;
CHECKVOID(ProSelectionAsmcomppathGet(selbufferSelections[i], &acp));
if (acp.table_num < 1)
continue;
const auto componentFeatureId = acp.comp_id_table[acp.table_num - 1];
acp.comp_id_table[acp.table_num - 1] = PRO_VALUE_UNUSED;
--acp.table_num;
ProMdl acpModelOwner;
CHECKVOID(ProAsmcomppathMdlGet(&acp, &acpModelOwner));
ProModelitem modelitemToHide = { PRO_FEATURE,
componentFeatureId,
acpModelOwner };
CHECKVOID(ProModelitemHide(&modelitemToHide));
}
ProSelectionarrayFree(selbufferSelections);
ProMdl curModel;
CHECKVOID(ProMdlCurrentGet(&curModel));
ProTreetoolRefresh(curModel);
ProSelbufferClear();
}
You have to validate and to deal with the path.
For example, if your path is 85 77 45 (size 3, these are feature IDs!) then you have selected the model 45 'index 2' in the sub assembly 77 (size-1, index 1) and your model item owner must be the handle to that assembly 77 and NOT the comp path owner , because this is the top level assembly you have just open.
To Hide 45
the model item should look like:
type is PRO_FEATURE
id is 45
owner is the model handle of 77 (with ProMdlToModelitem(memb_id_tab, size-1,&model))
You hide a feature in one assembly, so you hide it in every occurrence where this the assembly is used!
The owner is always the parent assembly of the selected model.
ProMdlToModelitem is useless because you need to deal with feature IDs and NOT with Model IDs. And 'modelitem' is not declared in your code snippet.
ProAsmcomppathMdlGet will return the model the Model based on the given path AND table_size, and you can modify the table_size before you call, this would not change ProIdTable memb_id_tab,
Only if the size is 1 you have selected something in the root assembly, than your code should work as far I can see this.
In that case:
type is PRO_FEATURE
id is 85 (for my example this must be an assembly)
owner is comppath.owner (the root assy)
Maybe this helps.
Try this:
ProAsmcomppath acp;
CHECKERROR(ProSelectionAsmcomppathGet(selection, &acp));
ProModelitem modelItem;
CHECKERROR(ProSelectionModelitemGet(selection, &modelItem));
const auto componentFeatureId =
acp.table_num > 0 ? acp.comp_id_table[acp.table_num - 1]
: modelItem.id;
ProModelitem modelitemToHide = { PRO_FEATURE, componentFeatureId, acp.owner };
CHECKERROR(ProModelitemHide(&modelitemToHide));
The point here why it worked before and no more after the "crush" might be that you had different selections in selbuffer. On the one hand, if you select the component itself, the AsmComppath has a table_num of zero and this won't lead to the correct component feature id for your modelitem to hide. On the other hand, if you select anything inside the component feature, a revolve for instance, then the component feature id will be contained in the com_id_table and the table_num won't be zero.
Hello Fabian, if a feature (a revolve) was selected, the model item will contain this feature ID, and NOT the path, the path is not impacted, it tells you only the path to the model. You should check the selected model item type and than decide if you want to hide the component where a revolve was selected.
It's a component path, not the path to a selected feature.
But maybe I'm wrong, hopefully not 🙂
@RPN schrieb:... if a feature (a revolve) was selected, the model item will contain this feature ID, and NOT the path, the path is not impacted, it tells you only the path to the model. ...
Exactly, and that's what we want. The revolve id is not of interest. We want the component feature id of the component, that owns the revolve. And this id is contained in the asmcomppath.
For me it’s easy to misunderstand
„ … then the component feature id will be contained in the com_id_table …“
because the revolve is a feature ID of the component. .
But we are on the same page, and I wasn’t wrong.
God bless 😜
Yes, the feature id is not the same as the id of the component owning the feature. They both have their own lifes and dreams and ids 😄
Have a nice day!
Hello Fabian
ProModelitem modelitemToHide = { PRO_FEATURE, componentFeatureId, acp.owner };
Hmm, acp.owner are you sure about, I think this will not work if you path size is greater then one.
I thought again about this riddle,.
If you have a selection buffer, the model item is PRO_PART or PRO_ASSEMBLY regardless of the selection filter, if a Part or an Assembly was picked. If this is the case you need to configure the model item to hide, by the last path id, and you need to get the parent of the id, this is for sure an assembly, The parent may the active assembly as well (size 0).
Here a working Tcl code, just use the same logic in your C code:
proc HideSelBuffer {} {
# prepare the sel object commands
# and link to an model item and comp path object
ps_sel selObj -modelitem miObj -comppath cpObj
# how big is the buffer
set size [selObj buffsize]
# if nothing selected do nothing
if {$size < 1} {
Debug "Buffer is empty or not available"
return
}
# now loop through
for {set idx 0 } {$idx < $size} {incr idx} {
# get the selection idx
selObj buffget $idx
# Check model item type
# only for PART or ASSEMBLY check for hide
if { [miObj cget -type] eq "PART" || [miObj cget -type] eq "ASSEMBLY"} {
# get the path
set path [cpObj cget -path]
# for '47 98 44' the level is three
# level 0 is comp path owner
set level [llength $path ]
# only if a path found
if {$level > 0} {
# get the selected component id
# from '47 98 44' it would be 44
set selcomp [lindex $path end]
# get the parent
# for '47 98 44' the parent is at '47 98'
# should be an assembly
set assy [cpObj model [incr level -1] ]
# prepare to hide
miObj config -model $assy -type Feature -id $selcomp
# hide only if not already hidden
if {[miObj ishidden] == 0 } {
# hide it
miObj hide
}
}
}
}
}
Dear RPN,
yes, you are right, i tried, and the code from Fabian only works for part in active assembly.
i try to interpret your codes into toolkit, but don't have a clue how to find the parent assembly, can you help me out?which function should i use?
thanks.
Jon
extern ProError ProAsmcomppathMdlGet (ProAsmcomppath *p_path,
ProMdl *p_model);
/*
Purpose: Retrieves the model specified by the component path.
Input Arguments:
p_path - The component path
Output Arguments:
p_model - The model found at the end of the component path
Return Values:
PRO_TK_NO_ERROR - The function successfully retrieved the model.
PRO_TK_BAD_INPUTS - The input argument is invalid.
PRO_TK_GENERAL_ERROR - The specified component path was wrong, or
contained missing members.
*/
typedef struct pro_comp_path
{
ProSolid owner;
ProIdTable comp_id_table;
int table_num;
} ProAsmcomppath;
Tcl level = Tk table_num
Hello JC,
by providing the tiny code snippet my goal was just to illustrate the role of different contents in the selection buffer. It was not intended to be a real world code ready to go live, of course 🙂
Here I provide a function that should suit your requirement to hide parts or subassemblies that are in active selection buffer:
auto HideSelectedPartsAndSubAssemblies() -> void
{
ProSelection *selbufferSelections = nullptr;
if (ProSelbufferSelectionsGet(&selbufferSelections) != PRO_TK_NO_ERROR)
return;
int nSels;
CHECKVOID(ProArraySizeGet(selbufferSelections, &nSels));
for (int i = 0; i < nSels; ++i)
{
ProModelitem modelItem;
CHECKVOID(ProSelectionModelitemGet(selbufferSelections[i], &modelItem));
if (modelItem.type != PRO_PART && modelItem.type != PRO_ASSEMBLY)
continue;
ProAsmcomppath acp;
CHECKVOID(ProSelectionAsmcomppathGet(selbufferSelections[i], &acp));
if (acp.table_num < 1)
continue;
const auto componentFeatureId = acp.comp_id_table[acp.table_num - 1];
acp.comp_id_table[acp.table_num - 1] = PRO_VALUE_UNUSED;
--acp.table_num;
ProMdl acpModelOwner;
CHECKVOID(ProAsmcomppathMdlGet(&acp, &acpModelOwner));
ProModelitem modelitemToHide = { PRO_FEATURE,
componentFeatureId,
acpModelOwner };
CHECKVOID(ProModelitemHide(&modelitemToHide));
}
ProSelectionarrayFree(selbufferSelections);
ProMdl curModel;
CHECKVOID(ProMdlCurrentGet(&curModel));
ProTreetoolRefresh(curModel);
ProSelbufferClear();
}
HI Fabian, thanks for your help, the code works perfectly.
From what I can see, RPN provided a great solution on this topic for tcl users 👍
Hello Fabian, thank you for the 🥀🥀.
Some Notes:
if (acp.table_num < 1)
continue;
May not needed if PRO_PART or PRO_ASSEMBLY is checked.
In Creo 10 the tree selection will return the model item based on the filter as I see.
Here the more Tcl enhanced version (regarding access to comp ID and parent model), without notes:
proc HideSelBuffer {} {
ps_sel selObj -modelitem miObj -comppath cpObj
for {set idx 0 } {$idx < [selObj buffsize] } {incr idx} {
selObj buffget $idx
set type [miObj cget -type]
if { $type ne "PART" || $type ne "ASSEMBLY"} continue
set compID [cpObj compid end]
set ParentAsm [cpObj model_in_level end-1]
miObj config -model $ParentAsm -type Feature -id $compID
miObj hide
}
selObj buffclear
ps_model tree_update -model [ps_model cur]
ps_wind rep
}
And a Proof 🙂
Cheers !!!
if (acp.table_num < 1)
continue;
is needed as the root assembly might be selected, which is also a PRO_ASSEMBLY 🙂
Great video!
Hide root! I get not an error if I try that 🙂
And the video lags a bit of Quality.
Anyhow stop thinking about that Buffer Stuff 🙂