// Copyright (c) 2009 Yanagi Asakura // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, and must not be // misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source // distribution. // // ElisKeyframe.m // Elis Colors // // Created by 柳 on 09/09/15. // Copyright 2009 __MyCompanyName__. All rights reserved. // #import "ElisKeyframe.h" static float convertQTTimeToSecond(QTTime t) { return (float)t.timeValue/t.timeScale; } @implementation ElisKeyframe - (id)init { [super init]; timesAndValues = [[NSMutableDictionary alloc] init]; cacheTime = NAN; #ifdef __SNOW_LEOPARD_GCD__ diq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); #endif return self; } - (void)setValueForTime:(float)value time:(QTTime)time { int i, j; long long tmp1, tmp2; [timesAndValues setObject:[NSNumber numberWithFloat:value] forKey:[NSNumber numberWithFloat:convertQTTimeToSecond(time)]]; sortedTimes = [[timesAndValues allKeys] sortedArrayUsingSelector:@selector(compare:)]; // 常識的に考えて、NSArrayである必要なくね? Cの配列でよくね? cacheTime = NAN; // Cの配列時代の実装。挿入ソート? // for(i = 0; i < index-1; i++){ // if(times[i].timeValue == time.timeValue){ // values[i] = value; // return; // } // if(times[i].timeValue <= time.timeValue && time.timeValue <= times[i+1].timeValue){ // for(j = index; j > i+1; j--){ // times[j] = times[j-1]; // values[j] = values[j-1]; // } // times[i+1] = time; // values[i+1] = value; // return; // } // } // if(times[index-1].timeValue == time.timeValue) values[index-1] = value; // else if(times[index-1].timeValue <= time.timeValue){ // times[index] = time; // values[index++] = value; // }else{ // times[index] = times[index-1]; // values[index] = values[index-1]; // times[index-1] = time; // values[index-1] = value; // index++; // } // return; } // いろいろすさまじい。ボトルネックになりそうだなあここ。 // 描画を実行する度に2回呼ばれる。キャッシュするか。 - (float)getValueForTime:(QTTime)time { // long long now = time.timeValue; // int i; // for(i = 0; i < index-1; i++){ // if(times[i].timeValue <= now && now <= times[i+1].timeValue){ // return ((float)(times[i+1].timeValue - now) * values[i] + // (float)(now - times[i].timeValue) * values[i+1])/(times[i+1].timeValue - times[i].timeValue); // } // } // if(now <= times[0].timeValue) return values[0]; // if(times[index-1].timeValue <= now) return values[index-1]; float now = convertQTTimeToSecond(time); if(cacheTime == now) return cacheValue; cacheTime = now; int i, size = [sortedTimes count]; if(size == 1){ cacheValue = [[timesAndValues objectForKey:[sortedTimes objectAtIndex:0]] floatValue]; return cacheValue; } if([[sortedTimes lastObject] floatValue] <= now){ cacheValue = [[timesAndValues objectForKey:[sortedTimes lastObject]] floatValue]; return cacheValue; } #ifdef __SNOW_LEOPARD_GCD__2 dispatch_apply(size-1, diq, ^(size_t i) { if([[sortedTimes objectAtIndex:i] floatValue] <= now && now <= [[sortedTimes objectAtIndex:i+1] floatValue]){ cacheValue = (([[sortedTimes objectAtIndex:i+1] floatValue] - now) * [[timesAndValues objectForKey:[sortedTimes objectAtIndex:i]] floatValue] + (now - [[sortedTimes objectAtIndex:i] floatValue]) * [[timesAndValues objectForKey:[sortedTimes objectAtIndex:i+1]] floatValue]) / ([[sortedTimes objectAtIndex:i+1] floatValue] - [[sortedTimes objectAtIndex:i] floatValue]); } }); return cacheValue; #else for(i = 0; i < size-1; i++){ if([[sortedTimes objectAtIndex:i] floatValue] <= now && now <= [[sortedTimes objectAtIndex:i+1] floatValue]){ cacheValue = (([[sortedTimes objectAtIndex:i+1] floatValue] - now) * [[timesAndValues objectForKey:[sortedTimes objectAtIndex:i]] floatValue] + (now - [[sortedTimes objectAtIndex:i] floatValue]) * [[timesAndValues objectForKey:[sortedTimes objectAtIndex:i+1]] floatValue]) / ([[sortedTimes objectAtIndex:i+1] floatValue] - [[sortedTimes objectAtIndex:i] floatValue]); return cacheValue; } } #endif return cacheValue; } - (void)encodeWithCoder:(NSCoder*)encoder { [encoder encodeObject:timesAndValues forKey:@"timesAndValues"]; [encoder encodeObject:sortedTimes forKey:@"sortedTimes"]; } - (id)initWithCoder:(NSCoder*)coder { timesAndValues = [coder decodeObjectForKey:@"timesAndValues"]; sortedTimes = [coder decodeObjectForKey:@"sortedTimes"]; cacheTime = NAN; return self; } @end