Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Solution to fix nested groups in G2.0?
Started by kilopop Apr 18 2014 04:04 AM

21 replies to this topic
[TOPIC CONTROLS]
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

As recently established in the forum and confirmed by Corona staff, groups containing other groups with anchorChildren = true produces unpredictable results. The upshot is nested groups and layers with different anchor points no longer work in G2 whereas they did in G1.. Is this a bug or is there another name for a feature that used to be possible but no no longer is?

 

Hopefully this is a temporary situation. But we can't wait around until it is fixed, so have started writing a function to implement nested groups that can have different anchor points.

 

The following code uses the example of a few shapes to make a vehicle. It is made up of a group with 3 other groups inserted, each of which can have its own anchor position.

 

So far, the code is nearly there.. It can take an object where ever it is on the screen and put the anchor where you provide to the anchorGroup function with object name and the new anchors x and y e.g.

 

anchorGroup(box, 1,1)

 

The trick is not to use anchorChildren = true which is where the crazy factor enters the equation with unpredictable results. Instead, images and groups are sent by their center point to 0,0, anchors added and then sent back to its original position via contentBounds.

 

Problem is that once groups are inserted into groups, changing the anchor to anything other than 0.5, 0.5 does provide an offset effect which leads to unpredictable effects. G1 also allowed referencePoints to be changed on an object without that object changing position which is possible on the first run of this function on an object but not if you call it again..

 

This is where some help would be fantastic. Hope it's all clear and someone is up for the challenge of bringing back some of the awesomeness of setReference..

 

 

local gp_carBody = display.newGroup()
local gp_wheel1 = display.newGroup()
local gp_wheel2 = display.newGroup()
local gp_car = display.newGroup()

-- Anchor Group

local function anchorGroup (obj, anchorX, anchorY)

	local obj = obj
	local anchorNewX = anchorX or 0.5
	local anchorNewY = anchorY or 0.5
	local anchorOldX = obj.anchorX or 0.5
	local anchorOldY = obj.anchorY or 0.5

	local offsetX = obj.width * ( anchorNewX - anchorOldX ) 
	local offsetY = obj.height * ( anchorNewY - anchorOldY )

	local centerX = obj.x
	local centerY = obj.y

	-- Determine whether obj is a single image (numChildren = nil) or a group that has already been prepped for anchor (hasAnchor)

	if obj.numChildren ~= nil then -- NOT an image, IS a group.

		obj.hasAnchor = true

		-- CALCULATE the max and min x and y of group's children's bounding area.

		local bounds = obj.contentBounds

		centerX = (bounds.xMax - bounds.xMin) / 2 + bounds.xMin
		centerY = (bounds.yMax - bounds.yMin) / 2 + bounds.yMin

		print("center x and y = ", centerX, centerY)

		-- Move the group's children so that their relationship to the center of the group is at 0

		local objX, objY

		local i

		for i = 1, obj.numChildren do
			objX, objY = obj[i]:localToContent(0,0)
			obj[i].x = objX - centerX  - offsetX
			obj[i].y = objY - centerY  - offsetY
		end


		-- Now the Group contents are properly organised around the anchor at x and y = 0

	end

	-- Set the anchor if passed in or default to center

	--print("anchors = ", anchorOldX, anchorOldY, anchorNewX, anchorNewY)

	obj.anchorX, obj.anchorY = anchorNewX, anchorNewY

	obj.x = centerX + offsetX
	obj.y = centerY + offsetY

	print("object x and y = ", obj.x, obj.y)
	print("object width and height = ", obj.width, obj.height)
	print("--------")

end

-- body positioning
local body = display.newRect( 1472, 922, 748, 228 ) 
body:setFillColor( 255/255, 255/255, 255/255 )

-- top positioning
local top = display.newRect( 1454, 758, 276, 260 )
top:setFillColor( 255/255, 255/255, 255/255 )

-- tyre1 positioning
local tyre1 = display.newCircle( 1265, 1041, 75 )
tyre1:setFillColor( 3/255, 145/255, 222/255 )

-- cap1 positioning
local cap1 = display.newCircle( 1265, 1041, 53 )
cap1:setFillColor( 255/255, 255/255, 255/255 )

