/*
* RoundedRectNode.m
*
* Created by John Swensen on 6/2/11.
* Copyright 2011 swenGames.com.
*
* 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 "RoundedRectNode.h"
@implementation RoundedRectNode
@synthesize size, radius, borderWidth, cornerSegments, borderColor, fillColor;
#define kappa 0.552228474
-(id) initWithRectSize:(CGSize)sz {
if((self == [super init]))
{
size = sz;
radius = 1;
borderWidth = 1;
cornerSegments = 4;
borderColor = ccc4(255,255,255,255);
fillColor = ccc4(0,0,0,255);
}
return self;
}
void appendCubicBezier(int startPoint, CGPoint* vertices, CGPoint origin, CGPoint control1, CGPoint control2, CGPoint destination, NSUInteger segments)
{
//ccVertex2F vertices[segments + 1];
float t = 0;
for(NSUInteger i = 0; i < segments; i++)
{
GLfloat x = powf(1 - t, 3) * origin.x + 3.0f * powf(1 - t, 2) * t * control1.x + 3.0f * (1 - t) * t * t * control2.x + t * t * t * destination.x;
GLfloat y = powf(1 - t, 3) * origin.y + 3.0f * powf(1 - t, 2) * t * control1.y + 3.0f * (1 - t) * t * t * control2.y + t * t * t * destination.y;
vertices[startPoint+i] = CGPointMake(x * CC_CONTENT_SCALE_FACTOR(), y * CC_CONTENT_SCALE_FACTOR() );
//vertices[startPoint+i] = (ccVertex2F) {x * CC_CONTENT_SCALE_FACTOR(), y * CC_CONTENT_SCALE_FACTOR() };
t += 1.0f / segments;
}
//vertices[segments] = (ccVertex2F) {destination.x * CC_CONTENT_SCALE_FACTOR(), destination.y * CC_CONTENT_SCALE_FACTOR() };
}
void ccFillPoly( CGPoint *poli, int points, BOOL closePolygon )
{
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_VERTEX_ARRAY,
// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, poli);
if( closePolygon )
// glDrawArrays(GL_LINE_LOOP, 0, points);
glDrawArrays(GL_TRIANGLE_FAN, 0, points);
else
glDrawArrays(GL_LINE_STRIP, 0, points);
// restore default state
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
}
-(void) draw {
CGPoint vertices[16];
vertices[0] = ccp(0,-radius);
vertices[1] = ccp(0,-radius*(1-kappa));
vertices[2] = ccp(radius*(1-kappa),0);
vertices[3] = ccp(radius,0);
vertices[4] = ccp(size.width-radius,0);
vertices[5] = ccp(size.width-radius*(1-kappa),0);
vertices[6] = ccp(size.width,-radius*(1-kappa));
vertices[7] = ccp(size.width,-radius);
vertices[8] = ccp(size.width,-size.height + radius);
vertices[9] = ccp(size.width,-size.height + radius*(1-kappa));
vertices[10] = ccp(size.width-radius*(1-kappa),-size.height);
vertices[11] = ccp(size.width-radius,-size.height);
vertices[12] = ccp(radius,-size.height);
vertices[13] = ccp(radius*(1-kappa),-size.height);
vertices[14] = ccp(0,-size.height+radius*(1-kappa));
vertices[15] = ccp(0,-size.height+radius);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
CGPoint polyVertices[4*cornerSegments+1];
appendCubicBezier(0*cornerSegments,polyVertices,vertices[0], vertices[1], vertices[2], vertices[3], cornerSegments);
appendCubicBezier(1*cornerSegments,polyVertices,vertices[4], vertices[5], vertices[6], vertices[7], cornerSegments);
appendCubicBezier(2*cornerSegments,polyVertices,vertices[8], vertices[9], vertices[10], vertices[11], cornerSegments);
appendCubicBezier(3*cornerSegments,polyVertices,vertices[12], vertices[13], vertices[14], vertices[15], cornerSegments);
polyVertices[4*cornerSegments] = vertices[0];
glColor4ub(fillColor.r, fillColor.g, fillColor.b, fillColor.a);
ccFillPoly(polyVertices, 4*cornerSegments+1, YES);
glColor4ub(borderColor.r, borderColor.g, borderColor.b, borderColor.a);
glLineWidth(borderWidth);
glEnable(GL_LINE_SMOOTH);
ccDrawCubicBezier(vertices[0], vertices[1], vertices[2], vertices[3], cornerSegments);
ccDrawLine(vertices[3], vertices[4]);
ccDrawCubicBezier(vertices[4], vertices[5], vertices[6], vertices[7], cornerSegments);
ccDrawLine(vertices[7], vertices[8]);
ccDrawCubicBezier(vertices[8], vertices[9], vertices[10], vertices[11], cornerSegments);
ccDrawLine(vertices[11], vertices[12]);
ccDrawCubicBezier(vertices[12], vertices[13], vertices[14], vertices[15], cornerSegments);
ccDrawLine(vertices[15], vertices[0]);
glDisable(GL_LINE_SMOOTH);
}
@end