Chromium Code Reviews| Index: nacltoons/data/res/drawing.lua |
| diff --git a/nacltoons/data/res/drawing.lua b/nacltoons/data/res/drawing.lua |
| index d6a7911d531081927a3ff8805bafc292b06b5e91..f42347b8868b2bd617776da58e1b9a9e538e473a 100644 |
| --- a/nacltoons/data/res/drawing.lua |
| +++ b/nacltoons/data/res/drawing.lua |
| @@ -28,13 +28,16 @@ local drawing = { |
| drawing.mode = drawing.MODE_FREEHAND |
| -- Brush information (set by SetBrush) |
| -local brush_node |
| +local brush_tex |
| local brush_thickness |
| -- Constant for grouping physics bodies |
| local MAIN_CATEGORY = 0x1 |
| local DRAWING_CATEGORY = 0x2 |
| +-- Constants for tagging cocos nodes |
| +local TAG_BATCH_NODE = 0x1 |
| + |
| -- Local state for default touch handlers |
| local current_shape = nil |
| local current_tag = 99 -- util.tags.TAG_DYNAMIC_START |
| @@ -54,6 +57,13 @@ local function b2VecFromLua(point) |
| return util.b2VecFromCocos(util.PointFromLua(point)) |
| end |
| +local function CreateBrushBatch(parent) |
| + local node = CCSpriteBatchNode:createWithTexture(brush_tex, 100) |
|
binji
2013/05/21 21:11:36
what is 100?
Sam Clegg
2013/05/21 22:51:46
Its the initial size of the batch node.
Done.
|
| + assert(node) |
| + parent:addChild(node, 1, TAG_BATCH_NODE) |
| + return node |
| +end |
| + |
| --- Create a fixed pivot point between the world and the given body. |
| local function CreatePivot(anchor, body) |
| local anchor_point = util.b2VecFromCocos(anchor) |
| @@ -79,18 +89,28 @@ local function AddShapeToBody(body, shape, sensor) |
| return body:CreateFixture(fixture_def) |
| end |
| -local function InitPhysicsSprite(sprite, location, dynamic) |
| +local function InitPhysicsNode(node, location, dynamic, tag) |
| local body_def = b2BodyDef:new_local() |
| if dynamic == true then |
| body_def.type = b2_dynamicBody |
| end |
| local body = level_obj.world:CreateBody(body_def) |
| - sprite:setB2Body(body) |
| - sprite:setPTMRatio(util.PTM_RATIO) |
| - sprite:setPosition(location) |
| + node:setB2Body(body) |
| + node:setPTMRatio(util.PTM_RATIO) |
| + node:setPosition(location) |
| + node:setTag(tag) |
| + body:SetUserData(tag) |
| + level_obj.layer:addChild(node, 1, tag) |
| return body |
| end |
| +-- Create and initialise a new invisible physics node. |
| +local function CreatePhysicsNode(location, dynamic, tag) |
| + local node = CCPhysicsNode:create() |
| + InitPhysicsNode(node, location, dynamic, tag) |
| + return node |
| +end |
| + |
| local function DrawBrush(parent, location, color) |
| local child_sprite = CCSprite:createWithTexture(brush_tex) |
| child_sprite:setPosition(location) |
| @@ -98,16 +118,6 @@ local function DrawBrush(parent, location, color) |
| parent:addChild(child_sprite) |
| end |
| -function DrawPhysicsBrush(location, color, tag, dynamic) |
| - local sprite = CCPhysicsSprite:createWithTexture(brush_tex) |
| - local body = InitPhysicsSprite(sprite, location, dynamic) |
| - sprite:setColor(color) |
| - sprite:setTag(tag) |
| - body:SetUserData(tag) |
| - brush_node:addChild(sprite) |
| - return sprite |
| -end |
| - |
| -- Add a new circle/sphere fixture to a body and return the new fixture |
| local function AddSphereToBody(body, location, radius, sensor) |
| local sphere = b2CircleShape:new_local() |
| @@ -118,65 +128,46 @@ local function AddSphereToBody(body, location, radius, sensor) |
| end |
| -- Add a new line/box fixture to a body and return the new fixture |
| -local function AddLineToShape(sprite, from, to, color) |
| +local function AddLineToShape(node, from, to, color, absolute) |
| -- calculate length and angle of line based on start and end points |
| - local body = sprite:getB2Body() |
| + local body = node:getB2Body() |
| local length = ccpDistance(from, to); |
| local dist_x = to.x - from.x |
| local dist_y = to.y - from.y |
| -- create fixture |
| - local relative_start_x = from.x - sprite:getPositionX() |
| - local relative_start_y = from.y - sprite:getPositionY() |
| - local center = b2Vec2:new_local(util.ScreenToWorld(relative_start_x + dist_x/2), |
| - util.ScreenToWorld(relative_start_y + dist_y/2)) |
| + local rel_start = from |
| + if absolute then |
| + rel_start = node:convertToNodeSpace(from) |
| + end |
| + local center = b2Vec2:new_local(util.ScreenToWorld(rel_start.x + dist_x/2), |
| + util.ScreenToWorld(rel_start.y + dist_y/2)) |
| local shape = b2PolygonShape:new_local() |
| local angle = math.atan2(dist_y, dist_x) |
| shape:SetAsBox(util.ScreenToWorld(length/2), util.ScreenToWorld(brush_thickness), |
| center, angle) |
| local fixture = AddShapeToBody(body, shape, false) |
| - -- Now create the visible CCPhysicsSprite that the body is attached to |
| - sprite:setColor(color) |
| - sprite:setPTMRatio(util.PTM_RATIO) |
| - |
| - -- And add a sequence of non-physics sprites as children of the first |
| + -- Create sequence of sprite nodes as children |
| local dist = CCPointMake(dist_x, dist_y) |
| local num_children = math.ceil(length / brush_step) |
| local inc_x = dist_x / num_children |
| local inc_y = dist_y / num_children |
| - local child_location = ccp(relative_start_x + brush_thickness, relative_start_y + brush_thickness) |
| + local child_location = rel_start |
| + |
| + util.Log('Create line at: rel=' .. util.PointToString(rel_start) .. ' len=' .. length .. ' num=' .. num_children) |
| - util.Log('Create line at: ' .. util.PointToString(from) .. ' len=' .. length .. ' num=' .. num_children) |
| + local batch_node = node:getChildByTag(TAG_BATCH_NODE) |
| + assert(batch_node) |
| for i = 1,num_children do |
| child_location.x = child_location.x + inc_x |
| child_location.y = child_location.y + inc_y |
| - DrawBrush(sprite, child_location, color) |
| + DrawBrush(batch_node, child_location, color) |
| end |
| return fixture |
| end |
| ---- Create a line between two points. |
| --- Uses a sequence of brush sprites an a single box2d rect. |
| -local function CreateLine(from, to, objdef) |
| - -- create body |
| - util.Log("Creating line with tag " .. objdef.tag) |
| - |
| - if objdef.color then |
| - color = ccc3(objdef.color[1], objdef.color[2], objdef.color[3]) |
| - else |
| - color = ccc3(255, 255, 255) |
| - end |
| - |
| - local sprite = drawing.DrawStartPoint(from, color, objdef.tag, objdef.dynamic) |
| - if objdef.anchor then |
| - CreatePivot(objdef.anchor, sprite:getB2Body()) |
| - end |
| - AddLineToShape(sprite, from, to, color) |
| - return sprite |
| -end |
| - |
| -- Set the collision group for a fixture |
| local function SetCategory(fixture, category) |
| local filter = fixture:GetFilterData() |
| @@ -198,116 +189,161 @@ end |
| --- Set brush texture for subsequent draw operations |
| function drawing.SetBrush(brush) |
| -- calculate thickness based on brush sprite size |
| - brush_node = brush |
| brush_tex = brush:getTexture() |
| local brush_size = brush_tex:getContentSizeInPixels() |
| brush_thickness = math.max(brush_size.height/2, brush_size.width/2) |
| brush_step = brush_thickness * 1.5 |
| end |
| +--- Create a physics sprite at a fiven location with a given image |
|
binji
2013/05/21 21:11:36
sp: given
Sam Clegg
2013/05/21 22:51:46
Done.
|
| +local function AddSpriteToShape(node, sprite_def, absolute) |
| + local pos = util.PointFromLua(sprite_def.pos, not absolute) |
|
binji
2013/05/21 21:11:36
you should probably flip PointFromLua to use absol
Sam Clegg
2013/05/21 22:51:46
Done.
|
| + util.Log('Create sprite [tag=' .. sprite_def.tag .. ' image=' .. sprite_def.image .. ' absolute=' .. tostring(absolute) .. ']: ' .. |
| + util.PointToString(pos)) |
| + local image = game_obj.assets[sprite_def.image] |
| + local sprite = CCSprite:create(image) |
| + local rel_pos |
| + local world_pos |
| + if absolute then |
|
binji
2013/05/21 21:11:36
I expected to see more symmetry between this funct
Sam Clegg
2013/05/21 22:51:46
Yes, me too. Its a little confusing but the box2d
|
| + rel_pos = node:convertToNodeSpace(pos) |
| + world_pos = pos |
| + else |
| + rel_pos = pos |
| + world_pos = node:convertToWorldSpace(pos) |
| + end |
| + sprite:setPosition(rel_pos) |
| + node:addChild(sprite) |
| + AddSphereToBody(node:getB2Body(), world_pos, sprite:boundingBox().size.height/2, sprite_def.sensor) |
| + return sprite |
| +end |
| + |
| +local function AddChildShape(shape, child_def, absolute) |
| + if child_def.color then |
| + color = ccc3(child_def.color[1], child_def.color[2], child_def.color[3]) |
| + else |
| + color = ccc3(255, 255, 255) |
| + end |
| + |
| + if child_def.type == 'line' then |
| + local start = util.PointFromLua(child_def.start, not absolute) |
| + local finish = util.PointFromLua(child_def.finish, not absolute) |
| + AddLineToShape(shape, start, finish, color, absolute) |
| + elseif child_def.type == 'image' then |
| + AddSpriteToShape(shape, child_def, absolute) |
| + else |
| + assert(false, 'invalid shape type: ' .. shape_def.type) |
| + end |
| +end |
| + |
| --- Draw a shape described by a given shape def. |
| -- This creates physics sprites and accosiated box2d bodies for |
| -- the shape. |
| function drawing.CreateShape(shape_def) |
| - if shape_def.type == 'line' then |
| - local start = util.PointFromLua(shape_def.start) |
| - local finish = util.PointFromLua(shape_def.finish) |
| - if shape_def.anchor then |
| - shape_def.anchor = util.PointFromLua(shape_def.anchor) |
| + local shape = nil |
| + |
| + if shape_def.type == 'compound' then |
| + local pos = util.PointFromLua(shape_def.pos) |
| + shape = CreatePhysicsNode(pos, shape_def.dynamic, shape_def.tag) |
| + CreateBrushBatch(shape) |
| + if shape_def.children then |
| + for _, child_def in ipairs(shape_def.children) do |
| + child_def.tag = shape_def.tag |
| + child = AddChildShape(shape, child_def, false) |
|
binji
2013/05/21 21:11:36
I'm finding the usage of absolute vs. not quite co
Sam Clegg
2013/05/21 22:51:46
I agree. I'll see what I can do.
I made the af
|
| + end |
| end |
| - return CreateLine(start, finish, shape_def) |
| + elseif shape_def.type == 'line' then |
| + local pos = util.PointFromLua(shape_def.start) |
| + shape = CreatePhysicsNode(pos, shape_def.dynamic, shape_def.tag) |
| + CreateBrushBatch(shape) |
| + AddChildShape(shape, shape_def, true) |
| elseif shape_def.type == 'edge' then |
| local body_def = b2BodyDef:new_local() |
| local body = level_obj.world:CreateBody(body_def) |
| local b2shape = b2EdgeShape:new_local() |
| b2shape:Set(b2VecFromLua(shape_def.start), b2VecFromLua(shape_def.finish)) |
| body:CreateFixture(b2shape, 0) |
| + return |
| + elseif shape_def.type == 'image' then |
| + local pos = util.PointFromLua(shape_def.pos) |
| + shape = CreatePhysicsNode(pos, shape_def.dynamic, shape_def.tag) |
| + AddChildShape(shape, shape_def, true) |
| else |
| - assert(false) |
| + assert(false, 'invalid shape type: ' .. shape_def.type) |
| end |
| -end |
| ---- Create a physics sprite at a fiven location with a given image |
| -function drawing.CreateSprite(sprite_def) |
| - local pos = util.PointFromLua(sprite_def.pos) |
| - -- util.Log('Create sprite [tag=' .. sprite_def.tag .. ' image=' .. sprite_def.image .. ']: ' .. |
| - -- util.PointToString(pos)) |
| - local image = game_obj.assets[sprite_def.image] |
| - local sprite = CCPhysicsSprite:create(image) |
| - local dynamic = not sprite_def.sensor |
| - local body = InitPhysicsSprite(sprite, pos, dynamic) |
| - body:SetUserData(sprite_def.tag) |
| + if shape_def.anchor then |
| + local body = shape:getB2Body() |
| + local anchor = util.PointFromLua(shape_def.anchor) |
| + CreatePivot(anchor, body) |
| + end |
| - AddSphereToBody(body, pos, sprite:boundingBox().size.height/2, sprite_def.sensor) |
| - return sprite |
| + return shape |
| end |
| --- Create a single circlular point with the brush. |
| --- This is used to start shapes that the use draws. The starting |
| --- point contains the box2d body for the shape. |
| +-- This is used to start shapes that the user draws. The returned |
| +-- node is the an invisible node that acts as the physics objects. |
| +-- Sprite nodes are then attached to this as the user draws. |
| function drawing.DrawStartPoint(location, color, tag, dynamic) |
| - -- Add visible sprite |
| - local sprite = DrawPhysicsBrush(location, color, tag, dynamic) |
| + -- Add invisibe physics node |
| + local node = CreatePhysicsNode(location, dynamic, tag) |
| + CreateBrushBatch(node) |
| + |
| + -- Add visiable sprite |
| + local sprite = CCSprite:createWithTexture(brush_tex) |
| + sprite:setColor(color) |
| + node:addChild(sprite) |
| -- Add collision info |
| - local fixture = AddSphereToBody(sprite:getB2Body(), location, brush_thickness, false) |
| + local fixture = AddSphereToBody(node:getB2Body(), location, brush_thickness, false) |
| SetCategory(fixture, DRAWING_CATEGORY) |
| - return sprite |
| + return node |
| end |
| --- Create a circle composed of brush sprites backed by a single box2d |
| -- circle fixture. |
| function drawing.DrawCircle(center, radius, color, tag) |
| - -- Create an initial, invisble sprite at the center, to which we |
| - -- attach a sequence of visible child sprites |
| + -- Create the initial (invisible) node at the center |
| + -- and then attach a sequence of visible child sprites |
| + local node = CreatePhysicsNode(center, true, tag) |
| + local batch_node = CreateBrushBatch(node) |
| local inner_radius = math.max(radius - brush_thickness, 1) |
| local circumference = 2 * math.pi * inner_radius |
| local num_sprites = math.max(circumference / brush_step, 1) |
| local angle_delta = 2 * math.pi / num_sprites |
| - -- The firsh brush draw is the origin of the physics object. |
| - local start_point = ccp(center.x + inner_radius, center.y) |
| - local sprite = DrawPhysicsBrush(start_point, color, tag) |
| - |
| - local start_offset = ccp(start_point.x - center.x, start_point.y - center.y) |
| - |
| - local anchor = sprite:getAnchorPointInPoints() |
| - util.Log('drawing circle: radius=' .. math.floor(radius) .. ' sprites=' .. num_sprites) |
| - util.Log('drawing circle: anchor=' .. util.PointToString(anchor)) |
| - for angle = angle_delta, 2 * math.pi, angle_delta do |
| + util.Log('drawing circle: radius=' .. math.floor(radius) .. ' sprites=' .. math.floor(num_sprites)) |
| + for angle = 0, 2 * math.pi, angle_delta do |
| x = inner_radius * math.cos(angle) |
| y = inner_radius * math.sin(angle) |
| - local pos = ccp(x - start_offset.x + anchor.x, y - start_offset.y + anchor.y) |
| - DrawBrush(sprite, pos, color) |
| + DrawBrush(batch_node, ccp(x, y), color) |
| end |
| -- Create the box2d physics body to match the sphere. |
| - local fixture = AddSphereToBody(sprite:getB2Body(), center, radius, false) |
| + local fixture = AddSphereToBody(node:getB2Body(), center, radius, false) |
| SetCategory(fixture, DRAWING_CATEGORY) |
| - |
| - return sprite |
| + return node |
| end |
| -function drawing.DrawEndPoint(sprite, location, color) |
| +function drawing.DrawEndPoint(node, location, color) |
| -- Add visible sprite |
| local child_sprite = CCSprite:createWithTexture(brush_tex) |
| - local relative_x = location.x - sprite:getPositionX() |
| - local relative_y = location.y - sprite:getPositionY() |
| - local brush_size = brush_tex:getContentSizeInPixels() |
| - child_sprite:setPosition(ccp(relative_x + brush_size.width/2, relative_y + brush_size.height/2)) |
| + local relative_x = location.x - node:getPositionX() |
| + local relative_y = location.y - node:getPositionY() |
| + child_sprite:setPosition(ccp(relative_x, relative_y)) |
| child_sprite:setColor(color) |
| - sprite:addChild(child_sprite) |
| + node:addChild(child_sprite) |
| -- Add collision info |
| - local body = sprite:getB2Body() |
| - local fixture = AddSphereToBody(body, location, sprite:boundingBox().size.height/2, false) |
| + local body = node:getB2Body() |
| + local fixture = AddSphereToBody(body, location, brush_thickness, false) |
| SetCategory(fixture, DRAWING_CATEGORY) |
| end |
| function drawing.AddLineToShape(sprite, from, to, color) |
| - fixture = AddLineToShape(sprite, from, to, color) |
| + fixture = AddLineToShape(sprite, from, to, color, true) |
| SetCategory(fixture, DRAWING_CATEGORY) |
| end |
| @@ -323,6 +359,10 @@ function drawing.OnTouchBegan(x, y) |
| return false |
| end |
| + if drawing.mode == drawing.MODE_SELECT then |
| + return false |
| + end |
| + |
| start_pos = ccp(x, y) |
| last_pos = start_pos |
| @@ -375,7 +415,6 @@ function drawing.OnTouchMoved(x, y) |
| current_shape.node = drawing.DrawStartPoint(start_pos, brush_color, tag) |
| drawing.AddLineToShape(current_shape.node, start_pos, new_pos, brush_color) |
| - |
| elseif drawing.mode == drawing.MODE_CIRCLE then |
| local tag = current_shape.node:getTag() |
| drawing.DestroySprite(current_shape.node) |