How to draw your own patches in the Composition Editor

smokris's picture

example of draw-your-own patches in Composition EditorWe can override the patch drawing method, using the infamous poseAsClass technique.

  1. Start with a new project, using at least v0.3 of the Xcode Template
  2. Create a new class (right-click on the project icon, click "Add" and then "New File...". Select "Objective-C class". Name it something like "MyPatchActor" (where "MyPatch" is the name of your patch).
  3. Paste the following into the .h file:
    #import <QCPatchActor.h>
     
    @interface MyPatchActor : QCPatchActor
    - (void)drawNode:(QCPatch *)node bounds:(struct _NSRect)rect view:(QCPatchView *)view;
    @end
  4. Paste the following into the .m file:
    #import "MyPatchActor.h"
    #import "MyPatch.h"
     
    @implementation MyPatchActor
    - (void)drawNode:(QCPatch *)node bounds:(struct _NSRect)rect view:(QCPatchView *)view
    {
       [super drawNode:node bounds:rect view:view];
     
       if( [node isMemberOfClass:[MyPatch class]] )
       {
          // do your own Quartz drawing here
       }
    }
    @end
    and modify as desired.
  5. Add the poseAsClass call to MyPatchPrincipal.h, so it ends up looking like this:
    #import "MyPrincipal.h"
    #import "MyPatchActor.h"
    #import "MyPatch.h"
     
    @implementation MyPatchPlugin
    + (void)registerNodesWithManager:(GFNodeManager*)manager
    {
       [MyPatchActor poseAsClass:[QCPatchActor class]];
     
       [manager registerNodeWithClass:[MyPatch class]];
    }
    @end
  6. Enjoy.

cwright's picture
poseAs isn't free

Careful with excessive use of this method. poseAs essentially inserts your class into the message chain, making it a bit longer with each new class. While it's only a class compare, having hundreds of patches successively poseAs QCPatchActor might increase load noticeably. Some scalability testing might be in order :).

smokris's picture
yes, but negligible, i think.

Yes. I'm guessing the typical user won't have more than a couple dozen custom patches installed (few of which will use the poseAsClass trick)... and a few hundred additional "if" statements / objective c messages per second probably won't be noticeable.

cwright's picture
clean form

Discovered a poseAs-free way to do this, using one of QCPatch's methods, -(QCPatchActor)nodeActorForView:(QCPatchView)view

Just return a MyPatchActor instance from this method, and it works the same way.

Each patch should declare a global patch actor in their .h file, and instantiate only one patch actor (each patch thus shares its actor with identical patches).

example method:

- (id)nodeActorForView:(id)fp8
{
        if(actor == nil)
        {
                actor = [testPatchActor new];
        }
        return actor;
}