What is the difference between balances[owner] and balances[plot.owner]? - ethereum

I'm learning Solidity via this https://medium.com/coinmonks/ethereum-land-marketplace-dapp-tutorial-part-1-create-and-deploy-a-smart-contract-351bc0d62be2
There's a function below that I don't know the difference between balances[owner] and balances[plot.owner].
function buyPlot(uint index) public payable {
Plot storage plot = plots[index];
require(msg.sender != plot.owner && plot.forSale && msg.value >= plot.price);
if(plot.owner == 0x0) {
balances[owner] += msg.value;
}else {
balances[plot.owner] += msg.value;
}
plot.owner = msg.sender;
plot.forSale = false;
emit PlotOwnerChanged(index);
}
Does it mean, if no one owns the plot (where plot.owner == 0x0) then pay the funds to the owner of the smart contract (the creator) or first owner of the land?
Here's the entire code.
pragma solidity ^0.4.11;
contract LandContract {
address owner;
mapping (address => uint) public balances;
struct Plot {
address owner;
bool forSale;
uint price;
}
Plot[12] public plots;
event PlotOwnerChanged(
uint index
);
event PlotPriceChanged(
uint index,
uint price
);
event PlotAvailabilityChanged(
uint index,
uint price,
bool forSale
);
constructor() public {
owner = msg.sender;
plots[0].price = 4000;
plots[0].forSale = true;
plots[1].price = 4000;
plots[1].forSale = true;
plots[2].price = 4000;
plots[2].forSale = true;
plots[3].price = 4000;
plots[3].forSale = true;
plots[4].price = 4000;
plots[4].forSale = true;
plots[5].price = 4000;
plots[5].forSale = true;
plots[6].price = 4000;
plots[6].forSale = true;
plots[7].price = 4000;
plots[7].forSale = true;
plots[8].price = 4000;
plots[8].forSale = true;
plots[9].price = 4000;
plots[9].forSale = true;
plots[10].price = 4000;
plots[10].forSale = true;
plots[11].price = 4000;
plots[11].forSale = true;
}
function putPlotUpForSale(uint index, uint price) public {
Plot storage plot = plots[index];
require(msg.sender == plot.owner && price > 0);
plot.forSale = true;
plot.price = price;
emit PlotAvailabilityChanged(index, price, true);
}
function takeOffMarket(uint index) public {
Plot storage plot = plots[index];
require(msg.sender == plot.owner);
plot.forSale = false;
emit PlotAvailabilityChanged(index, plot.price, false);
}
function getPlots() public view returns(address[], bool[], uint[]) {
address[] memory addrs = new address[](12);
bool[] memory available = new bool[](12);
uint[] memory price = new uint[](12);
for (uint i = 0; i < 12; i++) {
Plot storage plot = plots[i];
addrs[i] = plot.owner;
price[i] = plot.price;
available[i] = plot.forSale;
}
return (addrs, available, price);
}
function buyPlot(uint index) public payable {
Plot storage plot = plots[index];
require(msg.sender != plot.owner && plot.forSale && msg.value >= plot.price);
if(plot.owner == 0x0) {
balances[owner] += msg.value;
}else {
balances[plot.owner] += msg.value;
}
plot.owner = msg.sender;
plot.forSale = false;
emit PlotOwnerChanged(index);
}
function withdrawFunds() public {
address payee = msg.sender;
uint payment = balances[payee];
require(payment > 0);
balances[payee] = 0;
require(payee.send(payment));
}
function destroy() payable public {
require(msg.sender == owner);
selfdestruct(owner);
}
}

Yes, plot.owner is the person who owns a plot. Whereas the owner is the person who deployed the contract. You could think of it as if any plot that has not been bought yet belongs to the owner, that is the person who deployed the contract (assuming he did not transfer the ownership to anyone else), so when you buy a property that was not previously owned by anyone then the money will go to the owner of the contract

Related

Solidity,private function can't return value

