Recent commentsRecent topics
Recent wiki edits
|
QCRenderer and NSData Anyone familiar with QCRenderer will know of its weakness when it comes to initialization. Its only init method uses an NSString which is interpreted as a file name, which is loaded. If you want to provide data from some other route, you have no choice but to save your compositions in plain text on the harddrive. Normally, I'm all for open data, and I suppose the above enforces that. But there are times where you just want your compositions to be private. A few days ago, a friend "dared" me to overcome this limitation. And now, after quite a bit of reverse engineering, here I am, with a (very beta) solution. [Note: this only works for 10.4 versions of Quartz Composer. 10.5 changed the location of objects inside, so using this will cause cool errors when the QC runtime tries to invoke methods on the wrong objects]
typedef struct { QCPatch *patch; QCOpenGLContext *context; NSDictionary *args; void *reserved[3]; } KinemePrivateQCRendererStruct; extern NSDictionary* QCCompositionFromData(NSData*data); extern id QCPatchFromComposition(id composition, int something); extern id QCInfoFromComposition(id composition); @interface QCRenderer (KinemeData) - (QCRenderer) initWithOpenGLContext: (NSOpenGLContext)context pixelFormat: (NSOpenGLPixelFormat)format data: (NSData)data; @end @implementation QCRenderer (KinemeData)
// This is intended to behave exactly like
// initWith... file:, but using NSData instead
- (QCRenderer) initWithOpenGLContext: (NSOpenGLContext)context
pixelFormat: (NSOpenGLPixelFormat)format
data: (NSData)data
{
} @end This chunk of code creates a new method for QCRenderer, which eats an NSData object for init instead of an NSString for a file. You might need to define other classes before you use it. I can't promise that it works, but it works within QC itself when plugged into the ImageWithComposition patch, at least for me. Have a lot of fun :)
|
This is now a supported operation in QC Leopard. You'll do a [QCComposition compositionWithData:(NSData)myData], and then [QCRenderer initWith... composition:myComposition]; Pretty cool. Too bad I didn't read the release notes closely towards the end, or it would have saved me all the time it took to track this down by disassembling :) *oh well
(Later Edit:)
Ok, so the loading by composition stuff, according to the documentation, is not supposed to allow 'consumer patches' in the patch when loading like this. I've not seen any problems doing this though, but I might be cheating a bit :)
The code to do it is non-obvious (or at least, to me it wasn't), so here's what I came up with over the weekend to pull it off in Leopard
QCComposition qcc = [QCComposition compositionWithData:data]; if(qcc) { // I honestly have no idea what QCGetIndexedColorSpace(7) is for // I just know that QC does it // when loading from a file, following this exact pattern. [self initWithCGLContext: [context CGLContextObj] pixelFormat: [format CGLPixelFormatObj] colorSpace: (struct CGColorSpace)QCGetIndexedColorSpace(7) composition: qcc];} return nil;
This is straight from the initWith... file: method, so it should work identically. The only hairy part is the QCGetIndexedColorSpace guy... shrugs more exploring to do I guess :)