3 Replies Latest reply on Sep 30, 2016 12:55 PM by btempleton1982

    Recursive Loop PluginGroupUpdate

    btempleton1982 Level 2

      I've encountered an issue with my plugin group art where my PluginGroupUpdate function gets called over and over until memory runs out.

       

      I can cause it by duplicating an artboard that contains my plugin group art. On the first duplication, the PluginGroupUpdate function gets called about 14 times then finishes execution. The second duplication goes about 600 times, then finishes. The third duplication leads to a crash due to running out of memory.

       

      I've located what I think is the call that triggers each loop of the function. It seems to be caused by AIArtSuite->GetArtBounds(...). I wouldn't have thought that function would trigger a PluginGroupUpdate call, but that's where my code is right before each recursion.

       

      It seems like I'm supposed to do something to let Illustrator know the updates have been done, but I can't quite figure out where it's supposed to go. Or maybe I'm trying the wrong thing.

       

      I've read through the docs, and found a couple things that looked promising.

       

      Returning kMarkValidPluginGroupReply seemed like it might be part of the solution, but it's not working. That's expected, since by the time that code is returned, the loop is already recurring.

       

      I see the function MarkPluginArtClean(...). In the docs it says to "Use this function in an external notification handler, after updating the result group, to prevent the redundant update." I'm not quite sure where that would be. I'm guessing in response to kSelectorAINotifyEdits?

        • 1. Re: Recursive Loop PluginGroupUpdate
          LeoTaro Level 4

          I haven't used PluginArt much, but the LiveDropShadow sample has a PluginGroupUpdate function. Have you tried building this and seeing what happens if you do the same thing with its plugin art. Though having a quick look at its PluginGroupUpdate function, it seems to destroy and recreate the plugin art on each call?

          1 person found this helpful
          • 2. Re: Recursive Loop PluginGroupUpdate
            btempleton1982 Level 2

            There seems to be a series of calls to PluginGroupNotify(...).

             

            Digging more through the docs, it looks like you need to check the passed in AIPluginGroupMessage, specifically the time and code properties. Change your return code from that function depending on the behavior you're looking for. The allowable return codes are:

             

            kRefusePluginGroupReply

            kWantsAfterMsgPluginGroupReply

            kMarkValidPluginGroupReply

            kDontCarePluginGroupReply

            kDestroyPluginGroupReply

             

            I haven't quite figured out which codes I want to return in response to which messages, but I have a feeling this is the right track.

            • 3. Re: Recursive Loop PluginGroupUpdate
              btempleton1982 Level 2

              You are correct that the LiveDropShadow sample seems to trash and recreate the plugin art each time. I've kind of arrived at the same solution, but slightly different for my case.

               

              I've gotten around my recursive loop problem by doing the following:

               

              ASErr MyPlugin::PluginGroupNotify(AIPluginGroupMessage* message)

              {

                  if (strcmp( message->code, kAttachOperationCode ) == 0 && strcmp( message->time, kCheckOperationTime ) == 0)

                  {

                      return kNoErr;

                  }

                  if (strcmp( message->code, kAttachOperationCode ) == 0 && strcmp( message->time, kBeforeOperationTime ) == 0)

                  {

                      return kNoErr;

                  }

                  if (strcmp( message->code, kAttachOperationCode ) == 0 && strcmp( message->time, kAfterOperationTime ) == 0)

                  {

                      return kMarkValidPluginGroupReply;

                  }

                  return kUnhandledMsgErr;

              }

               

              You can change the return codes to create the behavior you need.

               

              kCheckOperationTime fires when you AIPluginGroupSuite->UseAIPluginGroup(...). You can return kRefusePluginGroupReply here to cancel the whole thing I think.

               

              kBeforeOperationTime fires after kCheckOperationTime. Presumably you'd store some kind of information here if you want to compare it to kAfterOperationTime.

               

              kAfterOperationTime fires after kBeforeOperationTime. AIPluginGroupSuite->UseAIPluginGroup(...) returns after this.

               

              This is speculation from what I've observed through testing various different ways of handling things. PluginGroupUpdate(...) seems to be related to the Silent/Dirty state of the plugin art. That seems to be toggled based on return codes from Notify, or by using the suite functions. As it is, my case doesn't seem to need to worry about it.