InputManager inject Mouse Move 事件

前面几篇主要介绍了MyGUI类的静态关系,还有一些粗糙的分析。

先看下关于Widget关于Inputmanager

注入鼠标移动事件时一些列流程。

	bool InputManager::injectMouseMove(int _absx, int _absy, int _absz)
	{
		// запоминаем позицию
		mMousePosition.set(_absx, _absy);

		// вычисляем прирост по колеса
		int relz = _absz - mOldAbsZ;
		mOldAbsZ = _absz;

		// проверка на скролл
		if (relz != 0)
		{
			bool isFocus = isFocusMouse();
			if (mWidgetMouseFocus != nullptr) mWidgetMouseFocus->onMouseWheel(relz);
			return isFocus;
		}

		if (mIsWidgetMouseCapture)
		{
			if (mWidgetMouseFocus != nullptr)
			{
				if (mLayerMouseFocus != nullptr)
				{
					IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
					mWidgetMouseFocus->onMouseDrag(point.left, point.top);
				}
			}
			else
				mIsWidgetMouseCapture = false;
			return true;
		}

		Widget* old_mouse_focus = mWidgetMouseFocus;

		// ищем активное окно
		Widget* item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);

		// ничего не изменилось
		if (mWidgetMouseFocus == item)
		{
			bool isFocus = isFocusMouse();
			if (mWidgetMouseFocus != nullptr)
			{
				if (mLayerMouseFocus != nullptr)
				{
					IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);  获取鼠标focus点-〉ILayer-〉ILayerItem-〉ILayerItem-〉Widget
					mWidgetMouseFocus->onMouseMove(_absx, _absy);
				}
			}
			return isFocus;
		}

		if (item)
		{
			// поднимаемся до рута
			Widget* root = item;
			while (root->getParent()) root = root->getParent();

			// проверяем на модальность
			if (!mVectorModalRootWidget.empty())
			{
				if (root != mVectorModalRootWidget.back())
				{
					item = nullptr;
				}
			}

			if (item != nullptr)
			{
				mLayerMouseFocus = root->getLayer();
			}
		}

		// в методе может пропасть наш виджет
		WidgetManager::getInstance().addWidgetToUnlink(item);


		//-------------------------------------------------------------------------------------//
		// новый вид рутового фокуса мыши
		Widget* save_widget = nullptr;

		// спускаемся по новому виджету и устанавливаем рутовый фокус
		Widget* root_focus = item;
		while (root_focus != nullptr)
		{
			if (root_focus->mRootMouseActive)
			{
				save_widget = root_focus;
				break;
			}
			root_focus->mRootMouseActive = true;

			// в методе может пропасть наш виджет
			WidgetManager::getInstance().addWidgetToUnlink(root_focus);
			root_focus->onMouseChangeRootFocus(true);
			WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);

			if (root_focus)
				root_focus = root_focus->getParent();
		}

		// спускаемся по старому виджету и сбрасываем фокус
		root_focus = mWidgetMouseFocus;
		while (root_focus != nullptr)
		{
			if (root_focus == save_widget)
			{
				break;
			}
			root_focus->mRootMouseActive = false;

			// в методе может пропасть наш виджет
			WidgetManager::getInstance().addWidgetToUnlink(root_focus);
			root_focus->onMouseChangeRootFocus(false);
			WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);

			if (root_focus)
				root_focus = root_focus->getParent();
		}
		//-------------------------------------------------------------------------------------//

		// смена фокуса, проверяем на доступность виджета
		if ((mWidgetMouseFocus != nullptr) && (mWidgetMouseFocus->isEnabled()))
		{
			mWidgetMouseFocus->onMouseLostFocus(item);
		}

		WidgetManager::getInstance().removeWidgetFromUnlink(item);


		if ((item != nullptr) && (item->isEnabled()))
		{
			item->onMouseMove(_absx, _absy);
			item->onMouseSetFocus(mWidgetMouseFocus);
		}

		// запоминаем текущее окно
		mWidgetMouseFocus = item;

		if (old_mouse_focus != mWidgetMouseFocus)
			eventChangeMouseFocus(mWidgetMouseFocus);

		return isFocusMouse();
	}


