mirror of https://github.com/axmolengine/axmol.git
Fixed bug: UI component can't click correctly by moving UI and camera far away of origin.
This commit is contained in:
commit
2ba6f266ad
|
@ -24,6 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "2d/CCMenu.h"
|
||||
#include "2d/CCCamera.h"
|
||||
#include "base/CCDirector.h"
|
||||
#include "base/CCTouch.h"
|
||||
#include "base/CCEventListenerTouch.h"
|
||||
|
@ -539,26 +540,25 @@ void Menu::alignItemsInRowsWithArray(const ValueVector& columns)
|
|||
MenuItem* Menu::getItemForTouch(Touch *touch)
|
||||
{
|
||||
Vec2 touchLocation = touch->getLocation();
|
||||
|
||||
if (!_children.empty())
|
||||
auto camera = Camera::getVisitingCamera();
|
||||
|
||||
if (!_children.empty() && nullptr != camera)
|
||||
{
|
||||
for (auto iter = _children.crbegin(); iter != _children.crend(); ++iter)
|
||||
{
|
||||
MenuItem* child = dynamic_cast<MenuItem*>(*iter);
|
||||
if (child && child->isVisible() && child->isEnabled())
|
||||
if (nullptr == child || false == child->isVisible() || false == child->isEnabled())
|
||||
{
|
||||
Vec2 local = child->convertToNodeSpace(touchLocation);
|
||||
Rect r = child->rect();
|
||||
r.origin.setZero();
|
||||
|
||||
if (r.containsPoint(local))
|
||||
{
|
||||
return child;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Rect rect;
|
||||
rect.size = child->getContentSize();
|
||||
if (isScreenPointInRect(touchLocation, camera, child->getWorldToNodeTransform(), rect, nullptr))
|
||||
{
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -2312,6 +2312,52 @@ void Node::disableCascadeColor()
|
|||
}
|
||||
}
|
||||
|
||||
bool isScreenPointInRect(const Vec2 &pt, const Camera* camera, const Mat4& w2l, const Rect& rect, Vec3 *p)
|
||||
{
|
||||
if (nullptr == camera || rect.size.width <= 0 || rect.size.height <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// first, convert pt to near/far plane, get Pn and Pf
|
||||
Vec3 Pn(pt.x, pt.y, -1), Pf(pt.x, pt.y, 1);
|
||||
Pn = camera->unprojectGL(Pn);
|
||||
Pf = camera->unprojectGL(Pf);
|
||||
|
||||
// then convert Pn and Pf to node space
|
||||
w2l.transformPoint(&Pn);
|
||||
w2l.transformPoint(&Pf);
|
||||
|
||||
// Pn and Pf define a line Q(t) = D + t * E which D = Pn
|
||||
auto E = Pf - Pn;
|
||||
|
||||
// second, get three points which define content plane
|
||||
// these points define a plane P(u, w) = A + uB + wC
|
||||
Vec3 A = Vec3(rect.origin.x, rect.origin.y, 0);
|
||||
Vec3 B(rect.size.width, 0, 0);
|
||||
Vec3 C(0, rect.size.height, 0);
|
||||
B = B - A;
|
||||
C = C - A;
|
||||
|
||||
// the line Q(t) intercept with plane P(u, w)
|
||||
// calculate the intercept point P = Q(t)
|
||||
// (BxC).A - (BxC).D
|
||||
// t = -----------------
|
||||
// (BxC).E
|
||||
Vec3 BxC;
|
||||
Vec3::cross(B, C, &BxC);
|
||||
auto BxCdotE = BxC.dot(E);
|
||||
if (BxCdotE == 0) {
|
||||
return false;
|
||||
}
|
||||
auto t = (BxC.dot(A) - BxC.dot(Pn)) / BxCdotE;
|
||||
Vec3 P = Pn + t * E;
|
||||
if (p) {
|
||||
*p = P;
|
||||
}
|
||||
return rect.containsPoint(Vec2(P.x, P.y));
|
||||
}
|
||||
|
||||
// MARK: Camera
|
||||
void Node::setCameraMask(unsigned short mask, bool applyChildren)
|
||||
{
|
||||
|
|
|
@ -57,6 +57,7 @@ class Material;
|
|||
class PhysicsBody;
|
||||
class PhysicsWorld;
|
||||
#endif
|
||||
class Camera;
|
||||
|
||||
/**
|
||||
* @addtogroup _2d
|
||||
|
@ -1875,6 +1876,24 @@ private:
|
|||
#endif //CC_USTPS
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This is a helper function, checks a GL screen point is in content rectangle space.
|
||||
*
|
||||
* The content rectangle defined by origin(0,0) and content size.
|
||||
* This function convert GL screen point to near and far planes as points Pn and Pf,
|
||||
* then calculate the intersect point P which the line PnPf intersect with content rectangle.
|
||||
* If P in content rectangle means this node be hitted.
|
||||
*
|
||||
* @param pt The point in GL screen space.
|
||||
* @param camera Which camera used to unproject pt to near/far planes.
|
||||
* @param w2l World to local transform matrix, used to convert Pn and Pf to rectangle space.
|
||||
* @param rect The test recangle in local space.
|
||||
* @parma p Point to a Vec3 for store the intersect point, if don't need them set to nullptr.
|
||||
* @return true if the point is in content rectangle, flase otherwise.
|
||||
*/
|
||||
bool CC_DLL isScreenPointInRect(const Vec2 &pt, const Camera* camera, const Mat4& w2l, const Rect& rect, Vec3 *p);
|
||||
|
||||
// NodeRGBA
|
||||
|
||||
/** @class __NodeRGBA
|
||||
|
|
|
@ -163,18 +163,23 @@ static bool camera_cmp(const Camera* a, const Camera* b)
|
|||
return a->getRenderOrder() < b->getRenderOrder();
|
||||
}
|
||||
|
||||
void Scene::render(Renderer* renderer)
|
||||
const std::vector<Camera*>& Scene::getCameras()
|
||||
{
|
||||
auto director = Director::getInstance();
|
||||
Camera* defaultCamera = nullptr;
|
||||
const auto& transform = getNodeToParentTransform();
|
||||
if (_cameraOrderDirty)
|
||||
{
|
||||
stable_sort(_cameras.begin(), _cameras.end(), camera_cmp);
|
||||
_cameraOrderDirty = false;
|
||||
}
|
||||
|
||||
for (const auto& camera : _cameras)
|
||||
return _cameras;
|
||||
}
|
||||
|
||||
void Scene::render(Renderer* renderer)
|
||||
{
|
||||
auto director = Director::getInstance();
|
||||
Camera* defaultCamera = nullptr;
|
||||
const auto& transform = getNodeToParentTransform();
|
||||
|
||||
for (const auto& camera : getCameras())
|
||||
{
|
||||
if (!camera->isVisible())
|
||||
continue;
|
||||
|
|
|
@ -88,10 +88,10 @@ public:
|
|||
|
||||
/** Get all cameras.
|
||||
*
|
||||
* @return The vector of all cameras.
|
||||
* @return The vector of all cameras, ordered by camera depth.
|
||||
* @js NA
|
||||
*/
|
||||
const std::vector<Camera*>& getCameras() const { return _cameras; }
|
||||
const std::vector<Camera*>& getCameras();
|
||||
|
||||
/** Get the default camera.
|
||||
* @js NA
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "2d/CCScene.h"
|
||||
#include "base/CCDirector.h"
|
||||
#include "base/CCEventType.h"
|
||||
|
||||
#include "2d/CCCamera.h"
|
||||
|
||||
#define DUMP_LISTENER_ITEM_PRIORITY_INFO 0
|
||||
|
||||
|
@ -762,7 +762,99 @@ void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, c
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fixedPriorityListeners)
|
||||
{
|
||||
if (!shouldStopPropagation)
|
||||
{
|
||||
// priority > 0
|
||||
ssize_t size = fixedPriorityListeners->size();
|
||||
for (; i < size; ++i)
|
||||
{
|
||||
auto l = fixedPriorityListeners->at(i);
|
||||
|
||||
if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
|
||||
{
|
||||
shouldStopPropagation = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventDispatcher::dispatchTouchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent)
|
||||
{
|
||||
bool shouldStopPropagation = false;
|
||||
auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
|
||||
auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
|
||||
|
||||
ssize_t i = 0;
|
||||
// priority < 0
|
||||
if (fixedPriorityListeners)
|
||||
{
|
||||
CCASSERT(listeners->getGt0Index() <= static_cast<ssize_t>(fixedPriorityListeners->size()), "Out of range exception!");
|
||||
|
||||
if (!fixedPriorityListeners->empty())
|
||||
{
|
||||
for (; i < listeners->getGt0Index(); ++i)
|
||||
{
|
||||
auto l = fixedPriorityListeners->at(i);
|
||||
if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
|
||||
{
|
||||
shouldStopPropagation = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sceneGraphPriorityListeners)
|
||||
{
|
||||
if (!shouldStopPropagation)
|
||||
{
|
||||
// priority == 0, scene graph priority
|
||||
|
||||
// first, get all enabled, unPaused and registered listeners
|
||||
std::vector<EventListener*> sceneListeners;
|
||||
for (auto& l : *sceneGraphPriorityListeners)
|
||||
{
|
||||
if (l->isEnabled() && !l->isPaused() && l->isRegistered())
|
||||
{
|
||||
sceneListeners.push_back(l);
|
||||
}
|
||||
}
|
||||
// second, for all camera call all listeners
|
||||
// get a copy of cameras, prevent it's been modified in linstener callback
|
||||
// if camera's depth is greater, process it earler
|
||||
auto cameras = Director::getInstance()->getRunningScene()->getCameras();
|
||||
Camera* camera;
|
||||
for (int j = int(cameras.size()) - 1; j >= 0; --j)
|
||||
{
|
||||
camera = cameras[j];
|
||||
if (camera->isVisible() == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Camera::_visitingCamera = camera;
|
||||
for (auto& l : sceneListeners)
|
||||
{
|
||||
if (onEvent(l))
|
||||
{
|
||||
shouldStopPropagation = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shouldStopPropagation)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Camera::_visitingCamera = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (fixedPriorityListeners)
|
||||
{
|
||||
if (!shouldStopPropagation)
|
||||
|
@ -803,6 +895,10 @@ void EventDispatcher::dispatchEvent(Event* event)
|
|||
|
||||
sortEventListeners(listenerID);
|
||||
|
||||
auto pfnDispatchEventToListeners = &EventDispatcher::dispatchEventToListeners;
|
||||
if (event->getType() == Event::Type::MOUSE) {
|
||||
pfnDispatchEventToListeners = &EventDispatcher::dispatchTouchEventToListeners;
|
||||
}
|
||||
auto iter = _listenerMap.find(listenerID);
|
||||
if (iter != _listenerMap.end())
|
||||
{
|
||||
|
@ -814,7 +910,7 @@ void EventDispatcher::dispatchEvent(Event* event)
|
|||
return event->isStopped();
|
||||
};
|
||||
|
||||
dispatchEventToListeners(listeners, onEvent);
|
||||
(this->*pfnDispatchEventToListeners)(listeners, onEvent);
|
||||
}
|
||||
|
||||
updateListeners(event);
|
||||
|
@ -945,7 +1041,7 @@ void EventDispatcher::dispatchTouchEvent(EventTouch* event)
|
|||
};
|
||||
|
||||
//
|
||||
dispatchEventToListeners(oneByOneListeners, onTouchEvent);
|
||||
dispatchTouchEventToListeners(oneByOneListeners, onTouchEvent);
|
||||
if (event->isStopped())
|
||||
{
|
||||
return;
|
||||
|
@ -1011,7 +1107,7 @@ void EventDispatcher::dispatchTouchEvent(EventTouch* event)
|
|||
return false;
|
||||
};
|
||||
|
||||
dispatchEventToListeners(allAtOnceListeners, onTouchesEvent);
|
||||
dispatchTouchEventToListeners(allAtOnceListeners, onTouchesEvent);
|
||||
if (event->isStopped())
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -276,6 +276,16 @@ protected:
|
|||
/** Dispatches event to listeners with a specified listener type */
|
||||
void dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent);
|
||||
|
||||
/** Special version dispatchEventToListeners for touch/mouse event.
|
||||
*
|
||||
* Touch/mouse event process flow different with common event,
|
||||
* for scene graph node listeners, touch event process flow should
|
||||
* order by viewport/camera first, because the touch location convert
|
||||
* to 3D world space is different by different camera.
|
||||
* When listener process touch event, can get current camera by Camera::getVisitingCamera().
|
||||
*/
|
||||
void dispatchTouchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent);
|
||||
|
||||
/// Priority dirty flag
|
||||
enum class DirtyFlag
|
||||
{
|
||||
|
|
|
@ -27,7 +27,7 @@ THE SOFTWARE.
|
|||
#include "base/ccUtils.h"
|
||||
#include "platform/CCDevice.h"
|
||||
#include "2d/CCTweenFunction.h"
|
||||
|
||||
#include "2d/CCCamera.h"
|
||||
NS_CC_BEGIN
|
||||
|
||||
namespace ui {
|
||||
|
@ -764,6 +764,7 @@ void ScrollView::endRecordSlidAction()
|
|||
if(!bounceBackStarted && _inertiaScrollEnabled)
|
||||
{
|
||||
startInertiaScroll();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -779,9 +780,15 @@ void ScrollView::handlePressLogic(Touch *touch)
|
|||
|
||||
void ScrollView::handleMoveLogic(Touch *touch)
|
||||
{
|
||||
Vec2 touchPositionInNodeSpace = this->convertToNodeSpace(touch->getLocation());
|
||||
Vec2 previousTouchPositionInNodeSpace = this->convertToNodeSpace(touch->getPreviousLocation());
|
||||
Vec2 delta = touchPositionInNodeSpace - previousTouchPositionInNodeSpace;
|
||||
Vec3 currPt, prevPt;
|
||||
if (nullptr == _hittedByCamera ||
|
||||
false == hitTest(touch->getLocation(), _hittedByCamera, &currPt) ||
|
||||
false == hitTest(touch->getPreviousLocation(), _hittedByCamera, &prevPt))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Vec3 delta3 = currPt - prevPt;
|
||||
Vec2 delta(delta3.x, delta3.y);
|
||||
scrollChildren(delta.x, delta.y);
|
||||
|
||||
while(_inertiaTouchDisplacements.size() > 5)
|
||||
|
|
|
@ -26,6 +26,7 @@ THE SOFTWARE.
|
|||
#include "ui/UIScale9Sprite.h"
|
||||
#include "ui/UIHelper.h"
|
||||
#include "2d/CCSprite.h"
|
||||
#include "2d/CCCamera.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
@ -425,16 +426,12 @@ void Slider::setPercent(int percent)
|
|||
}
|
||||
}
|
||||
|
||||
bool Slider::hitTest(const cocos2d::Vec2 &pt)
|
||||
bool Slider::hitTest(const cocos2d::Vec2 &pt, const Camera *camera, Vec3 *p) const
|
||||
{
|
||||
Vec2 nsp = this->_slidBallNormalRenderer->convertToNodeSpace(pt);
|
||||
Size ballSize = this->_slidBallNormalRenderer->getContentSize();
|
||||
Rect ballRect = Rect(0,0, ballSize.width, ballSize.height);
|
||||
if (ballRect.containsPoint(nsp))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
Rect rect;
|
||||
rect.size = _slidBallNormalRenderer->getContentSize();
|
||||
auto w2l = _slidBallNormalRenderer->getWorldToNodeTransform();
|
||||
return isScreenPointInRect(pt, camera, w2l, rect, nullptr);
|
||||
}
|
||||
|
||||
bool Slider::onTouchBegan(Touch *touch, Event *unusedEvent)
|
||||
|
@ -442,8 +439,7 @@ bool Slider::onTouchBegan(Touch *touch, Event *unusedEvent)
|
|||
bool pass = Widget::onTouchBegan(touch, unusedEvent);
|
||||
if (_hitted)
|
||||
{
|
||||
Vec2 nsp = convertToNodeSpace(_touchBeganPosition);
|
||||
setPercent(getPercentWithBallPos(nsp.x));
|
||||
setPercent(getPercentWithBallPos(_touchBeganPosition));
|
||||
percentChangedEvent(EventType::ON_SLIDEBALL_DOWN);
|
||||
}
|
||||
return pass;
|
||||
|
@ -452,8 +448,7 @@ bool Slider::onTouchBegan(Touch *touch, Event *unusedEvent)
|
|||
void Slider::onTouchMoved(Touch *touch, Event *unusedEvent)
|
||||
{
|
||||
_touchMovePosition = touch->getLocation();
|
||||
Vec2 nsp = convertToNodeSpace(_touchMovePosition);
|
||||
setPercent(getPercentWithBallPos(nsp.x));
|
||||
setPercent(getPercentWithBallPos(_touchMovePosition));
|
||||
percentChangedEvent(EventType::ON_PERCENTAGE_CHANGED);
|
||||
}
|
||||
|
||||
|
@ -469,9 +464,11 @@ void Slider::onTouchCancelled(Touch *touch, Event *unusedEvent)
|
|||
percentChangedEvent(EventType::ON_SLIDEBALL_CANCEL);
|
||||
}
|
||||
|
||||
float Slider::getPercentWithBallPos(float px)const
|
||||
float Slider::getPercentWithBallPos(const Vec2 &pt) const
|
||||
{
|
||||
return ((px/_barLength) * static_cast<float>(_maxPercent));
|
||||
Vec3 p;
|
||||
Widget::hitTest(pt, _hittedByCamera, &p);
|
||||
return ((p.x/_barLength) * static_cast<float>(_maxPercent));
|
||||
}
|
||||
|
||||
void Slider::addEventListenerSlider(Ref *target, SEL_SlidPercentChangedEvent selector)
|
||||
|
|
|
@ -247,7 +247,7 @@ public:
|
|||
virtual void ignoreContentAdaptWithSize(bool ignore) override;
|
||||
|
||||
//override the widget's hitTest function to perfom its own
|
||||
virtual bool hitTest(const Vec2 &pt) override;
|
||||
virtual bool hitTest(const Vec2 &pt, const Camera* camera, Vec3 *p) const override;
|
||||
/**
|
||||
* Returns the "class name" of widget.
|
||||
*/
|
||||
|
@ -270,7 +270,7 @@ CC_CONSTRUCTOR_ACCESS:
|
|||
|
||||
protected:
|
||||
virtual void initRenderer() override;
|
||||
float getPercentWithBallPos(float location)const;
|
||||
float getPercentWithBallPos(const Vec2 &pt) const;
|
||||
void percentChangedEvent(EventType event);
|
||||
virtual void onPressStateChangedToNormal() override;
|
||||
virtual void onPressStateChangedToPressed() override;
|
||||
|
|
|
@ -26,6 +26,7 @@ THE SOFTWARE.
|
|||
#include "platform/CCFileUtils.h"
|
||||
#include "ui/UIHelper.h"
|
||||
#include "base/ccUTF8.h"
|
||||
#include "2d/CCCamera.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
@ -380,26 +381,17 @@ void TextField::setTouchAreaEnabled(bool enable)
|
|||
_useTouchArea = enable;
|
||||
}
|
||||
|
||||
bool TextField::hitTest(const Vec2 &pt)
|
||||
bool TextField::hitTest(const Vec2 &pt, const Camera* camera, Vec3 *p) const
|
||||
{
|
||||
if (_useTouchArea)
|
||||
if (false == _useTouchArea)
|
||||
{
|
||||
Vec2 nsp = convertToNodeSpace(pt);
|
||||
Rect bb = Rect(-_touchWidth * _anchorPoint.x, -_touchHeight * _anchorPoint.y, _touchWidth, _touchHeight);
|
||||
if (nsp.x >= bb.origin.x && nsp.x <= bb.origin.x + bb.size.width
|
||||
&& nsp.y >= bb.origin.y && nsp.y <= bb.origin.y + bb.size.height)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return Widget::hitTest(pt, camera, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Widget::hitTest(pt);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
Rect rect(0, 0, _touchWidth, _touchHeight);
|
||||
return isScreenPointInRect(pt, camera, getWorldToNodeTransform(), rect, nullptr);
|
||||
}
|
||||
|
||||
|
||||
Size TextField::getTouchSize()const
|
||||
{
|
||||
return Size(_touchWidth, _touchHeight);
|
||||
|
|
|
@ -316,7 +316,7 @@ public:
|
|||
*/
|
||||
void setTouchAreaEnabled(bool enable);
|
||||
|
||||
virtual bool hitTest(const Vec2 &pt) override;
|
||||
virtual bool hitTest(const Vec2 &pt, const Camera* camera, Vec3 *p) const override;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,6 +34,7 @@ THE SOFTWARE.
|
|||
#include "renderer/CCGLProgram.h"
|
||||
#include "renderer/CCGLProgramState.h"
|
||||
#include "renderer/ccShaders.h"
|
||||
#include "2d/CCCamera.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
@ -154,6 +155,7 @@ _positionType(PositionType::ABSOLUTE),
|
|||
_actionTag(0),
|
||||
_customSize(Size::ZERO),
|
||||
_hitted(false),
|
||||
_hittedByCamera(nullptr),
|
||||
_touchListener(nullptr),
|
||||
_flippedX(false),
|
||||
_flippedY(false),
|
||||
|
@ -749,9 +751,13 @@ bool Widget::onTouchBegan(Touch *touch, Event *unusedEvent)
|
|||
if (isVisible() && isEnabled() && isAncestorsEnabled() && isAncestorsVisible(this) )
|
||||
{
|
||||
_touchBeganPosition = touch->getLocation();
|
||||
if(hitTest(_touchBeganPosition) && isClippingParentContainsPoint(_touchBeganPosition))
|
||||
auto camera = Camera::getVisitingCamera();
|
||||
if(hitTest(_touchBeganPosition, camera, nullptr))
|
||||
{
|
||||
_hitted = true;
|
||||
_hittedByCamera = camera;
|
||||
if (isClippingParentContainsPoint(_touchBeganPosition)) {
|
||||
_hitted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_hitted)
|
||||
|
@ -785,7 +791,7 @@ void Widget::onTouchMoved(Touch *touch, Event *unusedEvent)
|
|||
{
|
||||
_touchMovePosition = touch->getLocation();
|
||||
|
||||
setHighlighted(hitTest(_touchMovePosition));
|
||||
setHighlighted(hitTest(_touchMovePosition, _hittedByCamera, nullptr));
|
||||
|
||||
/*
|
||||
* Propagate touch events to its parents
|
||||
|
@ -914,16 +920,11 @@ void Widget::addCCSEventListener(const ccWidgetEventCallback &callback)
|
|||
this->_ccEventCallback = callback;
|
||||
}
|
||||
|
||||
bool Widget::hitTest(const Vec2 &pt)
|
||||
bool Widget::hitTest(const Vec2 &pt, const Camera* camera, Vec3 *p) const
|
||||
{
|
||||
Vec2 nsp = convertToNodeSpace(pt);
|
||||
Rect bb;
|
||||
bb.size = _contentSize;
|
||||
if (bb.containsPoint(nsp))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
Rect rect;
|
||||
rect.size = getContentSize();
|
||||
return isScreenPointInRect(pt, camera, getWorldToNodeTransform(), rect, p);
|
||||
}
|
||||
|
||||
bool Widget::isClippingParentContainsPoint(const Vec2 &pt)
|
||||
|
@ -955,7 +956,7 @@ bool Widget::isClippingParentContainsPoint(const Vec2 &pt)
|
|||
if (clippingParent)
|
||||
{
|
||||
bool bRet = false;
|
||||
if (clippingParent->hitTest(pt))
|
||||
if (clippingParent->hitTest(pt, _hittedByCamera, nullptr))
|
||||
{
|
||||
bRet = true;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ THE SOFTWARE.
|
|||
NS_CC_BEGIN
|
||||
|
||||
class EventListenerTouchOneByOne;
|
||||
|
||||
class Camera;
|
||||
|
||||
namespace ui {
|
||||
class LayoutComponent;
|
||||
|
@ -543,10 +543,12 @@ public:
|
|||
* Checks a point is in widget's content space.
|
||||
* This function is used for determining touch area of widget.
|
||||
*
|
||||
* @param pt The point in `Vec2`.
|
||||
* @param pt The point in `Vec2`.
|
||||
* @param camera The camera look at widget, used to convert GL screen point to near/far plane.
|
||||
* @param p Point to a Vec3 for store the intersect point, if don't need them set to nullptr.
|
||||
* @return true if the point is in widget's content space, flase otherwise.
|
||||
*/
|
||||
virtual bool hitTest(const Vec2 &pt);
|
||||
virtual bool hitTest(const Vec2 &pt, const Camera* camera, Vec3 *p) const;
|
||||
|
||||
/**
|
||||
* A callback which will be called when touch began event is issued.
|
||||
|
@ -956,6 +958,7 @@ protected:
|
|||
Vec2 _positionPercent;
|
||||
|
||||
bool _hitted;
|
||||
const Camera *_hittedByCamera;
|
||||
EventListenerTouchOneByOne* _touchListener;
|
||||
Vec2 _touchBeganPosition;
|
||||
Vec2 _touchMovePosition;
|
||||
|
|
Loading…
Reference in New Issue