Re: Pass struct from Tool to Operator
Many thanks to Oleg Bliznuk, we found what cause this problem: oCustomOperator.PutAlwaysEvaluate(true); -- Softimage Mailing List. To unsubscribe, send a mail to softimage-requ...@listproc.autodesk.com with "unsubscribe" in the subject, and reply to confirm.
Re: Pass struct from Tool to Operator
Hi guys. Yesterday i mention problem with userdata in Operators. I thought that each time i PutUserData to an OperatorContext it lies in this object instance, and each Operator would have its own UserData, with its own allocated memory for data structure. But as i said yesterday i mention that its not. The 1st Operator added to modelling stack would have pointer to 1st allocated dynamic memory in UserData. The 2nd Operator added to modelling stack would have 1st AND 2nd allocated dynamic memory in UserData. And so on. So i can't find out why does it happen. I wrote simple dummy plugin, to demonstrate the problem. This plugin simply create Operator and apply it to selected object edges. To reproduce this problem select edge-loop and run: Application.avDuplicateStart() Then select another one edge-loop and run it again: Application.avDuplicateStart() And you see that on a second run it would print to log both pointers to allocated memory from UserData ( currently and previously applied ). On a third run it would print three of them and so on. Here is the source code of dummy plugin: https://www.dropbox.com/sh/pi33a9l8miilu1o/AAAftxU3ppDXo7_j2CxWCOK1a?dl=0 And here is a part of Operator callbacks: SICALLBACK avDuplicate_Init( CRef& in_ctxt ) { Application().LogMessage(L"Operator: init callback "); OperatorContext opCtxt( in_ctxt ); //std::shared_ptr opDataPtr (new OperatorData); // create pointer to struct OpData allocated for curent CustomOperator in dynamic memory OperatorData* opDataPtr = new OperatorData; CValue opptrValue = (CValue::siPtrType) opDataPtr; OperatorData& opData = (*opDataPtr); opCtxt.PutUserData( opptrValue ); // set default value opData.merge = false; Application().LogMessage(L"[init] ptrValue" + CValue(opptrValue).GetAsText()); return CStatus::OK; } SICALLBACK avDuplicate_Define( CRef& in_ctxt ) { Application().LogMessage(L"Operator: define callback "); Context ctxt( in_ctxt ); CustomOperator oCustomOperator; Parameter oParam; CRef oPDef; Factory oFactory = Application().GetFactory(); oCustomOperator = ctxt.GetSource(); //! CUSTOMOPERATOR PARAMETERS: oPDef = oFactory.CreateParamDef(L"merge",CValue::siBool,siPersistable | siKeyable,L"",L"",CValue(false),0,1,0,1); oCustomOperator.AddParameter(oPDef,oParam); oCustomOperator.PutAlwaysEvaluate(true); oCustomOperator.PutDebug(0); return CStatus::OK; } SICALLBACK avDuplicate_Update( CRef& in_ctxt ) { Application().LogMessage(L"Operator: update callback "); OperatorContext opCtxt( in_ctxt ) ; CValue opptrValue = opCtxt.GetUserData(); OperatorData* opDataPtr = (OperatorData*)(CValue::siPtrType)opptrValue; OperatorData& opData = (*opDataPtr); // we would toggle this value to differentiate applied Operators opData.merge = opCtxt.GetParameterValue(L"merge"); Application().LogMessage(L"[update] ptrValue: " + CValue(opptrValue).GetAsText()); Application().LogMessage(L"[update] opData.merge: " + CValue(opData.merge).GetAsText()); return CStatus::OK; } SICALLBACK avDuplicate_Term( CRef& in_ctxt ) { Application().LogMessage(L"Operator: term callback "); OperatorContext opCtxt( in_ctxt ) ; CValue opptrValue = opCtxt.GetUserData(); OperatorData* opDataPtr = (OperatorData*)(CValue::siPtrType)opptrValue; delete opDataPtr; return CStatus::OK; } -- Softimage Mailing List. To unsubscribe, send a mail to softimage-requ...@listproc.autodesk.com with "unsubscribe" in the subject, and reply to confirm.
Re: Pass struct from Tool to Operator
If i use Plugin's UserData i have a problem with releaseing memory. struct myStruct{ XSI::CLongArray polyData; XSI::CValueArray edgeSegmentsArray; } SICALLBACK XSILoadPlugin( PluginRegistrar& in_reg ){ PlugData * pDataPtr = new PlugData ; CValue ptrValue = (CValue::siPtrType) pDataPtr; in_reg.PutUserData(ptrValue); } SICALLBACK XSIUnloadPlugin( PluginRegistrar& in_reg ){ CValue ptrValue = in_reg.GetUserData(); PlugData* ptr_pData = (PlugData*)(CValue::siPtrType)ptrValue; delete ptr_pData; } I get this heap error: http://i.imgur.com/FLzg6EV.png "__plastBlock == pHead" I tried the same code in Cmd_Term() callback. But it has no difference.
Re: Pass struct from Tool to Operator
If i use Plugin's UserData i have a problem with releaseing memory. struct myStruct{ XSI::CLongArray polyData; XSI::CValueArray edgeSegmentsArray; } SICALLBACK XSILoadPlugin( PluginRegistrar& in_reg ){ PlugData * pDataPtr = new PlugData ; CValue ptrValue = (CValue::siPtrType) pDataPtr; in_reg.PutUserData(ptrValue); } SICALLBACK myOperator_Update( CRef& in_ctxt ){ OperatorContext ctxt( in_ctxt ); CValue userData(ctxt.GetUserData()); update_func(ctxt); return CStatus::OK; } 2015-12-10 20:47 GMT+03:00 Steven Caron : > Could you use the Plugin's UserData to pass the struct between plugin > types? I never heard of using the context from one plugin type being used > in another plugin type. > > http://bit.ly/1NILLt7 > > On Thu, Dec 10, 2015 at 9:01 AM, Andruha Prostrelov > wrote: > >> I am looking for the way to pass a "struct" from Tool Class to the >> CustomOperator_Update() callback. >> I saw two approaches to this in SDK. First one should work via UserData >> attached to ctxt. You store in this >> data C++ pointer to allocated memory with your struct. Second one is to >> create Property and store this pointer in >> property. I prefer do not create additional Property, so i tried to add >> UserData to ctxt. >> But i don't quite sure that i make it right. >> I tried this piece of code ... >> >> struct myStruct{ >>XSI::CLongArray polyData; >>XSI::CValueArray edgeSegmentsArray; >> } >> SICALLBACK myCmd_Execute( CRef& in_ctxt ){ >> PlugData pData; >> PlugData * pDataPtr; >> pDataPtr = &pData; >> ctxt.PutUserData(XSI::CValue(pDataPtr)); >> } >> SICALLBACK myOperator_Update( CRef& in_ctxt ){ >>OperatorContext ctxt( in_ctxt ); >>CValue userData(ctxt.GetUserData()); >>update_func(ctxt); >>return CStatus::OK; >> } >> >> ... but in Update callback i didn't get pointer back. >> >> If someone has already faced a similar problem maybe you can share some >> advices. >> Or maybe there is a way to pass struct without UserData or Custom >> Property. >> > >
Re: Pass struct from Tool to Operator
Could you use the Plugin's UserData to pass the struct between plugin types? I never heard of using the context from one plugin type being used in another plugin type. http://bit.ly/1NILLt7 On Thu, Dec 10, 2015 at 9:01 AM, Andruha Prostrelov wrote: > I am looking for the way to pass a "struct" from Tool Class to the > CustomOperator_Update() callback. > I saw two approaches to this in SDK. First one should work via UserData > attached to ctxt. You store in this > data C++ pointer to allocated memory with your struct. Second one is to > create Property and store this pointer in > property. I prefer do not create additional Property, so i tried to add > UserData to ctxt. > But i don't quite sure that i make it right. > I tried this piece of code ... > > struct myStruct{ >XSI::CLongArray polyData; >XSI::CValueArray edgeSegmentsArray; > } > SICALLBACK myCmd_Execute( CRef& in_ctxt ){ > PlugData pData; > PlugData * pDataPtr; > pDataPtr = &pData; > ctxt.PutUserData(XSI::CValue(pDataPtr)); > } > SICALLBACK myOperator_Update( CRef& in_ctxt ){ >OperatorContext ctxt( in_ctxt ); >CValue userData(ctxt.GetUserData()); >update_func(ctxt); >return CStatus::OK; > } > > ... but in Update callback i didn't get pointer back. > > If someone has already faced a similar problem maybe you can share some > advices. > Or maybe there is a way to pass struct without UserData or Custom Property. >
Re: Pass struct from Tool to Operator
You have allocated pData on stack, it gets destroyed right after the allocation scope exit ( after the PutUserData call ), use dynamic allocation instead
Pass struct from Tool to Operator
I am looking for the way to pass a "struct" from Tool Class to the CustomOperator_Update() callback. I saw two approaches to this in SDK. First one should work via UserData attached to ctxt. You store in this data C++ pointer to allocated memory with your struct. Second one is to create Property and store this pointer in property. I prefer do not create additional Property, so i tried to add UserData to ctxt. But i don't quite sure that i make it right. I tried this piece of code ... struct myStruct{ XSI::CLongArray polyData; XSI::CValueArray edgeSegmentsArray; } SICALLBACK myCmd_Execute( CRef& in_ctxt ){ PlugData pData; PlugData * pDataPtr; pDataPtr = &pData; ctxt.PutUserData(XSI::CValue(pDataPtr)); } SICALLBACK myOperator_Update( CRef& in_ctxt ){ OperatorContext ctxt( in_ctxt ); CValue userData(ctxt.GetUserData()); update_func(ctxt); return CStatus::OK; } ... but in Update callback i didn't get pointer back. If someone has already faced a similar problem maybe you can share some advices. Or maybe there is a way to pass struct without UserData or Custom Property.