-- tyre2 positioning
local tyre2 = display.newCircle( 1689, 1041, 75 )
tyre2:setFillColor( 3/255, 145/255, 222/255 )

-- cap2 positioning
local cap2 = display.newCircle( 1689, 1041, 53 )
cap2:setFillColor( 255/255, 255/255, 255/255 )


-- Organise Groups

gp_carBody:insert(body)
gp_carBody:insert(top)
anchorGroup(gp_carBody)

gp_wheel1:insert(tyre1)
gp_wheel1:insert(cap1)
anchorGroup(gp_wheel1, 0,0)
gp_wheel1.xScale = 0.5

gp_wheel2:insert(tyre2)
gp_wheel2:insert(cap2)
anchorGroup(gp_wheel2)
gp_wheel2.xScale = 0.5

gp_car:insert(gp_carBody)
gp_car:insert(gp_wheel1)
gp_car:insert(gp_wheel2)
anchorGroup(gp_car)

-- animation

transition.to (gp_car, { time = 4000, x = -200 } )
transition.to (gp_wheel1, { time = 500, rotation = -360,  iterations=8} )
transition.to (gp_wheel2, { time = 500, rotation = -360,  iterations=8} )
transition.to (gp_carBody, { time = 250, y = -200, iterations=16, transition=easing.continuousLoop  } )


 



[TOPIC: post.html]
#2

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

Another challenge... the weekend is saved !

B)



[TOPIC: post.html]
#3

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,366 posts
  • Corona SDK

fwiw: i sort of do the opposite, and always use anchorChildren. the "trick" for me is to always include a big invisible "bounds" rectangle, so my group will have a known size. then anchorChildren will work in a reasonably sensible way (so long as you never exceed those bounds).

the "crazy" seems a byproduct of "groups have no inherent size, but take on the size of their contents" logic, so if anchorChildren is true then when the group repositions its children it also changes its own "size", so with a new size that affects the x/y derived from its anchor, so if x/y changed then move children, then affects size, so then move children, then affects size, ad inf.... which is just silly.

you can see this behavior just *inserting* into a non-bounded group as it shifts and shimmies all over the place after each addition, growing its content bounds and repositioning itself to its anchor, so good luck "guessing" where to insert the next object! :D

i banged this out to try to roughly mimic your car using this approach. you probably don't need ALL those group wrappers, but the fn was there so i used it. really the only thing of note is "bounds":
-- wrap object in group util fn
local function newWrapper(obj,x,y)
	local grp = display.newGroup()
	grp.anchorChildren = true
	if (obj) then grp:insert(obj) end
	if (x and y) then	grp.x,grp.y=x,y end
	return grp
end

-- create all parts at origin
local bounds = display.newRect(0, 0, 300, 300); bounds:setFillColor(1,1,1,0.1) -- typically bounds.isVisible=false
local body = display.newRect(0, 0, 200, 50); body:setFillColor(0.5,0.5,0.8)
local cab = display.newRect(0,0,50,50); cab:setFillColor(0.6,0.6,0.9)
local tiref = display.newCircle(0,0,30); tiref:setFillColor(0.2,0.2,0.2)
local wheelf = display.newCircle(0,0,20); wheelf:setFillColor(0.4,0.7,0.7)
local tireb = display.newCircle(0,0,30); tireb:setFillColor(0.2,0.2,0.2)
local wheelb = display.newCircle(0,0,20); wheelb:setFillColor(0.4,0.7,0.7)

-- wrap into groups and position internally
local truck = newWrapper(bounds)
local chassis = newWrapper()
	chassis:insert( newWrapper(body) )
	chassis:insert( newWrapper(cab, -25, -50) )
	truck:insert( chassis )
local wtiref = newWrapper()
	wtiref:insert( newWrapper(tiref) )
	wtiref:insert( newWrapper(wheelf) )
	wtiref.x, wtiref.y = -75, 50
	wtiref.xScale = 0.5
	truck:insert( wtiref );
local wtireb = newWrapper()
	wtireb:insert( newWrapper(tireb) )
	wtireb:insert( newWrapper(wheelb) )
	wtireb.x, wtireb.y = 75, 50
	wtireb.xScale = 0.5
	truck:insert( wtireb );

