diff --git a/Extensions/CCLayerSmoothLine/CCLayerSmoothLine.h b/Extensions/CCLayerSmoothLine/CCLayerSmoothLine.h new file mode 100644 index 0000000..f81020c --- /dev/null +++ b/Extensions/CCLayerSmoothLine/CCLayerSmoothLine.h @@ -0,0 +1,60 @@ +/* + * Smooth drawing: http://merowing.info + * + * Copyright (c) 2012 Krzysztof Zabłocki + * Copyright (c) 2014 Richard Groves + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "cocos2d.h" + +typedef struct +{ + CGPoint pos; + float z; + ccColor4F color; +} CCSmoothLineVertex; + +// ----------------------------------------------------------------------- + +@interface CCSmoothLinePoint : NSObject + +@property(nonatomic, assign) CGPoint pos; +@property(nonatomic, assign) float width; + +@end + +// ----------------------------------------------------------------------- + +@interface CCLayerSmoothLine : CCNode + +// ----------------------------------------------------------------------- + ++ (instancetype)layer; +- (instancetype)init; + +- (void)startNewLineFrom:(CGPoint)newPoint withSize:(CGFloat)aSize; +- (void)endLineAt:(CGPoint)aEndPoint withSize:(CGFloat)aSize; +- (void)addPoint:(CGPoint)newPoint withSize:(CGFloat)size; + +// ----------------------------------------------------------------------- + +@end \ No newline at end of file diff --git a/Extensions/CCLayerSmoothLine/CCLayerSmoothLine.m b/Extensions/CCLayerSmoothLine/CCLayerSmoothLine.m new file mode 100644 index 0000000..bdd0486 --- /dev/null +++ b/Extensions/CCLayerSmoothLine/CCLayerSmoothLine.m @@ -0,0 +1,491 @@ +/* + * Smooth drawing: http://merowing.info + * + * Copyright (c) 2012 Krzysztof Zabłocki + * Copyright (c) 2014 Richard Groves + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import +#import "cocos2d.h" +#import "CCLayerSmoothLine.h" +#import "CCNode_Private.h" // shader stuff +#import "CCRenderer_private.h" // access to get and stash renderer + +// ----------------------------------------------------------------------- + +@implementation CCSmoothLinePoint + +@end + +// ----------------------------------------------------------------------- + +@implementation CCLayerSmoothLine +{ + NSMutableArray *_points; + NSMutableArray *_velocities; + NSMutableArray *_circlesPoints; + + BOOL _connectingLine; + CGPoint _prevC, _prevD; + CGPoint _prevG; + CGPoint _prevI; + float _overdraw; + + CCRenderTexture *_renderTexture; + BOOL _finishingLine; +} + +// ----------------------------------------------------------------------- + ++ (instancetype)layer +{ + return([[self alloc] init]); +} + +// ----------------------------------------------------------------------- + +- (id)init +{ + self = [super init]; + if (self) + { + self.contentSize = [CCDirector sharedDirector].viewSize; + + _points = [NSMutableArray array]; + _velocities = [NSMutableArray array]; + _circlesPoints = [NSMutableArray array]; + + _overdraw = 3.0f; + + CGSize s = [[CCDirector sharedDirector] viewSize]; + _renderTexture = [[CCRenderTexture alloc] initWithWidth:s.width height:s.height pixelFormat:CCTexturePixelFormat_RGBA8888]; + + _renderTexture.positionType = CCPositionTypeNormalized; + _renderTexture.anchorPoint = ccp(0, 0); + _renderTexture.position = ccp(0.5f, 0.5f); + + [_renderTexture clear:1.0f g:1.0f b:1.0f a:1.0f]; + [self addChild:_renderTexture]; + + [[[CCDirector sharedDirector] view] setUserInteractionEnabled:YES]; + + UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; + panGestureRecognizer.maximumNumberOfTouches = 1; + [[[CCDirector sharedDirector] view] addGestureRecognizer:panGestureRecognizer]; + + UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; + [[[CCDirector sharedDirector] view] addGestureRecognizer:longPressGestureRecognizer]; + } + return self; +} + +// ----------------------------------------------------------------------- +#pragma mark - Handling points + +- (void)startNewLineFrom:(CGPoint)newPoint withSize:(CGFloat)aSize +{ + _connectingLine = NO; + [self addPoint:newPoint withSize:aSize]; +} + +// ----------------------------------------------------------------------- + +- (void)endLineAt:(CGPoint)aEndPoint withSize:(CGFloat)aSize +{ + [self addPoint:aEndPoint withSize:aSize]; + _finishingLine = YES; +} + +// ----------------------------------------------------------------------- + +- (void)addPoint:(CGPoint)newPoint withSize:(CGFloat)size +{ + CCSmoothLinePoint *point = [[CCSmoothLinePoint alloc] init]; + point.pos = newPoint; + point.width = size; + [_points addObject:point]; +} + +// ----------------------------------------------------------------------- +#pragma mark - Drawing + +#define ADD_TRIANGLE(A, B, C, Z) vertices[index].pos = A, vertices[index++].z = Z, vertices[index].pos = B, vertices[index++].z = Z, vertices[index].pos = C, vertices[index++].z = Z + +- (void)drawLines:(NSArray *)linePoints withColor:(ccColor4F)color +{ + NSUInteger numberOfVertices = ([linePoints count] - 1) * 18; + CCSmoothLineVertex *vertices = calloc(sizeof(CCSmoothLineVertex), numberOfVertices); + + CGPoint prevPoint = [(CCSmoothLinePoint *)[linePoints objectAtIndex:0] pos]; + float prevValue = [(CCSmoothLinePoint *)[linePoints objectAtIndex:0] width]; + float curValue; + int index = 0; + for (int i = 1; i < [linePoints count]; ++i) + { + CCSmoothLinePoint *pointValue = [linePoints objectAtIndex:i]; + CGPoint curPoint = [pointValue pos]; + curValue = [pointValue width]; + + //! equal points, skip them + if (ccpFuzzyEqual(curPoint, prevPoint, 0.0001f)) + { + continue; + } + + CGPoint dir = ccpSub(curPoint, prevPoint); + CGPoint perpendicular = ccpNormalize(ccpPerp(dir)); + CGPoint A = ccpAdd(prevPoint, ccpMult(perpendicular, prevValue / 2)); + CGPoint B = ccpSub(prevPoint, ccpMult(perpendicular, prevValue / 2)); + CGPoint C = ccpAdd(curPoint, ccpMult(perpendicular, curValue / 2)); + CGPoint D = ccpSub(curPoint, ccpMult(perpendicular, curValue / 2)); + + //! continuing line + if (_connectingLine || index > 0) + { + A = _prevC; + B = _prevD; + } + else if (index == 0) + { + //! circle at start of line, revert direction + [_circlesPoints addObject:pointValue]; + [_circlesPoints addObject:[linePoints objectAtIndex:i - 1]]; + } + + ADD_TRIANGLE(A, B, C, 1.0f); + ADD_TRIANGLE(B, C, D, 1.0f); + + _prevD = D; + _prevC = C; + if (_finishingLine && (i == [linePoints count] - 1)) + { + [_circlesPoints addObject:[linePoints objectAtIndex:i - 1]]; + [_circlesPoints addObject:pointValue]; + _finishingLine = NO; + } + prevPoint = curPoint; + prevValue = curValue; + + //! Add overdraw + CGPoint F = ccpAdd(A, ccpMult(perpendicular, _overdraw)); + CGPoint G = ccpAdd(C, ccpMult(perpendicular, _overdraw)); + CGPoint H = ccpSub(B, ccpMult(perpendicular, _overdraw)); + CGPoint I = ccpSub(D, ccpMult(perpendicular, _overdraw)); + + //! end vertices of last line are the start of this one, also for the overdraw + if (_connectingLine || index > 6) + { + F = _prevG; + H = _prevI; + } + + _prevG = G; + _prevI = I; + + ADD_TRIANGLE(F, A, G, 2.0f); + ADD_TRIANGLE(A, G, C, 2.0f); + ADD_TRIANGLE(B, H, D, 2.0f); + ADD_TRIANGLE(H, D, I, 2.0f); + } + [self fillLineTriangles:vertices count:index withColor:color]; + + if (index > 0) + { + _connectingLine = YES; + } + + free(vertices); +} + +// ----------------------------------------------------------------------- + +- (void)fillLineEndPointAt:(CGPoint)center direction:(CGPoint)aLineDir radius:(CGFloat)radius andColor:(ccColor4F)color +{ + int numberOfSegments = 32; + CCSmoothLineVertex *vertices = malloc(sizeof(CCSmoothLineVertex) * numberOfSegments * 9); + float anglePerSegment = (float)(M_PI / (numberOfSegments - 1)); + + //! we need to cover M_PI from this, dot product of normalized vectors is equal to cos angle between them... and if you include rightVec dot you get to know the correct direction :) + CGPoint perpendicular = ccpPerp(aLineDir); + float angle = acosf(ccpDot(perpendicular, CGPointMake(0, 1))); + float rightDot = ccpDot(perpendicular, CGPointMake(1, 0)); + if (rightDot < 0.0f) + { + angle *= -1; + } + + CGPoint prevPoint = center; + CGPoint prevDir = ccp(sinf(0), cosf(0)); + for (unsigned int i = 0; i < numberOfSegments; ++i) + { + CGPoint dir = ccp(sinf(angle), cosf(angle)); + CGPoint curPoint = ccp(center.x + radius * dir.x, center.y + radius * dir.y); + vertices[i * 9 + 0].pos = center; + vertices[i * 9 + 1].pos = prevPoint; + vertices[i * 9 + 2].pos = curPoint; + + //! fill rest of vertex data + for (unsigned int j = 0; j < 9; ++j) + { + vertices[i * 9 + j].z = j < 3 ? 1.0f : 2.0f; + vertices[i * 9 + j].color = color; + } + + //! add overdraw + vertices[i * 9 + 3].pos = ccpAdd(prevPoint, ccpMult(prevDir, _overdraw)); + vertices[i * 9 + 3].color.a = 0; + vertices[i * 9 + 4].pos = prevPoint; + vertices[i * 9 + 5].pos = ccpAdd(curPoint, ccpMult(dir, _overdraw)); + vertices[i * 9 + 5].color.a = 0; + + vertices[i * 9 + 6].pos = prevPoint; + vertices[i * 9 + 7].pos = curPoint; + vertices[i * 9 + 8].pos = ccpAdd(curPoint, ccpMult(dir, _overdraw)); + vertices[i * 9 + 8].color.a = 0; + + prevPoint = curPoint; + prevDir = dir; + angle += anglePerSegment; + } + + CCRenderer *renderer = [CCRenderer currentRenderer]; + GLKMatrix4 projection; + [renderer.globalShaderUniforms[CCShaderUniformProjection] getValue:&projection]; + CCRenderBuffer buffer = [renderer enqueueTriangles:numberOfSegments * 3 andVertexes:numberOfSegments * 9 withState:self.renderState globalSortOrder:1]; + + CCVertex vertex; + for (int i = 0; i < numberOfSegments * 9; i++) + { + vertex.position = GLKVector4Make(vertices[i].pos.x, vertices[i].pos.y, 0.0, 1.0); + vertex.color = GLKVector4Make(vertices[i].color.r, vertices[i].color.g, vertices[i].color.b, vertices[i].color.a); + CCRenderBufferSetVertex(buffer, i, CCVertexApplyTransform(vertex, &projection)); + } + + for (unsigned int i = 0; i < numberOfSegments * 3; i++) + { + CCRenderBufferSetTriangle(buffer, i, i*3, (i*3)+1, (i*3)+2); + } + + free(vertices); +} + +// ----------------------------------------------------------------------- + +- (void)fillLineTriangles:(CCSmoothLineVertex *)vertices count:(NSUInteger)count withColor:(ccColor4F)color +{ + if (!count) + { + return; + } + + ccColor4F fullColor = color; + ccColor4F fadeOutColor = color; + fadeOutColor.a = 0; + + for (int i = 0; i < count / 18; ++i) + { + for (int j = 0; j < 6; ++j) + { + vertices[i * 18 + j].color = color; + } + + //! FAG + vertices[i * 18 + 6].color = fadeOutColor; + vertices[i * 18 + 7].color = fullColor; + vertices[i * 18 + 8].color = fadeOutColor; + + //! AGD + vertices[i * 18 + 9].color = fullColor; + vertices[i * 18 + 10].color = fadeOutColor; + vertices[i * 18 + 11].color = fullColor; + + //! BHC + vertices[i * 18 + 12].color = fullColor; + vertices[i * 18 + 13].color = fadeOutColor; + vertices[i * 18 + 14].color = fullColor; + + //! HCI + vertices[i * 18 + 15].color = fadeOutColor; + vertices[i * 18 + 16].color = fullColor; + vertices[i * 18 + 17].color = fadeOutColor; + } + + CCRenderer *renderer = [CCRenderer currentRenderer]; + GLKMatrix4 projection; + [renderer.globalShaderUniforms[CCShaderUniformProjection] getValue:&projection]; + CCRenderBuffer buffer = [renderer enqueueTriangles:count/3 andVertexes:count withState:self.renderState globalSortOrder:1]; + + CCVertex vertex; + for (unsigned int i = 0; i < count; i++) + { + vertex.position = GLKVector4Make(vertices[i].pos.x, vertices[i].pos.y, 0.0, 1.0); + vertex.color = GLKVector4Make(vertices[i].color.r, vertices[i].color.g, vertices[i].color.b, vertices[i].color.a); + CCRenderBufferSetVertex(buffer, i, CCVertexApplyTransform(vertex, &projection)); + } + + for (unsigned int i = 0; i < count/3; i++) + { + CCRenderBufferSetTriangle(buffer, i, i*3, (i*3)+1, (i*3)+2); + } + + for (unsigned int i = 0; i < [_circlesPoints count] / 2; ++i) + { + CCSmoothLinePoint *prevPoint = [_circlesPoints objectAtIndex:i * 2]; + CCSmoothLinePoint *curPoint = [_circlesPoints objectAtIndex:i * 2 + 1]; + CGPoint dirVector = ccpNormalize(ccpSub(curPoint.pos, prevPoint.pos)); + + [self fillLineEndPointAt:curPoint.pos direction:dirVector radius:curPoint.width * 0.5f andColor:color]; + } + [_circlesPoints removeAllObjects]; +} + +// ----------------------------------------------------------------------- + +- (NSMutableArray *)calculateSmoothLinePoints +{ + if ([_points count] > 2) + { + NSMutableArray *smoothedPoints = [NSMutableArray array]; + for (unsigned int i = 2; i < [_points count]; ++i) + { + CCSmoothLinePoint *prev2 = [_points objectAtIndex:i - 2]; + CCSmoothLinePoint *prev1 = [_points objectAtIndex:i - 1]; + CCSmoothLinePoint *cur = [_points objectAtIndex:i]; + + CGPoint midPoint1 = ccpMult(ccpAdd(prev1.pos, prev2.pos), 0.5f); + CGPoint midPoint2 = ccpMult(ccpAdd(cur.pos, prev1.pos), 0.5f); + + int segmentDistance = 2; + float distance = ccpDistance(midPoint1, midPoint2); + int numberOfSegments = MIN(128, MAX(floorf(distance / segmentDistance), 32)); + + float t = 0.0f; + float step = 1.0f / numberOfSegments; + for (NSUInteger j = 0; j < numberOfSegments; j++) + { + CCSmoothLinePoint *newPoint = [[CCSmoothLinePoint alloc] init]; + newPoint.pos = ccpAdd(ccpAdd(ccpMult(midPoint1, powf(1 - t, 2)), ccpMult(prev1.pos, 2.0f * (1 - t) * t)), ccpMult(midPoint2, t * t)); + newPoint.width = powf(1 - t, 2) * ((prev1.width + prev2.width) * 0.5f) + 2.0f * (1 - t) * t * prev1.width + t * t * ((cur.width + prev1.width) * 0.5f); + + [smoothedPoints addObject:newPoint]; + t += step; + } + CCSmoothLinePoint *finalPoint = [[CCSmoothLinePoint alloc] init]; + finalPoint.pos = midPoint2; + finalPoint.width = (cur.width + prev1.width) * 0.5f; + [smoothedPoints addObject:finalPoint]; + } + //! we need to leave last 2 points for next draw + [_points removeObjectsInRange:NSMakeRange(0, [_points count] - 2)]; + return smoothedPoints; + } else { + return nil; + } +} + +// ----------------------------------------------------------------------- + +- (void)draw:(CCRenderer *)renderer transform:(const GLKMatrix4 *)transform +{ + ccColor4F color = {0, 0, 0, 1}; + [_renderTexture begin]; + + NSMutableArray *smoothedPoints = [self calculateSmoothLinePoints]; + if (smoothedPoints) + { + [self drawLines:smoothedPoints withColor:color]; + } + [_renderTexture end]; +} + +// ----------------------------------------------------------------------- +#pragma mark - Math + +// ----------------------------------------------------------------------- +#pragma mark - GestureRecognizers + +- (float)extractSize:(UIPanGestureRecognizer *)panGestureRecognizer +{ + //! result of trial & error + float vel = ccpLength([panGestureRecognizer velocityInView:panGestureRecognizer.view]); + float size = vel / 166.0f; + size = clampf(size, 1, 40); + + if ([_velocities count] > 1) + { + size = size * 0.2f + [[_velocities objectAtIndex:[_velocities count] - 1] floatValue] * 0.8f; + } + [_velocities addObject:[NSNumber numberWithFloat:size]]; + return size; +} + +// ----------------------------------------------------------------------- + +- (void)handlePanGesture:(UIPanGestureRecognizer *)panGestureRecognizer +{ + const CGPoint point = [[CCDirector sharedDirector] convertToGL:[panGestureRecognizer locationInView:panGestureRecognizer.view]]; + + if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) + { + [_points removeAllObjects]; + [_velocities removeAllObjects]; + + float size = [self extractSize:panGestureRecognizer]; + + [self startNewLineFrom:point withSize:size]; + } + + if (panGestureRecognizer.state == UIGestureRecognizerStateChanged) + { + //! skip points that are too close + float eps = 1.5f; + if ([_points count] > 0) + { + float length = ccpLength(ccpSub([(CCSmoothLinePoint *)[_points lastObject] pos], point)); + + if (length < eps) + { + return; + } + } + float size = [self extractSize:panGestureRecognizer]; + [self addPoint:point withSize:size]; + } + + if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) + { + float size = [self extractSize:panGestureRecognizer]; + [self endLineAt:point withSize:size]; + } +} + +// ----------------------------------------------------------------------- + +- (void)handleLongPress:(UILongPressGestureRecognizer *)longPressGestureRecognizer +{ + [_renderTexture beginWithClear:1.0 g:1.0 b:1.0 a:0]; + [_renderTexture end]; +} + +// ----------------------------------------------------------------------- + +@end diff --git a/Extensions/CCLayerSmoothLine/README.md b/Extensions/CCLayerSmoothLine/README.md new file mode 100644 index 0000000..d8cc95c --- /dev/null +++ b/Extensions/CCLayerSmoothLine/README.md @@ -0,0 +1,19 @@ +CCLayerSmoothLine +================= + +Type of class : Descendant of CCNode +Uses extension : [NONE] + +Authors : Krzysztof Zabłocki, Richard Groves + +Acts like a layer, enabling smooth line drawing. + +Example +======= + +[self addChild:[CCLayerSmoothLine layer]]; + +Known Bugs +========== +Misses round line ends when drawing fast zig zag pattern. + diff --git a/cocos2d-iphone-ext.xcodeproj/project.pbxproj b/cocos2d-iphone-ext.xcodeproj/project.pbxproj index 4066b19..e59290e 100644 --- a/cocos2d-iphone-ext.xcodeproj/project.pbxproj +++ b/cocos2d-iphone-ext.xcodeproj/project.pbxproj @@ -10,7 +10,10 @@ 0E21D306198A47A400E84AB1 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 0E21D305198A47A400E84AB1 /* README.md */; }; 0E21D30C198A484600E84AB1 /* CCSpriteMultiTouch.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E21D30B198A484600E84AB1 /* CCSpriteMultiTouch.m */; }; 0E21D30F198A637900E84AB1 /* CCSpriteMultiTouchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E21D30E198A637900E84AB1 /* CCSpriteMultiTouchTest.m */; }; + 0E9A092A199CDDD10049E409 /* CCLayerSmoothLineTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E9A0929199CDDD10049E409 /* CCLayerSmoothLineTest.m */; }; 0ED73BB51997951A00C83507 /* CCSpineCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ED73BB41997951A00C83507 /* CCSpineCurve.m */; }; + 0EF602FD199CDC8F007AEBD9 /* CCLayerSmoothLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 0EF602FC199CDC8F007AEBD9 /* CCLayerSmoothLine.m */; }; + 0EF602FF199CDD8F007AEBD9 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 0EF602FE199CDD8F007AEBD9 /* README.md */; }; A6270E62193757E400196BD3 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6270E61193757E400196BD3 /* QuartzCore.framework */; }; A6270E64193757E400196BD3 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6270E63193757E400196BD3 /* OpenGLES.framework */; }; A6270E66193757E400196BD3 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6270E65193757E400196BD3 /* OpenAL.framework */; }; @@ -125,8 +128,12 @@ 0E21D30A198A484600E84AB1 /* CCSpriteMultiTouch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCSpriteMultiTouch.h; path = Extensions/CCSpriteMultiTouch/CCSpriteMultiTouch.h; sourceTree = SOURCE_ROOT; }; 0E21D30B198A484600E84AB1 /* CCSpriteMultiTouch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCSpriteMultiTouch.m; path = Extensions/CCSpriteMultiTouch/CCSpriteMultiTouch.m; sourceTree = SOURCE_ROOT; }; 0E21D30E198A637900E84AB1 /* CCSpriteMultiTouchTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCSpriteMultiTouchTest.m; path = Classes/Tests/CCSpriteMultiTouchTest.m; sourceTree = ""; }; + 0E9A0929199CDDD10049E409 /* CCLayerSmoothLineTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCLayerSmoothLineTest.m; path = Classes/Tests/CCLayerSmoothLineTest.m; sourceTree = ""; }; 0ED73BB31997951A00C83507 /* CCSpineCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCSpineCurve.h; path = Extensions/CCSpine/CCSpineCurve.h; sourceTree = SOURCE_ROOT; }; 0ED73BB41997951A00C83507 /* CCSpineCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCSpineCurve.m; path = Extensions/CCSpine/CCSpineCurve.m; sourceTree = SOURCE_ROOT; }; + 0EF602FB199CDC8F007AEBD9 /* CCLayerSmoothLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCLayerSmoothLine.h; path = Extensions/CCLayerSmoothLine/CCLayerSmoothLine.h; sourceTree = SOURCE_ROOT; }; + 0EF602FC199CDC8F007AEBD9 /* CCLayerSmoothLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCLayerSmoothLine.m; path = Extensions/CCLayerSmoothLine/CCLayerSmoothLine.m; sourceTree = SOURCE_ROOT; }; + 0EF602FE199CDD8F007AEBD9 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.md; path = Extensions/CCLayerSmoothLine/README.md; sourceTree = SOURCE_ROOT; }; A6254BAF193A1438006BD09E /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.md; path = Extensions/CCNodeTag/README.md; sourceTree = SOURCE_ROOT; }; A6254BB1193A144A006BD09E /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.md; path = Extensions/CCDictionary/README.md; sourceTree = SOURCE_ROOT; }; A6254BB3193A145D006BD09E /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.md; path = Extensions/CCSpine/README.md; sourceTree = SOURCE_ROOT; }; @@ -278,6 +285,16 @@ name = CCSpriteMultiTouch; sourceTree = ""; }; + 0EF602F9199CDC4A007AEBD9 /* CCLayerSmoothLine */ = { + isa = PBXGroup; + children = ( + 0EF602FE199CDD8F007AEBD9 /* README.md */, + 0EF602FB199CDC8F007AEBD9 /* CCLayerSmoothLine.h */, + 0EF602FC199CDC8F007AEBD9 /* CCLayerSmoothLine.m */, + ); + name = CCLayerSmoothLine; + sourceTree = ""; + }; A6270E55193757E300196BD3 = { isa = PBXGroup; children = ( @@ -452,6 +469,7 @@ A6994F83194A2FAC00B97481 /* CCTransformationNodeTest.m */, A6994F80194A2F3D00B97481 /* CCCropNodeTest.m */, 0E21D30E198A637900E84AB1 /* CCSpriteMultiTouchTest.m */, + 0E9A0929199CDDD10049E409 /* CCLayerSmoothLineTest.m */, A6994F7E194A2E2800B97481 /* Test helper classes */, ); name = Tests; @@ -460,6 +478,7 @@ A66C5808193A0C24009D2BD4 /* Extensions */ = { isa = PBXGroup; children = ( + 0EF602F9199CDC4A007AEBD9 /* CCLayerSmoothLine */, 0E21D303198A45F800E84AB1 /* CCSpriteMultiTouch */, A6994F76194A2C8000B97481 /* CCCropNode */, A68895A91949A785002950DD /* CCTransformationNode */, @@ -670,6 +689,7 @@ A6271295193769A900196BD3 /* din-ipad.fnt in Resources */, A6270E82193757E400196BD3 /* Default-Landscape~ipad.png in Resources */, A6270E97193757E400196BD3 /* Icon-Small.png in Resources */, + 0EF602FF199CDD8F007AEBD9 /* README.md in Resources */, A6270E95193757E400196BD3 /* Icon-Small-50.png in Resources */, A62712AA193769A900196BD3 /* Sprites.plist in Resources */, A62712AB193769A900196BD3 /* Sprites.png in Resources */, @@ -731,8 +751,10 @@ A68895AF1949A8B4002950DD /* CCTransformationNode.m in Sources */, A627126D19375F2700196BD3 /* MainMenu.m in Sources */, A66C5830193A0C87009D2BD4 /* CCSpineAnimation.m in Sources */, + 0EF602FD199CDC8F007AEBD9 /* CCLayerSmoothLine.m in Sources */, A66C5835193A0C87009D2BD4 /* CCSpineSkeleton.m in Sources */, A66C5836193A0C87009D2BD4 /* CCSpineSkin.m in Sources */, + 0E9A092A199CDDD10049E409 /* CCLayerSmoothLineTest.m in Sources */, A6271107193757E600196BD3 /* main.m in Sources */, 0E21D30C198A484600E84AB1 /* CCSpriteMultiTouch.m in Sources */, A66C5837193A0C87009D2BD4 /* CCSpineSprite.m in Sources */, diff --git a/cocos2d-iphone-ext.xcodeproj/project.xcworkspace/xcuserdata/Birkemose.xcuserdatad/UserInterfaceState.xcuserstate b/cocos2d-iphone-ext.xcodeproj/project.xcworkspace/xcuserdata/Birkemose.xcuserdatad/UserInterfaceState.xcuserstate index bfee2ff..cd5f1c8 100644 Binary files a/cocos2d-iphone-ext.xcodeproj/project.xcworkspace/xcuserdata/Birkemose.xcuserdatad/UserInterfaceState.xcuserstate and b/cocos2d-iphone-ext.xcodeproj/project.xcworkspace/xcuserdata/Birkemose.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/cocos2d-iphone-ext/Classes/Tests/CCLayerSmoothLineTest.m b/cocos2d-iphone-ext/Classes/Tests/CCLayerSmoothLineTest.m new file mode 100644 index 0000000..d3d268c --- /dev/null +++ b/cocos2d-iphone-ext/Classes/Tests/CCLayerSmoothLineTest.m @@ -0,0 +1,37 @@ +// +// CCLayerSmoothLineTest.m +// cocos2d-iphone-ext +// +// Created by Lars Birkemose on 14/08/14. +// Copyright 2014 Cocos2D-iphone. All rights reserved. +// + +#import "TestBase.h" +#import "CCLayerSmoothLine.h" + +//---------------------------------------------------------------------- + +@interface CCLayerSmoothLineTest : TestBase + +@end + +//---------------------------------------------------------------------- + +@implementation CCLayerSmoothLineTest + +- (NSArray *)testConstructors +{ + return [NSArray arrayWithObjects: + @"smoothLineTest", + nil]; +} + +- (void)smoothLineTest +{ + self.subTitle = @"Touch and hold to wipe drawing"; + [self.contentNode addChild:[CCLayerSmoothLine layer]]; +} + +@end + +//----------------------------------------------------------------------