The code below can't estimate gasLimit by metamask, force send transaction failed also.
function calc(uint256 _boughtTokenAmount) private returns (uint256) {
/* uint256 _circle = safeSub(now, startTime) % circleSecs; */
uint256 _circle = 2;
if(_circle == 0){
return _boughtTokenAmount;
}else{
uint256 _d = safeMul(100 , safeSub(lastCircle, 1));
uint256 _n = safeSub(_d, safeMul(safeSub(_circle, 1), safeSub(attenuationCoefficient0 ,attenuationCoefficient)));
uint256 _ret = safeMul(_boughtTokenAmount, _n);
testRet = _ret;
_ret = _ret/_d;
testRet1 = _ret;
return uint(_ret);
}
}
If change the last line 'return uint(_ret)' to 'return _boughtTokenAmount',this code works, and variable '_d', '_n', 'testRet1' got expected value.
So my question is, how the return the variable '_ret'.
Thanks.

e+ is added with string after converting from integer

After converting integer into string , at compile time string add up with e+
like in trace i am getting value 90 and in swf it is showing 9.0e+
percentage function and teamxml functions are added below.
public function getPlayerAttack(ourTeam:Boolean=true):String{
var attackArr:Array=[];
var num:int;
var total:int=0;
var _teamXML:XML;
if (ourTeam)
_teamXML=getOurTeamXml();
else
_teamXML=getOppTeamXml();
for each (var playerList:XML in _teamXML.player.(#gp!="0")){
if (playerList.#name!="TEAM"){
var attackStat:String=getStat("attack_kills",playerList);
num = int(attackStat);
if(num >= 10)
{
total += num;
attackArr.push(num);
}
}
}
var attackPer:int = getPercent(total,attackArr.length);
var mytext:String = String(attackPer);
trace(typeof mytext);
return mytext;
}
public function getPercent(att:int,made:int):int{
if (made==0)
return 0;
return Math.round((made/att)*100);
}
public function getOurTeamXml():XML{
if (homeGame)
return xml.team.(#vh=="H")[0];
else
return xml.team.(#vh=="V")[0];
}
public function getOppTeamXml():XML{
if (homeGame)
return xml.team.(#vh=="V")[0];
else
return xml.team.(#vh=="H")[0];
}

Change handler not triggering the first time in Flex

I use a multiple-check Drop-Down which does not trigger the first Change event. Subsequent events trigger properly. When I select Select All or any other option the first time it does not trigger the event either.
use namespace mx_internal;
[Style(name="selectAllBorderAlpha", type="Number", inherit="no", theme="spark, mobile", minValue="0.0", maxValue="1.0")]
[Style(name="selectAllBorderColor", type="uint", format="Color", inherit="no", theme="spark, mobile")]
[Style(name="selectAllBorderVisible", type="Boolean", inherit="no", theme="spark, mobile")]
[Style(name="selectAllBackgroundColor", type="uint", format="Color", inherit="no", theme="spark, mobile")]
[Style(name="selectAllBackgroundAlpha", type="Number", inherit="no", theme="spark, mobile", minValue="0.0", maxValue="1.0")]
[IconFile("DropDownList.png")]
[DiscouragedForProfile("mobileDevice")]
public class CheckBoxDropDownList extends CheckBoxDropDownListBase
{
public function CheckBoxDropDownList()
{
super();
addEventListener(IndexChangeEvent.CHANGE, indexChangeHandler);
}
protected function indexChangeHandler(event:IndexChangeEvent):void
{
selectedAll = false;
}
[SkinPart(required="false")]
public var selectAllCheckBox:CheckBox;
[SkinPart(required="false")]
public var selectAllHitArea:UIComponent;
[SkinPart(required="false")]
public var labelDisplay:IDisplayText;
private var labelChanged:Boolean = false;
private var labelDisplayExplicitWidth:Number;
private var labelDisplayExplicitHeight:Number;
private var sizeSetByTypicalItem:Boolean;
override public function get baselinePosition():Number
{
return getBaselinePositionForPart(labelDisplay as IVisualElement);
}
private var _prompt:String = "";
[Inspectable(category="General", defaultValue="")]
public function get prompt():String
{
return _prompt;
}
public function set prompt(value:String):void
{
if (_prompt == value)
return;
_prompt = value;
labelChanged = true;
invalidateProperties();
}
[Inspectable(category="Data")]
override public function set typicalItem(value:Object):void
{
super.typicalItem = value;
invalidateSize();
}
override protected function commitProperties():void
{
super.commitProperties();
if (labelChanged)
{
labelChanged = false;
updateLabelDisplay();
}
if (selectedAllChanged)
{
selectedAllChanged = false;
if (selectAllCheckBox)
{
selectAllCheckBox.selected = _selectedAll;
this.dispatchEvent(new Event("selectAllChanged"));
}
invalidateList();
}
}
override protected function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
if (instance == labelDisplay)
{
labelChanged = true;
invalidateProperties();
}
if (instance == selectAllCheckBox)
{
selectedAllChanged = true;
invalidateProperties();
}
if (instance == selectAllHitArea)
{
selectAllHitArea.addEventListener(MouseEvent.CLICK, selectAllHitArea_clickHandler);
}
}
override protected function partRemoved(partName:String, instance:Object):void
{
super.partRemoved(partName, instance);
if (instance == selectAllHitArea)
{
selectAllHitArea.removeEventListener(MouseEvent.CLICK, selectAllHitArea_clickHandler);
}
}
protected function selectAllHitArea_clickHandler(event:MouseEvent):void
{
if (selectAllCheckBox)
selectedAll = !selectAllCheckBox.selected;
}
private var _selectedAll:Boolean = false;
private var selectedAllChanged:Boolean;
public function get selectedAll():Boolean
{
return _selectedAll;
}
public function set selectedAll(value:Boolean):void
{
if (value == _selectedAll)
return;
_selectedAll = value;
selectedAllChanged = true;
labelChanged = true;
selectedIndices = Vector.<int>([]);
//setSelectedItem(undefined, false);
invalidateProperties();
}
public function setSelectedIndices(selValues:Array):void
{
if (this.dataProvider == null) {
return;
}
var selIndices:Vector.<int> = new Vector.<int>();
if (selValues == null || selValues.length == 0)
{
this.selectedAll = true;
return;
}
for(var i:int=0; i < this.dataProvider.length; i++)
{
for(var j:int=0; j < selValues.length; j++)
{
var obj:Object = this.dataProvider.getItemAt(i);
if(selValues[j] == obj.value || selValues[j] == obj.label)
{
selIndices.push(i);
break;
}
}
}
if (selIndices.length == 0)
{
this.selectedAll = true;
}
else
{
this.selectedAll = false;
this.selectedIndices = selIndices;
}
}
override protected function item_mouseDownHandler(event:MouseEvent):void
{
if (selectedAll)
{
selectedAll = false;
var newIndex:int
if (event.currentTarget is IItemRenderer)
newIndex = IItemRenderer(event.currentTarget).itemIndex;
else
newIndex = dataGroup.getElementIndex(event.currentTarget as IVisualElement);
var arr:Array = dataProvider.toArray()
arr.splice(newIndex, 1);
selectedItems = Vector.<Object>(arr);
return;
}
super.item_mouseDownHandler(event);
// if all items are selected, then unselect them and check the "Select All" checkbox.
if (selectedItems.length == dataProvider.length)
{
selectedAll = true;
selectedIndex = -1;
}
}
override protected function dropDownController_closeHandler(event:DropDownEvent):void
{
super.dropDownController_closeHandler(event);
// Automatically selected all items if no items are selected when closing the dropDown.
if (selectedItems.length == 0 && !selectedAll)
selectedAll = true;
}
override protected function measure():void
{
var labelComp:TextBase = labelDisplay as TextBase;
// If typicalItem is set, then use it for measurement
if (labelComp && typicalItem != null)
{
// Save the labelDisplay's dimensions in case we clear out typicalItem
if (!sizeSetByTypicalItem)
{
labelDisplayExplicitWidth = labelComp.explicitWidth;
labelDisplayExplicitHeight = labelComp.explicitHeight;
sizeSetByTypicalItem = true;
}
labelComp.explicitWidth = NaN;
labelComp.explicitHeight = NaN;
// Swap in the typicalItem into the labelDisplay
updateLabelDisplay(typicalItem);
UIComponentGlobals.layoutManager.validateClient(skin, true);
// Force the labelDisplay to be sized to the measured size
labelComp.width = labelComp.measuredWidth;
labelComp.height = labelComp.measuredHeight;
// Set the labelDisplay back to selectedItem
updateLabelDisplay();
}
else if (labelComp && sizeSetByTypicalItem && typicalItem == null)
{
// Restore the labelDisplay to its original size
labelComp.width = labelDisplayExplicitWidth;
labelComp.height = labelDisplayExplicitHeight;
sizeSetByTypicalItem = false;
}
super.measure();
}
override mx_internal function updateLabelDisplay(displayItem:* = undefined):void
{
if (labelDisplay)
{
if (displayItem == undefined)
{
if (selectedItems != null && selectedItems.length > 1)
displayItem = VectorUtils.vectorToArray(selectedItems, Object);
else
displayItem = selectedItem;
}
if (displayItem != null && displayItem != undefined)
if (displayItem is Array)
{
this.toolTip = selectedItemsToLabel(displayItem, labelField, labelFunction);
labelDisplay.text = (displayItem as Array).length + " selected";
}
else
{
this.toolTip = null;
labelDisplay.text = selectedItemsToLabel(displayItem, labelField, labelFunction);
}
else if (selectedAll)
labelDisplay.text = "All";
else
labelDisplay.text = prompt;
}
}
private function invalidateList():void
{
if (dataGroup == null)
return;
for each (var itemIndex:int in dataGroup.getItemIndicesInView())
{
var renderer:UIComponent = dataGroup.getElementAt(itemIndex) as UIComponent;
if (renderer)
renderer.invalidateDisplayList();
}
}
private function selectedItemsToLabel(item:Object, labelField:String=null, labelFunction:Function=null):String
{
if (labelFunction != null)
return labelFunction(item);
var collection:ICollectionView = null;
if (item is Array)
{
collection = new ArrayCollection(item as Array);
}
else if (item is ICollectionView)
{
collection = ICollectionView(item);
}
else if (item is IList)
{
collection = new ListCollectionView(IList(item));
}
if (collection != null)
{
var itemLabels:Array = [];
for each (var obj:Object in collection)
{
itemLabels.push(obj[labelField]);
}
return itemLabels.join(", ");
}
return LabelUtil.itemToLabel(item, labelField, labelFunction);
}
public function get selectedValues():Array
{
var arr:Array = [];
if(selectedItems != null && selectedItems.length > 0)
{
for each (var obj:Object in selectedItems)
arr.push(obj.value);
}
return arr;
}
public function get selectedLabels():Array
{
var arr:Array = [];
if(selectedItems != null && selectedItems.length > 0)
{
for each (var obj:Object in selectedItems)
arr.push(obj.label);
}
return arr;
}
}
Try to call super() after the addEventListener() in the constructor function

ActionScript3 : Argument Error on constructor

I have a real problem on an ActionScript homework. I have to program a solitaire, and I'm now stuck on a bug that I don't understand.
When I launch my game object, it instanciates a CardDeck object, and fill its array with Card objects. But since my last edit, a "ArgumentError: Error #1063" is thrown every 2 seconds, and i just don't get why. I've looked and tried the few topics related to this Error, but I didn't manage to make it work ...
Here are my classes :
Card.as
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.*;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Card extends MovieClip
{
public static const COLOR_RED:int = 1;
public static const COLOR_BLACK:int = 2;
public static const SYMBOL_HEART:int = 1;
public static const SYMBOL_DIAMOND:int = 2;
public static const SYMBOL_SPADE:int = 3;
public static const SYMBOL_CLUB:int = 4;
public var game:Game;
private var t:Timer; // For click/double click fix
private var currentTarget:Card;
public var container:CardStack;
public var color:int;
public var symbol:int;
public var value:int;
public var isVisible:Boolean = false;
public function Card(type:int, value:int, g:Game)
{
game = g;
if (type == SYMBOL_HEART || type == SYMBOL_DIAMOND)
this.color = COLOR_RED;
else
this.color = COLOR_BLACK;
this.symbol = type;
this.value = value;
this.doubleClickEnabled = true;
this.addEventListener(MouseEvent.CLICK, Click);
this.addEventListener(MouseEvent.DOUBLE_CLICK, doubleClick);
}
private function doubleClick(e:MouseEvent):void
{
t.removeEventListener(TimerEvent.TIMER_COMPLETE, onCardClick);
if (t.running)
t.stop();
onCardDoubleClick(e);
}
private function Click(e:MouseEvent):void
{
currentTarget = (Card)(e.currentTarget);
t = new Timer(100,1);
t.addEventListener(TimerEvent.TIMER_COMPLETE, onCardClick);
t.start();
}
public function isSameColor(otherCard:Card):Boolean
{
if (this.color == otherCard.color)
return true;
else
return false;
}
public function setVisible(flipped:Boolean):void
{
if (flipped == true)
{
isVisible = true;
gotoAndStop(value);
}
else {
isVisible = false;
gotoAndStop(14);
}
game.pStage.addChild(this);
}
public function setInvisible():void
{
removeListeners();
game.pStage.removeChild(this);
}
public function removeListeners():void
{
this.removeEventListener(MouseEvent.CLICK, Click);
this.removeEventListener(MouseEvent.DOUBLE_CLICK, doubleClick);
}
private function onCardClick(e:TimerEvent):void
{
var card:Card = currentTarget;
if (this.isVisible == true) {
if (game.flagSelecting == false) {
if (!(card.container == game.deck && game.deck.isHeadCard(card) == false))
game.select.addToSelect(card);
}else{
if (card.container == game.deck)
game.deck.lastPickedCard--;
game.mvOutCard(game.select.tSelect, card.container);
}
}else {
if (((card.container.deckSize()) - 1) == (game.selCard(card, card.container)))
card.setVisible(true);
}
}
private function onCardDoubleClick(e:MouseEvent):void
{
var card:Card = (Card)(e.currentTarget);
// Acestack
if (game.aceStacks.canMoveTo(card) == true)
{
game.moveToAce(card);
}
//K sur place libre
if (card.value == 13) {
var freeStack:CardStack = (game.river.hasFreeStack());
if (freeStack != null){
game.select.addToSelect(card);
game.moveKing(game.select.tSelect, freeStack);
}
}
game.select.reinitSelection();
}
}
CardDeck.as
import Math;
import flash.events.MouseEvent;
import flash.events.Event;
public class CardDeck extends CardStack
{
// THIS IS ABOUT CARDDECK
public var lastPickedCard:int = 0;
public var isEmptyNow:Boolean = false;
// THIS IS ABOUT HANDSTACK
public var handStack:Array = new Array();
public static const X_FIRST_HANDCARD:int = 120;
public static const X_CARD_PADDING:int = 18;
public static const Y_HANDSTACK:int = 62;
public function CardDeck(g:Game)
{
trace("GAME" + g);
var a:Array = new Array();
var nGame:Game = g;
super(a,g);
trace("CONSTRUCTEUR2");
var i:int = 1;
while (i <= 52)
{
if (i < 14)
this.deck.push(new HeartCard(i,g));
else if (i >= 14 && i < 27)
this.deck.push(new DiamondCard(i - 13, g));
else if (i >= 27 && i < 40)
this.deck.push(new SpadeCard(i - 26, g));
else if (i >= 40)
this.deck.push(new ClubCard(i - 39, g));
i++;
}
trace("CONSTRUCTEUR3");
var nDeck:Array;
nDeck = new Array();
var idx:int;
while(this.deck.length > 0){
var r:int = Math.random()*(this.deck.length);
idx = (Math.floor(r));
//deck[idx].container = game.deck;
nDeck.push(deck.splice(idx, 1)[0]);
}
trace("CONSTRUCTEUR4");
this.deck = nDeck;
this.addEventListener(MouseEvent.CLICK, onDeckClick);
this.game.pStage.addChild(this);
this.x = 46;
this.y = 62;
trace("CONSTRUCTEUR5");
}
private function onDeckClick(e:MouseEvent):void
{
trace("LISTENER");
if (isEmptyNow == false)
fillHand();
else
setFilled();
}
public function setEmpty():void
{
this.alpha = .2;
this.isEmptyNow = true;
}
public function setFilled():void
{
this.alpha = 1;
this.isEmptyNow = false;
this.reinitHS();
}
// HANDSTACK
public function showHand():void
{
var i:int = 0;
while (i < (this.handStack.length)) {
trace("SHOW HAND");
handStack[i].setVisible(true);
handStack[i].y = Y_HANDSTACK;
handStack[i].x = X_FIRST_HANDCARD + (i * X_CARD_PADDING);
i++;
}
this.setDepth();
}
public function fillHand():void
{
trace("FILL");
if(lastPickedCard < (deck.length)-3)
this.handStack = this.deck.slice(deck.lastPickedCard, 3);
else {
this.handStack = this.deck.slice(game.deck.lastPickedCard);
this.setEmpty();
}
showHand();
}
public function reinitHS():void {
var i:int = 0;
while (i < (this.handStack.length)) {
handStack[i].setInvisible();
i++;
}
this.handStack = new Array();
}
public function isHeadCard(c:Card):Boolean
{
if (handStack.indexOf(c) == handStack.length -1)
return true;
else
return false;
}
}
CardStack.as
import flash.display.MovieClip;
public class CardStack extends MovieClip
{
public var deck:Array;
public var game:Game;
public function CardStack(newDeck:Array, g:Game)
{
game = g;
this.deck = newDeck;
}
public function isEmpty():Boolean {
if (this.deck.lenght == 0)
return true;
else
return false;
}
public function setDepth():void
{
var i:int = 0;
while (i < (this.deck.length))
{
if (i == 0)
this.deck[i].parent.setChildIndex(this.deck[i], 1);
else
this.deck[i].parent.setChildIndex(this.deck[i], 1 + i);
i++;
}
}
public function deckSize():int {return (this.deck.length);}
}
I call this here :
public function Game(pS:Stage)
{
pStage = pS;
select = new Selection(this);
trace("flag");
deck = new CardDeck(this);
trace("flag2");
aceStacks = new AceRiver(this);
river = new River(deck.deck, this);
}
And I get this exception :
ArgumentError: Error #1063: Argument count mismatch on CardDeck(). Expected 1, got 0
Any help would be really appreciated !
Stab in the dark; assuming that the only line that calls CardDeck() is:
deck = new CardDeck(this);
then I would ask, are you using more than one swf file in your project and loading one in at runtime? If so, try rebuilding all of your swfs that reference the CardDeck class.

how to trace "depth" or stacking order of a display object?

How can you trace the "depth" or stacking order of a display object with AS3?
I'm trying to figure out if my sprite is behind another sprite...
container.getChildIndex(displayObject);
but that will only tell you how deep it is, not necessarily if anything is in front of it.
Function comparing two DisplayObject instances to determine which one is at a higher "depth" on the display list:
private function higher(a:DisplayObject, b:DisplayObject):DisplayObject
{
// Parent chains
var ac:Array = [a];
var bc:Array = [b];
// Pointers to individual nodes
var an:DisplayObject = a.parent;
var bn:DisplayObject = b.parent;
while (an != null) {
ac.push(an);
an = an.parent;
}
while (bn != null) {
bc.push(bn);
bn = bn.parent;
}
var acl:int = ac.length;
var bcl:int = bc.length;
var n:int = Math.min(acl, bcl);
var i:int = 0;
for (; i < n; i++) {
an = ac[acl - i - 1];
bn = bc[bcl - i - 1];
// First uncommon ancestor
if (an != bn)
break;
}
var ca:DisplayObjectContainer = an.parent;
if (!ca)
return null;
if (ca.getChildIndex(an) > ca.getChildIndex(bn))
return a;
else
return b;
}
Note: If one of the objects is not on the display list, the function returns null. You can change it to return the other object instead.
You can almost certainly optimize this, but this is a first cut.
Just a refactored version of Manish answer using vectors and which won't return weird result if you ever call higher(a,a.parent).
parents() may be used for other purpose too :
public function higher(a:DisplayObject, b:DisplayObject):DisplayObject
{
var aParents:Vector.<DisplayObject> = parents(a);
var bParents:Vector.<DisplayObject> = parents(b);
var commonDepth:int = Math.min(aParents.length, bParents.length);
for (var depth:int = 0; depth < commonDepth; depth++)
if (aParents[depth] != bParents[depth])
break;
if (depth == 0 || depth == commonDepth)
return null;
var commonAncestor:DisplayObjectContainer = aParents[depth].parent;
if (commonAncestor.getChildIndex(aParents[depth]) > commonAncestor.getChildIndex(bParents[depth]))
return a;
else
return b;
}
private function parents(d:DisplayObject):Vector.<DisplayObject>
{
var result:Vector.<DisplayObject> = new Vector.<DisplayObject>;
while (d != null)
{
result.unshift(d);
d = d.parent;
}
return result;
}
private function getDepth(clip:DisplayObject):uint
{
var depth:uint = 0;
var currentClip:DisplayObject = clip;
while (currentClip.parent && currentClip.parent != this)
{
depth++;
currentClip = currentClip.parent;
}
return depth;
}
container.getChildIndex(child) should do it, it returns the index of the child
This is a revised version of what jauboux did from a version Manish did.
Namely, adding a null return value from highestOf() when depths match.
/**
* #param ifDepthsMatchReturnObjectA
* #return Whichever DisplayObject is higher on the display list.
* Optionally returns `null` if they're at the same depth.
*/
public function highestOf(a:DisplayObject, b:DisplayObject, ifDepthsMatchReturnObjectA:Boolean = false):DisplayObject
{
var aParents:Vector.<DisplayObject> = ancestorsOf(a);
var bParents:Vector.<DisplayObject> = ancestorsOf(b);
var commonDepth:int = Math.min(aParents.length, bParents.length);
for (var depth:int = 0; depth < commonDepth; depth++)
if (aParents[depth] != bParents[depth])
break;
if (depth == 0 || depth == commonDepth)
return null;
var commonAncestor:DisplayObjectContainer = aParents[depth].parent;
var aDepthOnCommonAncestor:int = commonAncestor.getChildIndex(aParents[depth]);
var bDepthOnCommonAncestor:int = commonAncestor.getChildIndex(bParents[depth]);
if (aDepthOnCommonAncestor > bDepthOnCommonAncestor)
return a;
else if (aDepthOnCommonAncestor < bDepthOnCommonAncestor)
return b;
else
return ifDepthsMatchReturnObjectA ? a : null;
}
/**
* #return Whether a is higher than b.
*/
public function isHigher(a:DisplayObject, b:DisplayObject):Boolean
{
return highestOf(a, b) === a;
}
/**
* #return All ancestors of given display.
*/
private function ancestorsOf(display:DisplayObject):Vector.<DisplayObject>
{
var result:Vector.<DisplayObject> = new Vector.<DisplayObject>;
while (display != null)
{
result.unshift(display);
display = display.parent;
}
return result;
}