-- now position overall
truck.x, truck.y = display.contentCenterX, display.contentCenterY
-- give a fixed indication of center
-- (with animation off, the back corner of cab-at-chassis should occur here)
local center = display.newCircle(display.contentCenterX, display.contentCenterY, 5); center:setFillColor(1,0,0,0.5)

if (true) then -- animation??
	transition.to (wtireb, { time = 500, rotation = -360,  iterations=8} )
	transition.to (wtiref, { time = 500, rotation = -360,  iterations=8} )
	transition.to (chassis, { time = 250, y = -50, iterations=16, transition=easing.continuousLoop  } )
	transition.to (truck, { time = 4000, x = 200 } )
end


[TOPIC: post.html]
#4

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

Huh! Neat trick!



[TOPIC: post.html]
#5

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

Good find Dave, you've zeroed in to the exact issue with nested groups. Do you think it's worth submitting this as a bug, or are we doomed to forever adding this kind of work around everytime a group is created that needs nested animation?

 

Back to your solution Dave. Very cool trick where you put things into a temporary group to slam a layers origin into 0,0 with anchorChildren = true. You then nudge objects around in relation according to offsets you've worked out. These kind of little manual equations are another example of disruptions to work flow. In fact this is a big issue with us as our scenes are laid out in photshop with a script that outputs their positions which need to be stated when they are first created in newImageRect.

 

So the big issue is how you maintain the relationship of objects to each other in a group when you bring them through your wrapper function. So when you create the chassis group for instance you base the "body" to define the main origin of the group chassis and then adjust the position of "top" to fit with that. But how would you take a group of objects with their relation to each other sorted with their x and y already set and then use your wrapper to slam each in the temp group - how do you automate their positioning after the wrapper process to return them back to their original positioning in relation to each other - without manually passing in x and y into the wrapper?

 

Other than that, if you change the anchor point, then the object still does shift to match so some kind of offset calculation needs to about
every time you set the anchor if it's not 0.5, 0.5  This can be easily achieved with an offset function.



[TOPIC: post.html]
#6

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,366 posts
  • Corona SDK

I think (?) they intend for it to work this way. I personally can't imagine the use case that makes this way seem "better", but there must be one -- it made it out of beta afterall, so has become "entrenched", and seems unlikely they'd change it (or risk breaking those who DO know the use case).

I think you're asking if I know a way to "wrap existing content in place, thence anchored", right? If so, short answer: no. It's the "opposite" of what I've found works for me, but it would seem your method was headed that way? Perhaps some type of flow like:

create an unanchored group
add pre-positioned children
groups bounds fit children, but x/y still meaningless 0,0

have a "becomeAnchored(grp)" -type function that:

takes that populated unanchored group
calc its bounds center xy
for each child, stores its delta from center xy, puts at 0,0
grp.anchorChildren=true, grp xy now meaningful 0,0
and bounds should (? - test!) match zero'd children
for each child, put back at dx/dy
(groups bound would change, tho, so still need that big "bounds" rectangle to prevent)
put group xy at original bounds center

