-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathDTArrayPatch.m
144 lines (108 loc) · 2.98 KB
/
DTArrayPatch.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#import "DTArrayPatch.h"
static bool DTArrayPortIsSettingState(void)
{
// @@@ surely there's a better way to detect this...
for(NSString *frame in [NSThread callStackSymbols])
if(
[frame rangeOfString:@"-[QCPatch(Override) setState:]"].location != NSNotFound // open composition
|| [frame rangeOfString:@"-[GFGraph(Private) _loadState:]"].location != NSNotFound // paste from clipboard
)
return YES;
return NO;
}
@interface DTArrayPort : QCVirtualPort
@end
@implementation DTArrayPort
- (void)_setConnectedPort:(QCPort *)port
{
// only add ports if the connection is happening live in the editor (not when restoring composition state)
if(!DTArrayPortIsSettingState())
if(port)
[(DTArrayPatch *)[self parentPatch] addPort];
else
[(DTArrayPatch *)[self parentPatch] trimPorts];
[super _setConnectedPort:port];
}
- (void)_setProxyPort:(QCPort *)port
{
// only add ports if the connection is happening live in the editor (not when restoring composition state)
if(!DTArrayPortIsSettingState())
if(port)
[(DTArrayPatch *)[self parentPatch] addPort];
else
[(DTArrayPatch *)[self parentPatch] trimPorts];
[super _setProxyPort:port];
}
@end
@implementation DTArrayPatch
- (void)addPort
{
[portArray addObject:
[self createInputWithPortClass:[DTArrayPort class] forKey:[NSString stringWithFormat:@"%i",[portArray count]] attributes:nil]
];
}
// remove unused ports from the end, leaving just one spare port
- (void)trimPorts
{
while(1)
{
NSString *k = [NSString stringWithFormat:@"%i",[portArray count]-1];
QCPort *p = (QCPort *)[self portForPath:k];
if([p connectedPort] || [p proxyPort])
break;
[self deleteInputForKey:k];
[portArray removeLastObject];
}
[self addPort];
}
+(BOOL)isSafe
{
return YES;
}
+(BOOL)allowsSubpatchesWithIdentifier:(id)identifier
{
return NO;
}
-(id)initWithIdentifier:(id)identifier
{
if(self = [super initWithIdentifier:identifier])
{
[[self userInfo] setObject:@"Array" forKey:@"name"];
portArray = [[NSMutableArray alloc] init];
[self addPort];
}
return self;
}
- (void)dealloc
{
[portArray release];
[super dealloc];
}
-(BOOL)execute:(QCOpenGLContext*)context time:(double)time arguments:(NSDictionary*)arguments
{
QCStructure *s = [[QCStructure alloc] init];
GFList *l = [s _list];
for(NSUInteger i=0;i<[[self inputPorts] count]-1;++i)
{
id v = [[[self inputPorts] objectAtIndex:i] value];
[l insertObject:v?v:[NSArray array] atIndex:i forKey:nil];
}
[outputArray setStructureValue:s];
[s release];
return YES;
}
- (NSDictionary*)state
{
NSMutableDictionary *stateDict = [[NSMutableDictionary alloc] initWithCapacity:2];
[stateDict addEntriesFromDictionary:[super state]];
[stateDict setObject:[NSNumber numberWithInt:[portArray count]-1] forKey:@"arrayCount"];
[stateDict autorelease];
return stateDict;
}
- (BOOL)setState:(NSDictionary*)state
{
for(NSUInteger i=[portArray count];i<=[[state objectForKey:@"arrayCount"] intValue];++i)
[self addPort];
return [super setState:state];
}
@end