OSDN Git Service

first commit
[eliscolors/main.git] / ElisLayer.m
1 //
2 //  ElisLayer.m
3 //  Elis Colors
4 //
5 //  Created by 柳 on 09/09/12.
6 //  Copyright 2009 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "ElisLayer.h"
10
11 static float convertQTTimeToSecond(QTTime t)
12 {
13     return (float)t.timeValue/t.timeScale;
14 }
15
16 @implementation ElisLayer
17
18 @synthesize media;
19
20 - (id)init
21 {
22     self.media = nil;
23     position.x = 0;
24     position.y = 0;
25     offset = QTZeroTime;
26     effects = [[NSMutableArray alloc] init];
27     pxKeyframe = [[ElisKeyframe alloc] init];
28     pyKeyframe = [[ElisKeyframe alloc] init];
29     [pxKeyframe setValueForTime:0.0 time:QTZeroTime];
30     [pyKeyframe setValueForTime:0.0 time:QTZeroTime];
31     
32     [self addEffect:@"CIOpacity"]; //デフォルトで透過度フィルタと
33 //    [self addEffect:@"CILanczosScaleTransform"]; // 拡大縮小フィルタと
34     [self addEffect:@"CIAffineTransform"]; // アフィン変換フィルタはつけておく。
35     
36   
37     return self;
38 }
39
40 - (void)setAlayer:(CALayer *)layer
41 {
42     alayer = layer;
43     
44     [layer setValue:self forKey:@"ElisLayer"];
45     
46     // layer.frameをバインド。
47     [layer addObserver:self 
48             forKeyPath:@"frame" 
49                options:(NSKeyValueObservingOptionNew) 
50                context:NULL];
51 }
52
53 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
54 {
55     [self changeMapping];
56 }
57
58 - (void)addEffect:(NSString*)name
59 {
60     [effects addObject:[[ElisEffect alloc] initWithName:name]];
61 }
62
63 - (void)changeMapping
64 {
65     CGRect frame = alayer.frame;
66     QTTime begin = QTMakeTime(frame.origin.x*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
67     QTTime d = QTMakeTime(frame.size.width*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
68     
69     trackNumber = floor(frame.origin.y/51.0);
70     mapping = QTMakeTimeRange(begin, d);
71     
72     // mappingとtrackNumberを変化させる。
73 }
74
75 - (void)changeOffset:(float)df
76 {
77     QTTime new_offset = QTTimeIncrement(offset, QTMakeTime(df*DEFAULT_FPS/timeLineScale, DEFAULT_FPS));
78     
79     offset = new_offset;
80 }
81
82 - (BOOL)canChangeMapping:(CGRect)rect
83 {
84     QTTime duration = [media duration];
85     QTTime wantDuration = QTMakeTime(rect.size.width*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
86     float d = convertQTTimeToSecond(duration) - convertQTTimeToSecond(offset);
87     float wd = convertQTTimeToSecond(wantDuration);
88     
89     return 0.5 <= wd && wd <= d;
90 }
91
92 - (BOOL)canChangeOffset:(float)df
93 {
94     float now_offset = convertQTTimeToSecond(offset);
95     float duration = convertQTTimeToSecond([media duration]);
96     df /= timeLineScale;
97     
98     return 0.0 <= df + now_offset && df + now_offset <= duration;
99 }
100
101 - (BOOL)isInclude:(QTTime)time
102 {
103     float t = convertQTTimeToSecond(time);
104     float begin = convertQTTimeToSecond(mapping.time);
105     return begin <= t && t <= begin + convertQTTimeToSecond(mapping.duration);
106 //    return QTTimeInTimeRange(time, mapping); // これだとマルチスレッドにできなくね?
107 }
108
109 - (int)trackNumber
110 {
111     return trackNumber;
112 }
113
114 - (void)setPositionX:(float)x forTime:(QTTime)time
115 {
116     if(recording)
117         [pxKeyframe setValueForTime:x time:time];
118     else
119         [pxKeyframe setValueForTime:x time:QTZeroTime];
120 }
121
122 - (void)setPositionY:(float)y forTime:(QTTime)time
123 {
124     if(recording)
125         [pyKeyframe setValueForTime:y time:time];
126     else 
127         [pyKeyframe setValueForTime:y time:QTZeroTime];
128 }
129
130 - (CIImage*)getEffectedImage:(CVTimeStamp*)timeStamp forTime:(QTTime)time
131 {
132     QTTime innerTime = QTTimeDecrement(time, mapping.time);
133     CIImage* image = [media getFrameForTime:timeStamp];
134     if(image == nil) return nil;
135     
136     return [self applyEffects:image forTime:QTTimeIncrement(innerTime, offset)];
137 }
138
139 - (CIImage*)getEffectedImageWithoutStamp:(QTTime)time
140 {
141     QTTime innerTime = QTTimeDecrement(time, mapping.time);
142     CIImage* image = [media getFrameForQTTime:QTTimeIncrement(innerTime, offset)];
143     if(image == nil) return nil;
144     
145     return [self applyEffects:image forTime:QTTimeIncrement(innerTime, offset)];    
146 }
147
148 - (CIImage*)applyEffects:(CIImage*)image forTime:(QTTime)time
149 {
150     int i, size = [effects count];
151     ElisEffect* ef;
152     
153     for(i = 0; i < size; i++){
154         ef = [effects objectAtIndex:i];
155         [ef setInputImage:image];
156         image = [ef getImage:time];
157     }
158     
159     return image;
160 }    
161
162 - (NSPoint)getPositionForTime:(QTTime)time
163 {
164     float x = [pxKeyframe getValueForTime:time];
165     float y = [pyKeyframe getValueForTime:time];
166     
167     return NSMakePoint(x, y);
168 }
169
170 - (void)play
171 {
172     [media play];
173 }
174
175 - (void)stop
176 {
177     [media stop];
178 }
179
180 - (void)releaseContext
181 {
182     [media releaseContext];
183 }
184
185 - (QTTimeRange)mapping
186 {
187     return mapping;
188 }
189
190 - (void)seek:(QTTime)time
191 {
192     if([self isInclude:time]){
193         QTTime innerTime = QTTimeDecrement(time, mapping.time); // レイヤー内相対時間へ変換
194         [media setCurrentTime:QTTimeIncrement(innerTime, offset)];
195     } else {
196         [media setCurrentTime:offset];
197     }
198 }
199
200
201 // for Property Table
202 - (void)createPropertyTableDataSource:(NSMutableArray*)t_effects
203                              property:(NSMutableArray*)t_propertyNames
204                                 value:(NSMutableArray*)t_valueNames
205 {
206     NSMutableDictionary* params;
207     NSArray* arr;
208     NSString* paramName, *effectName;
209     NSDictionary* dict;
210     
211     [t_propertyNames addObject:@"Position X"];
212     [t_effects addObject:self];
213     [t_valueNames addObject:@""];
214     [t_propertyNames addObject:@"Position Y"];
215     [t_effects addObject:self];
216     [t_valueNames addObject:@""];
217     
218     int i, size = [effects count];
219     for(i = 0; i < size; i++){
220         params = [[effects objectAtIndex:i] getParamDictionary];
221         arr = [params allKeys];
222         arr = [arr sortedArrayUsingSelector:@selector(compare:)];
223         effectName = [[effects objectAtIndex:i] getName];
224         for(paramName in arr){
225             [t_propertyNames addObject:[NSString stringWithFormat:@"%@ %@", effectName, [paramName substringFromIndex:5]]];
226             [t_effects addObject:[effects objectAtIndex:i]];
227             [t_valueNames addObject:paramName];
228         }
229     }
230 }
231
232 - (QTTime)convertToInnnerTime:(QTTime)globalTime
233 {
234     return QTTimeIncrement(QTTimeDecrement(globalTime, mapping.time), offset);
235 }
236
237 - (QTTime)plusOffsetTime:(QTTime)time
238 {
239     return QTTimeIncrement(time, offset);
240 }
241
242 - (void)finalize
243 {
244     [alayer removeObserver:self forKeyPath:@"frame"];
245     [super finalize];
246 }
247
248 - (void)removePositionXKeyframe
249 {
250     pxKeyframe = [[ElisKeyframe alloc] init];
251     [pxKeyframe setValueForTime:0.0 time:QTZeroTime];
252 }
253
254 - (void)removePositionYKerframe
255 {
256     pyKeyframe = [[ElisKeyframe alloc] init];
257     [pyKeyframe setValueForTime:0.0 time:QTZeroTime];
258 }
259
260 - (void)removeEffect:(ElisEffect*)ef
261 {
262     [effects removeObject:ef];
263 }
264
265 @end