and your code already appears to do 90% of that, except for the anchoring (without which I think it won't really act as what you want it to, right?). now everything ?*should*? be relatively "where it was", but anchored to the group. Note that I haven't tested any of that tho, just rambling ideas off top of my head, fwiw.

[TOPIC: post.html]
#7

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

Yeah use case is very hard to determine..

 

Ok, so the bounds solution works well. It is a work around solution but it does work so that's a relief..

 

I've adapted a function which also works to adjust an object passed in with anchor points which when used with bounds also now works to set anchors and offset group content so it doesn't jump around.

 

local function anchorGroup (obj, anchorX, anchorY)

	local obj = obj
	local anchorNewX = anchorX or 0.5
	local anchorNewY = anchorY or 0.5
	local anchorOldX = obj.anchorX or 0.5
	local anchorOldY = obj.anchorY or 0.5

	local offsetX = obj.width * ( anchorNewX - anchorOldX ) 
	local offsetY = obj.height * ( anchorNewY - anchorOldY )

	if obj.numChildren ~= nil or obj.anchorChildren ~= true then -- NOT an image, IS a non anchored group

		-- CALCULATE the Center of the group.

		local bounds = obj.contentBounds

		local centerX = (bounds.xMax - bounds.xMin) / 2 + bounds.xMin
		local centerY = (bounds.yMax - bounds.yMin) / 2 + bounds.yMin

		-- Set group to this position

		obj.x, obj.y = centerX, centerY

		-- Set .anchorChildren = true to slam group origin into center

		obj.anchorChildren = true

	end

	-- Set the anchor if passed in or default to center

	obj.anchorX, obj.anchorY = anchorNewX, anchorNewY

	obj.x = obj.x + offsetX
	obj.y = obj.y + offsetY

end

The only problem now when putting groups into groups is that contents x/y relate to their position in their immediate parent without consideration for how they are offset by the parent's parent's etc.. So if you try to transition an object in a group that is in a group, you need to multiply the x and y value by 2. You also need to do the same for scale. So transitioning a group within a group to twice the xScale isn't 2 - it's 4.. Groups suuuure have changed in G2.0. Shockers.



[TOPIC: post.html]
#8

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

...if you try to transition an object in a group that is in a group, you need to multiply the x and y value by 2. You also need to do the same for scale. So transitioning a group within a group to twice the xScale isn't 2 - it's 4..

 

Really?!

Now that must be a bug. I can't think of any use-case where *that* makes any sense...



[TOPIC: post.html]
#9

jonjonsson

[GLOBAL: userInfoPane.html]
jonjonsson
  • Corona Geek

  • 1,051 posts
  • Corona SDK

Here is something I reported, maybe you have covered it.  In this example the object is first transitioned to a Y coordinate, then a second transition on the group ignores the Y position and the object is jerked back up to original position.
 
local group          = display.newGroup()
group.anchorChildren = true -- Commenting this out and nothing will jump around
group.x              = 150
group.y              = 200
 
local box = display.newRect(group, 0, 0, 90, 54)
 
transition.to(box, {time = 1000, y = box.height})
--box.y = box.height -- Comment this in + transition above out, nothing will jump around 
 
-- This transition will affect the y position of the red box, but should not
transition.to(group, {delay = 1200, time = 1000, x = 50})
 
It was deemed not a bug and Coroan said 'Setting "anchorChildren = true" on groups is not a good idea unless you have a specific need for using anchor points on groups.'
 
I gave up understanding anchored groups after that lol.


[TOPIC: post.html]
#10

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

Ingemar - Yeah seems like it.

 

Calling someone from Corona Staff. Did you know if you put a group B within group A and want to xScale or yScale to twice its size you have to use 4 not 2..?

 

jonjonsson - Definitely another one of graphic 2.0's crazy clown fun time quirks. If you swap them over and transition the group first, it does work if you then transition the object. It must be that the group doesn't know itself until you use it somehow? Then when it wakes up it assumes the child's initial position rather than taking into account where it currently is on screen.. awesome..



[TOPIC: post.html]
#11

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

It was deemed not a bug and Coroan said 'Setting "anchorChildren = true" on groups is not a good idea unless you have a specific need for using anchor points on groups.'

 

In that case I'm happy that I spent the weekend modifying my frameworks to get rid of "anchorChildren=true" on all groups.

The reason I used it in the first place was that my groups are not always symmetrical. If the shared anchor among the children isn't in the center of the group it's nearly impossible to find a way to position it where you want.

 

I struggled for a while, but I managed to find a way to reposition the children within the group so that the internal anchor effectively becomes an anchor point that can be positioned where you want it.

I've modified my alignment functions to also take care of groups now. It's still a bit early to tell, but so far I haven't seen any adverse effects when updating my existing projects. 

 

It's probably not the answer to everybody's problems, but below is an excerpt from my utilities module.

This mini version only has one public function: 

align = function(object, alignTo, x, y) 

It aligns an object / group according to the anchor point specified as a string.

 

"TL" - Top Left

"TC" - Top Center

"TR" - Top Right

"CL" - Center Left

"C" - Center

"CR" - Center Right

"BL" - Bottom Left

"BC" - Bottom Center

"BR" - Bottom Right

-- utilities.lua

local M = {};

-- -------------------------------
-- text/group alignment functions
-- -------------------------------

local setGroupAnchor = function(object)
    local anchorCoordinates = function(object)
        local xc = (object.width * object.anchorX) - object.x;
        local yc = (object.height * object.anchorY) - object.y;

        if (xc < 0 ) then
            xc = 0;
        end

        if (yc < 0) then
            yc = 0;
        end

        return xc, yc;
    end

    local internalAnchor = {x=nil, y=nil};

    -- find group;s anchor point
    for i = 1, object.numChildren do
        local xc, yc = anchorCoordinates(object[i]);

        if (not internalAnchor.x) or (xc > internalAnchor.x) then
            internalAnchor.x = xc;
        end

        if (not internalAnchor.y) or (yc > internalAnchor.y) then
            internalAnchor.y = yc;
        end
    end

    object.internalAnchor = internalAnchor;
end

local alignGroup = function(object, alignTo, x, y)
    setGroupAnchor(object);

    local alignPos = alignTo or "C";
    local xPos     = x or 0;
    local yPos     = y or 0;
    local gWidth   = object.width;
    local gHeight  = object.height;
    local xOffset  = 0;
    local yOffset  = 0;
    
    if (alignPos == "TL") then
        xOffset = object.internalAnchor.x;
        yOffset = object.internalAnchor.y;

    elseif (alignPos == "TC") then
        xOffset = object.internalAnchor.x - (gWidth / 2);
        yOffset = object.internalAnchor.y;

    elseif (alignPos == "TR") then
        xOffset = object.internalAnchor.x - gWidth;
        yOffset = object.internalAnchor.y;

    elseif (alignPos == "CL") then
        xOffset = object.internalAnchor.x;
        yOffset = object.internalAnchor.y - (gHeight / 2);

    elseif (alignPos == "CR") then
        xOffset = object.internalAnchor.x - gWidth;
        yOffset = object.internalAnchor.y - (gHeight / 2);

    elseif (alignPos == "BL") then
        xOffset = object.internalAnchor.x;
        yOffset = object.internalAnchor.y - gHeight;

    elseif (alignPos == "BC") then
        xOffset = object.internalAnchor.x - (gWidth / 2);
        yOffset = object.internalAnchor.y - gHeight;

    elseif (alignPos == "BR") then
        xOffset = object.internalAnchor.x - gWidth;
        yOffset = object.internalAnchor.y - gHeight;
        
    else -- default "C"
        xOffset = object.internalAnchor.x - (gWidth / 2);
        yOffset = object.internalAnchor.y - (gHeight / 2);
    end

    for i = 1, object.numChildren do
        object[i].x = object[i].x + xOffset;
        object[i].y = object[i].y + yOffset;
    end
    
    object.x = math.round(xPos);
    object.y = math.round(yPos);
    
    return object;
end

M.align = function(object, alignTo, x, y)
    if (object.anchorChildren ~= nil) and (not object.anchorChildren) then
        return alignGroup(object, alignTo, x, y);
    end

    local alignPos = alignTo or "C";
    local xPos = x or 0;
    local yPos = y or 0;
    
    if (alignPos == "TL") then
        object.anchorX = 0;
        object.anchorY = 0;

    elseif (alignPos == "TC") then
        object.anchorX = 0.5;
        object.anchorY = 0;

    elseif (alignPos == "TR") then
        object.anchorX = 1;
        object.anchorY = 0;

    elseif (alignPos == "CL") then
        object.anchorX = 0;
        object.anchorY = 0.5;

    elseif (alignPos == "CR") then
        object.anchorX = 1;
        object.anchorY = 0.5;

    elseif (alignPos == "BL") then
        object.anchorX = 0;
        object.anchorY = 1;

    elseif (alignPos == "BC") then
        object.anchorX = 0.5;
        object.anchorY = 1;

    elseif (alignPos == "BR") then
        object.anchorX = 1;
        object.anchorY = 1;
        
    else -- default "C"
        object.anchorX = 0.5;
        object.anchorY = 0.5;
    end
    
    object.x = math.round(xPos);
    object.y = math.round(yPos);
    
    return object;
end

return M;

 

A small sample project with 2 animated groups (with animated children) within a container group:

 

[attachment=2105:groupAnchor.zip]



[TOPIC: post.html]
#12

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

I tried scaling one of the internal groups in a transition (xScale=2, yScale=2), and it seems to work as expected, but my sample might not be complex enough to show the problem...



[TOPIC: post.html]
#13

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

Right, ok. I'll break things down and see where this size thing is occuring..

 

Glad you've got a solution that works for you. Especially good to bring back the setReference names. Can't see much use for anything other than those 9 spots. If you want to move the anchor with reference points, I always used a small non visible rect and moved that around until the group was the right shape for the anchor to fall in the right spot. Hell of a lot easier than the kind of extreme work arounds we're now faced with.

 

How does your solution work with animating, nested groups?



[TOPIC: post.html]
#14

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

I modified my post above to include a sample project (ZIP).

If you run it you'll see 2 animated groups (with animated children) within a container group.



[TOPIC: post.html]
#15

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

Cool. Nice work Ingemar, will be good to have a look :)

 