分析点一:LayerManager

层的概念在这里运用:

第一步找出大的层位置:

LayerManager

	Widget* LayerManager::getWidgetFromPoint(int _left, int _top)
	{
		VectorLayer::reverse_iterator iter = mLayerNodes.rbegin();
		while (iter != mLayerNodes.rend())
		{
			ILayerItem * item = (*iter)->getLayerItemByPoint(_left, _top);
			if (item != nullptr) return static_cast<Widget*>(item);
			++iter;
		}
		return nullptr;
	}

分析点二:ILayerItem

找到对应的ILayerItem

 Widget* LayerManager::getWidgetFromPoint(int _left, int _top)

	{
		VectorLayer::reverse_iterator iter = mLayerNodes.rbegin();
		while (iter != mLayerNodes.rend())
		{
			ILayerItem * item = (*iter)->getLayerItemByPoint(_left, _top);
			if (item != nullptr) return static_cast<Widget*>(item);
			++iter;
		}
		return nullptr;
	}

分析点三:LayerNode

Widget的子节点放入LayerNode中进行子节点的查询操作

这一招MyGUI用的已经很纯熟,因为每次的WidgetFocus只可能是不可分割的一部分,原子级的。

所以MyGUI 遍历子节点查询自己的焦点所在。

注意:第一个for的作用和第二个for的作用是不同的。

第一个for的作用就是用作遍历子节点,而第二个是查找子节点的Item

	ILayerItem* LayerNode::getLayerItemByPoint(int _left, int _top)
	{
		// сначала пикаем детей
		for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
		{
			ILayerItem * item = (*iter)->getLayerItemByPoint(_left, _top);
			if (nullptr != item) return item;
		}

		for (VectorLayerItem::iterator iter=mLayerItems.begin(); iter!=mLayerItems.end(); ++iter)
		{
			ILayerItem * item = (*iter)->getLayerItemByPoint(_left, _top);
			if (nullptr != item) return item;
		}

		return nullptr;
	}

分析点四:

最终实现 IlayerItem 的 getLayerItemByPoint 接口

LayerItem 是一个虚类,因为其没有实现 IlayerItem 接口

是Widget实现的。

而Widget 的方法与LayerNode 中找焦点的办法一样

同样的两个for,同样的回调本身

这应该算是递归吧,;)(本人基础的问题!)

	ILayerItem * Widget::getLayerItemByPoint(int _left, int _top)
	{
		// проверяем попадание
		if (!mSubSkinsVisible
			|| !mEnabled
			|| !mVisible
			|| (!mNeedMouseFocus && !mInheritsPick)
			|| !_checkPoint(_left, _top)
			// если есть маска, проверяем еще и по маске
			|| ((!mMaskPickInfo->empty()) && (!mMaskPickInfo->pick(IntPoint(_left - mCoord.left, _top - mCoord.top), mCoord))))
				return nullptr;
		// спрашиваем у детишек
		for (VectorWidgetPtr::reverse_iterator widget= mWidgetChild.rbegin(); widget != mWidgetChild.rend(); ++widget)
		{
			// общаемся только с послушными детьми
			if ((*widget)->mWidgetStyle == WidgetStyle::Popup) continue;

			ILayerItem * item = (*widget)->getLayerItemByPoint(_left - mCoord.left, _top - mCoord.top);
			if (item != nullptr) return item;
		}
		// спрашиваем у детишек скна
		for (VectorWidgetPtr::reverse_iterator widget= mWidgetChildSkin.rbegin(); widget != mWidgetChildSkin.rend(); ++widget)
		{
			ILayerItem * item = (*widget)->getLayerItemByPoint(_left - mCoord.left, _top - mCoord.top);
			if (item != nullptr) return item;
		}
		// непослушные дети
		return mInheritsPick ? nullptr : this;
	}

经过四层传回move所聚焦的Widget

好漫长啊!为什么?






你可能感兴趣的:(InputManager inject Mouse Move 事件)