// // ElisTimeLineController.m // Elis Colors // // Created by 柳 on 09/09/12. // Copyright 2009 __MyCompanyName__. All rights reserved. // #import "ElisTimeLineController.h" @implementation ElisTimeLineController - (void)awakeFromNib { NSLog(@"Building TimeLine ..."); CGImageRef bar, trblack; NSBundle *bundle = [NSBundle mainBundle]; bar = [[NSBitmapImageRep imageRepWithContentsOfFile:[bundle pathForResource:@"white" ofType:@"jpg"]] CGImage]; trblack = [[NSBitmapImageRep imageRepWithContentsOfFile:[bundle pathForResource:@"trackgray" ofType:@"jpg"]] CGImage]; timeLineScale = 10.0; // 10倍表示 rootLayer = [CALayer layer]; timeLine = [CALayer layer]; playbackBar = [CALayer layer]; rootLayer.backgroundColor = CGColorCreateGenericGray(0, 0.4f); playbackBar.contents = (id)bar; playbackBar.frame = CGRectMake(0, 0, 1, 51*TRACK_MAX); int i; CALayer* track; for(i = 0; i < TRACK_MAX; i++){ track = [CALayer layer]; track.frame = CGRectMake(0, 51*i+1, [_timeLineView frame].size.width, 50); track.contents = (id)trblack; track.opacity = 0.35; track.autoresizingMask = kCALayerWidthSizable; [timeLine addSublayer:track]; } timeLine.autoresizingMask = kCALayerWidthSizable; NSRect r = [_timeLineView frame]; [_timeLineView setFrame:NSMakeRect(0, 0, 10*60*timeLineScale, 51*TRACK_MAX)]; rootLayer.frame = *(CGRect*)&r; rootLayer.masksToBounds = YES; [rootLayer addSublayer:timeLine]; [rootLayer addSublayer:playbackBar]; [_timeLineView setLayer:rootLayer]; [_timeLineView setWantsLayer:YES]; draggingLayer = nil; clickedPosition.x = -1; dragging = NO; _layerFactory = [[ElisAnimationLayerFactory alloc] init]; } - (void)movePlaybackBar:(float)p { // 自動スクロールはうまくできないので無効にしてある。 // 再生中にフリーズするよ! よ! // NSRect r = [_timeLineView visibleRect]; // if(p > r.origin.x){ // r.origin.x += 2; // [_timeLineView scrollPoint:r.origin]; // } [CATransaction begin]; [CATransaction setValue:[NSNumber numberWithFloat:0.0f] forKey:kCATransactionAnimationDuration]; CGPoint po = playbackBar.position; po.x = p; playbackBar.position = po; [CATransaction commit]; } - (void)addMedia:(NSString*)path { CALayer* newLayer = [_mainController createNewLayer:path]; if(draggingLayer) draggingLayer.opacity = 0.75; draggingLayer = newLayer; [timeLine addSublayer:newLayer]; } - (void)dragging:(NSPoint)point { if(draggingLayer == nil) return; if(stretch == STRETCH_RIGHT){ CGRect rect = draggingLayer.frame; float dx = point.x - rect.origin.x - rect.size.width; rect.size.width += dx; if([[draggingLayer valueForKey:@"ElisLayer"] canChangeMapping:rect]){ [self changeLayerFrame:draggingLayer rect:rect]; } return; } else if (stretch == STRETCH_LEFT){ CGRect rect = draggingLayer.frame; float dx = point.x - rect.origin.x; if([[draggingLayer valueForKey:@"ElisLayer"] canChangeOffset:dx]){ [[draggingLayer valueForKey:@"ElisLayer"] changeOffset:dx]; rect.size.width -= dx; [self changeLayerFrame:draggingLayer rect:rect]; [_mainController refresh]; } return; } if(dragging == NO) dragging = YES; if(clickedPosition.x == -1){ point.x -= 25; point.y -= 25; } else { float dx = clickedPosition.x - point.x; float dy = clickedPosition.y - point.y; point = NSMakePoint(clickedLayerPosition.x - dx, clickedLayerPosition.y - dy); } [self changeLayerPosition:draggingLayer position:point]; } - (void)draggingDone { if(draggingLayer == nil) return; if(dragging){ CGPoint point = draggingLayer.position; point.y = floor(point.y/51.0) * 51 + 1 + 25; // +25ってどこから出てきた? draggingLayer.position = point; draggingLayer.opacity = 0.75; draggingLayer = nil; clickedPosition.x = -1; dragging = NO; // [_timeLineView setCursorRect:NSZeroRect]; // これなに? } [_timeLineView setCursorRect:draggingLayer.frame]; stretch = 0; } - (void)changeLayerPosition:(CALayer*)layer position:(NSPoint)point { [CATransaction begin]; [CATransaction setValue:[NSNumber numberWithFloat:0.0f] forKey:kCATransactionAnimationDuration]; CGRect r = layer.frame; r.origin.x = point.x; r.origin.y = point.y; layer.frame = r; // KVOでCALayerに対応してElisLayerも変化 [CATransaction commit]; [_mainController refresh]; // ElisLayerの構造が変わったので再描画を要請。ループしないよう注意。 } - (void)changeLayerFrame:(CALayer*)layer rect:(CGRect)rect { [CATransaction begin]; [CATransaction setValue:[NSNumber numberWithFloat:0.0f] forKey:kCATransactionAnimationDuration]; layer.frame = rect; [CATransaction commit]; [_mainController refresh]; } - (IBAction)add:(id)sender { [self addMedia:@"/Users/yanagi/Desktop/59926_2_m1_1.mp4"]; NSValue* v = [draggingLayer valueForKey:@"frame"]; NSRect r = [v rectValue]; r.origin.x = 0; // [draggingLayer willChangeValueForKey:@"frame"]; [draggingLayer setValue:[NSValue valueWithRect:r] forKey:@"frame"]; // [draggingLayer didChangeValueForKey:@"frame"]; } - (void)clicked:(NSPoint)point { if(draggingLayer){ draggingLayer.opacity = 0.75; draggingLayer = nil; } NSArray* layers; int i, size; layers = [timeLine sublayers]; size = [layers count]; dragging = NO; for(i = TRACK_MAX; i < size; i++){ if([self isInclude:[layers objectAtIndex:i] point:point]){ draggingLayer = [layers objectAtIndex:i]; draggingLayer.opacity = 1.0; clickedPosition = point; clickedLayerPosition = draggingLayer.frame.origin; [_timeLineView setCursorRect:draggingLayer.frame]; [_tableController createPropertyTable:[draggingLayer valueForKey:@"ElisLayer"]]; [_tableController reload]; [_mainController refresh]; return; } } if(draggingLayer){ draggingLayer.opacity = 0.75; draggingLayer = nil; } clickedPosition.x = -1; // "レイヤーは選択されていない" という意味。 stretch = 0; } - (void)doubleClicked { if(draggingLayer == nil) return; if([[draggingLayer valueForKey:@"have keyframeLayer"] boolValue]){ NSLog(@"release"); [[[draggingLayer sublayers] lastObject] removeFromSuperlayer]; [draggingLayer setValue:[NSNumber numberWithBool:NO] forKey:@"have keyframeLayer"]; [_layerFactory removeParentLayer]; // 参照を切る = GCで回収されるようにする return; } CALayer* keyframeLayer; keyframeLayer = [_layerFactory createKeyframeLayerWithLayer:draggingLayer]; float size = draggingLayer.frame.size.width; float x; CGRect r; CALayer *miniLayer; [draggingLayer addSublayer:keyframeLayer]; [draggingLayer setValue:[NSNumber numberWithBool:YES] forKey:@"have keyframeLayer"]; if([_tableController isSelected] == NO) return; for(x = 0.0; x < size-1; x += MINI_LAYER_WIDTH){ miniLayer = [_layerFactory createKeyframeLevelLayer]; r = miniLayer.frame; r.size.height = 100 * [_tableController getSelectedValueForTime:x]; r.origin.x = x; miniLayer.frame = r; [keyframeLayer addSublayer:miniLayer]; } } - (void)updateKeyframeLayer { if(draggingLayer == nil) return; if([[draggingLayer valueForKey:@"have keyframeLayer"] boolValue] == NO) return; NSArray* minis; minis = [[[draggingLayer sublayers] lastObject] sublayers]; CALayer* mini; CGRect r; int i, size = [minis count]; for(i = 0; i < size; i++){ mini = [minis objectAtIndex:i]; r = mini.frame; r.size.height = 100 * [_tableController getSelectedValueForTime:i * MINI_LAYER_WIDTH]; mini.frame = r; } } // 左側のマッピングを調整する。(レイヤー内オフセットをいじる) - (void)stretchLeft { stretch = STRETCH_LEFT; } // 右側のマッピングを調整する。(マッピングの範囲を変えるだけ) - (void)stretchRight { stretch = STRETCH_RIGHT; } - (BOOL)isInclude:(CALayer*)layer point:(NSPoint)point { CGRect r = layer.frame; return r.origin.x <= point.x && point.x <= r.origin.x + r.size.width && r.origin.y <= point.y && point.y <= r.origin.y + r.size.height; } - (CALayer*)getSelectLayer { return draggingLayer; } - (void)removeSelectLayer { [draggingLayer setValue:nil forKey:@"ElisLayer"]; draggingLayer = nil; } @end