Oh and tracked down the source of the problem with scale and position is the use of transition=easing.continuousLoop in transition.to. this happens with groups or images outside of groups.



[TOPIC: post.html]
#16

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

Oh and tracked down the source of the problem with scale and position is the use of transition=easing.continuousLoop in transition.to. this happens with groups or images outside of groups.

 

confirmed.



[TOPIC: post.html]
#17

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,366 posts
  • Corona SDK

'Setting "anchorChildren = true" on groups is not a good idea unless you have a specific need for using anchor points on groups.'

Guess I'm getting old - I've heard that sort of thing too many times for it to be funny any more.

Imagine if that sort of statement were from an automobile manufacturer:
'Our brakes have unexpected behavior, so using them is not a good idea... unless you REALLY need them."

Or if from a fire extinguisher manufacturer:
'The trigger on our fire extinguishers is faulty, so we recommend that you only use it if you REALLY need it.'

Isn't the flaw in that logic evident?

In my opinion, this is an "engineering cop out" - to admit that you have "weird" behavior, and suggest that it only be used 'when needed' (as if devs go around all day wasting their time implementing stuff they DON'T need!). But, of course, if you actually DO need it that's when you're most likely to notice the weirdness!!


BTW, here's a scene from a new screenplay I'm working on, for your amusement:

Engineering: it's weird, don't use it, unless you need to.
Dev: i need to use it, but it's weird, fix it
Engineering: not our fault, we told you not to use it, won't fix
Dev: but you said i could use it if i 'needed it'!
Engineering: no, we said only if you 'specifically' needed it
Dev: what's the difference?
Engineering: we have internally redefined the word 'specifically' to cover only those uses that DON'T expose known flaws in our software - those are the 'specific' needs that are allowed.
Dev: so we are only to use that portion of your software that works correctly?
Engineering: yes, now you've got it
Dev: what about the other portion, the portion that doesn't work correctly?
Engineering: you don't 'specifically need' that portion, by definition, so stop complaining about it
Dev: ahhh, brilliant!


( :D don't take me too seriously!)

[TOPIC: post.html]
#18

jonjonsson

[GLOBAL: userInfoPane.html]
jonjonsson
  • Corona Geek

  • 1,051 posts
  • Corona SDK

I don't want accused of taking that quote out of context. Its from here with an explanation http://forums.coronalabs.com/topic/41599-fixed-transitions-jerky/?p=218568

[TOPIC: post.html]
#19

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

dave - it does sound like the engineers are calling the shots with regard to use case. I'm sure Steve Jobs would argue for engineering to follow use case not the other way around, I guess Corona lacks a visionary leader in that respect.

 

jonjonsson - also to add to your point from Tom over at http://forums.coronalabs.com/topic/42781-questions-about-anchorchildren/

 

nested groups with "anchorChildren = true" was never intended to be supported and is not tested. The property was added to support containers, which are a form of groups. Graphics 2.0 groups are not 100% compatible with Graphics 1.0 groups

 

So you can hear the debates over at Corona engineering when they programmed anchors in G2. Someone must have pointed out that they didn't work in groups so a hurried solution was found in the form of anchorChildren which wasn't tested and isn't universally supported by all the team members. Clearly some of those team members just don't think developers need to use anchors in nested groups. This just seems really short sighted to dictate only specific uses of Corona.

 

Corona engineers, if you are struggling to imagine why anyone would want to set anchors in nested groups, just think of setting up a character for animation where the parts of the body are parented together in the form of a hierarchy. That's exactly what we've been doing in Corona G1 with fantastic results. Now in G2, this is nolonger possible. To that you are effectively saying "that's fine by us, you shouldn't be using Corona to do character animation, you can no longer do that - go away."



[TOPIC: post.html]
#20

dingo

[GLOBAL: userInfoPane.html]
dingo
  • Contributor

  • 700 posts
  • Corona SDK

i am trying to get things running with anchorChidren, but it seems to be very buggy to me. has anyone come up with a neat solution to this problem yet?



[TOPIC: post.html]
#21

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

We have a library module "anchorGroups". It takes care of all the repositioning that happens when you create groups automatically. You can also use it to change the position of the anchor group on the fly without the group jumping around visibly.

 

The main problem with anchorChildren is when items within the group are moving in their own orbit and increasing the bounds of the group. What is required then is to create a null shape that is as big as the group ever gets when the item inside adjusts its position.

 

Anyway, this works great. You require it as anchorGroups:

 

local anchor = require("anchorGroups")

 

And apply it with this to a group you have created, lets say groupName:

 

anchor.new(groupName, 1, 1) -- Bottom right.

--====================================================================--
-- PROCESS GROUPS
--====================================================================--


local M = {}


-- Anchor Group

M.new = function (obj, anchorX, anchorY)

	local obj = obj 
	obj.name = obj.name or "nameless"
	--print("Group obj = ", obj.name)
	local anchorX, anchorY = anchorX, anchorY

	local anchorNewX = anchorX or 0.5
	local anchorNewY = anchorY or 0.5

	local anchorOldX = obj.anchorX or 0.5
	local anchorOldY = obj.anchorY or 0.5

	local offsetX = obj.width * ( anchorNewX - anchorOldX ) 
	local offsetY = obj.height * ( anchorNewY - anchorOldY )


	-- Determine whether obj is a single image (numChildren = nil) or a group that has already been prepped for anchor (hasAnchor)

	if obj.numChildren ~= nil then -- NOT an image, is a group

		if obj.width >0 and obj.height >0 then -- isn't an empty group

			if not obj.anchorChildren then 	-- IS a non anchored group

				-- CALCULATE the Center of the group, add to key obj.xOrig, obj.yOrig

				local bounds = obj.contentBounds

				obj.xOrig = (bounds.xMax - bounds.xMin) / 2 + bounds.xMin
				obj.yOrig = (bounds.yMax - bounds.yMin) / 2 + bounds.yMin

				--print(obj.name.." xOrig, yOrig = ", obj.xOrig, obj.yOrig)
				--print(obj.name.." xMin, xMax = ", bounds.xMin, bounds.xMax)
				--print(obj.name.." Width, height = ", bounds.xMax-bounds.xMin, bounds.yMax-bounds.yMin)

				-- Set group to this position

				obj.x, obj.y = obj.xOrig, obj.yOrig

				-- Set .anchorChildren = true to slam group origin into center

				obj.anchorChildren = true

			end

		end

	end

	-- Set the anchor if passed in or default to center

	if obj.width >0 and obj.height >0 then -- isn't an empty group

		obj.x = obj.x + offsetX
		obj.y = obj.y + offsetY

		obj.anchorX, obj.anchorY = anchorNewX, anchorNewY

		--print("imgMode = ", imgMode)
		--print(obj.name, " anchors = ", anchorNewX, anchorNewY)

	else --print (obj.name, " = an empty group")

	end

end


return M



[TOPIC: post.html]
#22

dingo

[GLOBAL: userInfoPane.html]
dingo
  • Contributor

  • 700 posts
  • Corona SDK

hi kilopop

 

thanks for the class. i gave it a try yesterday but it did not really help to solve my problems. but it was a quick run, so i hope to be wrong :).

 

right now i am using a group for the character, and inside i change sprite animations. to make it work i had to use display.newContainer instead of display.newGroup. positioning inside the group is fine now, but the parent group itself gets missplaced during gameplay (and corrected withing a few ms). an anchorX and anchorY is set on the parent group, which stays the same for all the level (so not changing any anchors etc on the parent group). pretty confusing.

 

let me try your class again!




[topic_controls]
[/topic_controls]