Add a bunch of hooks to handle finding the object the mouse is over.
git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@985 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
@@ -37,6 +37,8 @@ import flash.events.MouseEvent;
|
||||
|
||||
import mx.core.ClassFactory;
|
||||
|
||||
import as3isolib.display.IsoSprite;
|
||||
import as3isolib.display.primitive.IsoBox;
|
||||
import as3isolib.core.IsoDisplayObject;
|
||||
import as3isolib.geom.Pt;
|
||||
import as3isolib.geom.IsoMath;
|
||||
@@ -45,6 +47,7 @@ import as3isolib.display.IsoView;
|
||||
|
||||
import com.threerings.crowd.client.PlaceView;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.util.ClassUtil;
|
||||
import com.threerings.util.DelayUtil;
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.Map;
|
||||
@@ -98,9 +101,10 @@ public class MisoScenePanel extends Sprite
|
||||
_isoView.size.x, _isoView.size.y);
|
||||
|
||||
_isoView.addEventListener(MouseEvent.CLICK, onClick);
|
||||
_isoView.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoved);
|
||||
_isoView.addEventListener(MouseEvent.ROLL_OUT, mouseExited);
|
||||
|
||||
_objScene = new IsoScene();
|
||||
_objScene.layoutRenderer = new ClassFactory(PrioritizedSceneLayoutRenderer);
|
||||
addObjectScenes();
|
||||
|
||||
addChild(_loading = createLoadingPanel());
|
||||
|
||||
@@ -158,8 +162,98 @@ public class MisoScenePanel extends Sprite
|
||||
|
||||
public function onClick (event :MouseEvent) :void
|
||||
{
|
||||
// TODO - handle _hobject
|
||||
handleMousePressed(null, event);
|
||||
handleMousePressed(_hobject, event);
|
||||
}
|
||||
|
||||
public function mouseMoved (event :MouseEvent) :void
|
||||
{
|
||||
var viewPt :Point = _isoView.globalToLocal(new Point(event.stageX, event.stageY));
|
||||
|
||||
var x :int = event.stageX;
|
||||
var y :int = event.stageY;
|
||||
|
||||
// give derived classes a chance to start with a hover object
|
||||
var hobject :Object = computeOverHover(x, y);
|
||||
|
||||
// if they came up with nothing, compute the list of objects over
|
||||
// which the mouse is hovering
|
||||
if (hobject == null) {
|
||||
var hits :Array =
|
||||
_objScene.displayListChildren.filter(
|
||||
function(val :Object, idx :int, arr :Array) :Boolean {
|
||||
if (val is PriorityIsoDisplayObject) {
|
||||
return PriorityIsoDisplayObject(val).hitTest(x, y);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
hits.sort(function (v1 :PriorityIsoDisplayObject, v2 :PriorityIsoDisplayObject) :int {
|
||||
// We want reverse order, highest prio first...
|
||||
return v2.getPriority() - v1.getPriority();
|
||||
});
|
||||
|
||||
if (hits.length > 0) {
|
||||
hobject = hits[0];
|
||||
}
|
||||
}
|
||||
|
||||
// if the user isn't hovering over a sprite or object with an
|
||||
// action, allow derived classes to provide some other hover
|
||||
if (hobject == null) {
|
||||
hobject = computeUnderHover(x, y);
|
||||
}
|
||||
|
||||
changeHoverObject(hobject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives derived classes a chance to compute a hover object that takes precedence over sprites
|
||||
* and actionable objects. If this method returns non-null, no sprite or object hover
|
||||
* calculations will be performed and the object returned will become the new hover object.
|
||||
*/
|
||||
protected function computeOverHover (mx :int, my :int) :Object
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives derived classes a chance to compute a hover object that is used if the mouse is not
|
||||
* hovering over a sprite or actionable object. If this method is called, it means that there
|
||||
* are no sprites or objects under the mouse. Thus if it returns non-null, the object returned
|
||||
* will become the new hover object.
|
||||
*/
|
||||
protected function computeUnderHover (mx :int, my :int) :Object
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the hover object to the new object.
|
||||
*/
|
||||
protected function changeHoverObject (newHover :Object) :void
|
||||
{
|
||||
if (newHover == _hobject) {
|
||||
return;
|
||||
}
|
||||
var oldHover :Object = _hobject;
|
||||
_hobject = newHover;
|
||||
hoverObjectChanged(oldHover, newHover);
|
||||
}
|
||||
|
||||
/**
|
||||
* A place for subclasses to react to the hover object changing.
|
||||
* One of the supplied arguments may be null.
|
||||
*/
|
||||
protected function hoverObjectChanged (oldHover :Object, newHover :Object) :void
|
||||
{
|
||||
// Nothing by default.
|
||||
}
|
||||
|
||||
public function mouseExited (event :MouseEvent) :void
|
||||
{
|
||||
// clear the highlight tracking data
|
||||
changeHoverObject(null);
|
||||
}
|
||||
|
||||
public function handleMousePressed (hobject :Object, event :MouseEvent) :Boolean
|
||||
@@ -309,6 +403,19 @@ public class MisoScenePanel extends Sprite
|
||||
}
|
||||
}
|
||||
|
||||
protected function renderObjectScenes () :void
|
||||
{
|
||||
_objScene.render();
|
||||
}
|
||||
|
||||
protected function addObjectScenes () :void
|
||||
{
|
||||
_objScene = new IsoScene();
|
||||
_objScene.layoutRenderer = new ClassFactory(PrioritizedSceneLayoutRenderer);
|
||||
|
||||
_isoView.addScene(_objScene);
|
||||
}
|
||||
|
||||
protected function resolutionComplete () :void
|
||||
{
|
||||
// First, we add in our new blocks...
|
||||
@@ -319,11 +426,7 @@ public class MisoScenePanel extends Sprite
|
||||
}
|
||||
_readyBlocks = Sets.newSetOf(SceneBlock);
|
||||
|
||||
// Force to end of list so it's on top...
|
||||
_isoView.removeScene(_objScene);
|
||||
_isoView.addScene(_objScene);
|
||||
|
||||
_objScene.render();
|
||||
renderObjectScenes();
|
||||
|
||||
// Then we let the scene finally move if it's trying to...
|
||||
if (_pendingMoveBy != null) {
|
||||
@@ -500,6 +603,9 @@ public class MisoScenePanel extends Sprite
|
||||
/** If any block happens to resolve should we currently skip calling completion. */
|
||||
protected var _skipComplete :Boolean
|
||||
|
||||
/** Info on the object that the mouse is currently hovering over. */
|
||||
protected var _hobject :Object;
|
||||
|
||||
protected var _vbounds :Rectangle;
|
||||
|
||||
protected var _covered :Set = Sets.newSetOf(String);
|
||||
|
||||
@@ -28,5 +28,10 @@ public interface PriorityIsoDisplayObject
|
||||
* Returns the render priority for the display object.
|
||||
*/
|
||||
function getPriority () :int;
|
||||
|
||||
/**
|
||||
* Returns whether the location on the object should register a hit if clicked.
|
||||
*/
|
||||
function hitTest (stageX :int, stageY :int) :Boolean;
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,11 @@
|
||||
|
||||
package com.threerings.miso.client {
|
||||
|
||||
import flash.display.Bitmap;
|
||||
import flash.display.DisplayObject;
|
||||
|
||||
import flash.geom.Point;
|
||||
|
||||
import as3isolib.core.IsoDisplayObject;
|
||||
import as3isolib.display.IsoSprite;
|
||||
import as3isolib.display.primitive.IsoBox;
|
||||
@@ -92,6 +95,30 @@ public class TileIsoSprite extends IsoSprite
|
||||
return _priority;
|
||||
}
|
||||
|
||||
public function hitTest (stageX :int, stageY :int) :Boolean
|
||||
{
|
||||
if (sprites == null || sprites.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sprites[0] is Bitmap) {
|
||||
if (!sprites[0].hitTestPoint(stageX, stageY, true)) {
|
||||
// Doesn't even hit the bounds...
|
||||
return false;
|
||||
}
|
||||
// Check the actual pixels...
|
||||
var pt :Point = sprites[0].globalToLocal(new Point(stageX, stageY));
|
||||
return Bitmap(sprites[0]).bitmapData.hitTest(new Point(0, 0), 0, pt);
|
||||
} else {
|
||||
return sprites[0].hitTestPoint(stageX, stageY, true);
|
||||
}
|
||||
}
|
||||
|
||||
public function toString () :String
|
||||
{
|
||||
return x + ", " + y + ": " + _tileId;
|
||||
}
|
||||
|
||||
protected var _tileId :int;
|
||||
|
||||
protected var _priority :int;
|
||||
|
||||
Reference in New Issue
Block a user