Plugin multiple inputs & outputs

benoitlahoz's picture

Hi !

I'm trying to write my first plugin, and I have a trouble with multiple inputs and outputs.

They never appear in the plugin, though XCode doesn't output an error. QC only take one input and one output.

I studied many examples in the sources I found here, but well...

Sorry for the stupid question. Does anybody have an idea on what's happening ?

vade's picture
Re: Plugin multiple inputs & outputs

Are you :

a) making a @property named inputfoo or outputfoo in your interface file?

b) are you using @dynamic for the input and output ports you declared above in your implementation file?

c) without source, its impossible to know.

benoitlahoz's picture
Re: Plugin multiple inputs & outputs

Yes I'm doing all this...

Here is the code of a buggy-newbie-plugin... It's not working yet, that's why I want to output a "debug" string.

PreviewAttachmentSize
Buggy_plugin_to_come.zip2.42 MB

dust's picture
Re: Plugin multiple inputs & outputs

your issue is you need to prepend input or output to your port variables. like

@property(assign) NSString * outputDebug;

also i found when first starting that sometimes i would screw up things in

+ (NSDictionary*) attributesForPropertyPortWithKey:(NSString*)key
{
   /*
   Specify the optional attributes for property based ports (QCPortAttributeNameKey, QCPortAttributeDefaultValueKey...).
   */
 
   if ([key isEqualToString:@"inputStructure"])
      return [NSDictionary dictionaryWithObjectsAndKeys:
            @"Mesh", QCPortAttributeNameKey,
            nil];
 
   if ([key isEqualToString:@"outputStructure"])
      return [NSDictionary dictionaryWithObjectsAndKeys:
            @"Mesh", QCPortAttributeNameKey,
            nil];
 
   if ([key isEqualToString:@"debug"])
      return [NSDictionary dictionaryWithObjectsAndKeys:
            @"Debug", QCPortAttributeNameKey,
            nil];
 
   return nil;
}

remember these are optional attributes. that yes make your plugin look tidy but are not necessary. so if a port isn't showing up and you have declared your input/ouputVar with @property and @dynamic then the next place to hunt the problem will be in you optional attributes. i actually prefer not to use them personally. if you don't use them then all your io's look like "inputVar" or "outputVar". i'm not saying don't use them.... just saying i don't all the time. it seems most people do however so for the sake of uniformity is probably good practice to set your attributes and keys etc..

you can also override property ports like this to define a specific order in your interface like this. just add this method after your declare attributes.

+ (NSArray*) sortedPropertyPortKeys
{
    return [NSArray arrayWithObjects:@"inputModelPath",
 
            @"inputMesh",@"outputMesh",@"outputDebug",nil];
}   

benoitlahoz's picture
Re: Plugin multiple inputs & outputs

Once again, thank you Dust !

I can't really understand right now why your code is running so well and mine was bugging so deep :-) but I'll look at it.

As you can see in the code, my way to sort coordinates isn't really working. Once I have debugged the thing I'm only reversing the sorting : by X instead of by Y.

I'm hanging with the NSSortDescriptor right now... Ooops... How to sort without key but with indices ? Hum...

Cheers !

[edit : for newbies like me, sorting numerically :

[myUnsortedArray sortedArrayUsingSelector:@selector(compare:)];

[edit2 : while trying to make an input port, I have the same trouble... Argh... Don't know what I am doing wrong :

@property double distanceThreshold;

gtoledo3's picture
Re: Plugin multiple inputs & outputs

I didn't really look through the code line per line, b/c I have a headache...

I see some stuff where it it looked like you're trying to look for an object at index 4... that would seemingly indicate that you're at some point making a 5 line structure, which may be a typo/problematic. That can totally work depending on what else is going on, but you probably don't want to be actually outputting it if you intend this to work with typical QC vertex structure type stuff. I didn't look enough to see why you do that.

An aesthetic suggestion (I understand this is just in progress); I would advise against naming inputs and outputs mesh, if they're really working on a QCStructure. Mesh Vertices, Vertices, Structure, etc., would all be clearer choices. Because, one would tend to hook up a mesh cable, and then go "why doesn't this work?" If you've named it structure/vertices/mesh vertices, it should be much clearer to a user.

If I had a port that took a structure of colors, I wouldn't name it "Color", because that indicates a Color port. Colors, maybe. Color Structure, for sure. RGBA structure, yeah.

If you're using this to order structure, there a bunch of things that would be useful for besides mesh, so keep that in mind as well. inputStructure, outputStructure, may be really appropriate for an ordering algorithm.

Look at the built in QC patches that sort structures in ascending or descending order. They can bog down with big structures, but they do work. That would be the thing to beat.

You could do a search on types of ordering algorithms and accuracy vs. speed. That would probably be a great benefit to you before really plowing into this. I did a search on this a few months back, and returned some really interesting reading.

Go through the ADC "programming patches for QC" stuff, starting with the basic Consumer, then looking at the others. That's going to explain how/why about these kind of questions you're asking.

Are you trying to be able to sort by any given lane in the structure (I'm not clear on this), or be vector length, or by all (multiple modes)?

(You don't have to print your errors to a port, you can print them to Console..I've never really thought of printing errors to a port/never seen it done. It might make sense, but somehow it seems like a bad idea...idk).

dust's picture
Re: Plugin multiple inputs & outputs

@property double inputDistanceThreshold;

benoitlahoz's picture
Re: Plugin multiple inputs & outputs

Thanks to you 2.

I'm beginning to understand... Wooofff...

dust's picture
Re: Plugin multiple inputs & outputs

ok sorting is a bit complicated in cocoa as there are a ton of collections programming things you can do.

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/C...

the easy way to use sorting descriptors is to use a nsdictionary. basically you would want to make an array and add to your dictionary key value pairs to the array. there are various ways to do this.

use something like this to add each important index you want to a sorting array. the sorting array is an array of dictionaries.

NSString * x   = @"xpos";
NSString * y  = @"ypos";
NSString * z = @"zpos";
NSString * w  = @"wpos";
 
NSMutableArray * array = [NSMutableArray array];
 
NSDictionary * dict;
 
dict = [NSDictionary dictionaryWithObjectsAndKeys:
          [tempI objectAtIndex:0], x,  [tempI objectAtIndex:1], y,
             [tempI objectAtIndex:2], z,
             [tempI objectAtIndex:3], w, nil];
[array addObject:dict];

now you want to sort using your descriptors. so this will sort your values for ascending based on the values stored in the z component or key of your dictionary.

NSSortDescriptor * zOrder =
    [[[NSSortDescriptor alloc] initWithKey:z
                                 ascending:YES] autorelease];
 
id obj;
NSEnumerator * enumerator = [array objectEnumerator];
while ((obj = [enumerator nextObject])) NSLog(@"%@", obj);
 
NSArray * descriptors =
    [NSArray arrayWithObjects:zOrder, nil];
NSArray * sortedArray =
    [array sortedArrayUsingDescriptors:descriptors];
 
NSLog(@"\nSorted ...");
 
enumerator = [sortedArray objectEnumerator];
while ((obj = [enumerator nextObject])) NSLog(@"%@", obj);

this all clearly would need to be optimized for use in a plugin and it assumes your sorting by NSNumber. you would do something like this if you want to sort case sensitive strings.

NSSortDescriptor *myDescriptor =
    [[[NSSortDescriptor alloc]
        initWithKey:z
          ascending:YES
           selector:@selector(localizedCaseInsensitiveCompare:)] autorelease];