axmol/extensions/fairygui/GComponent.cpp

1387 lines
34 KiB
C++
Raw Normal View History

2020-08-04 12:31:33 +08:00
#include "GComponent.h"
#include "GButton.h"
#include "GGroup.h"
#include "Relations.h"
#include "TranslationHelper.h"
#include "UIObjectFactory.h"
#include "UIPackage.h"
#include "display/FUIContainer.h"
#include "utils/ByteBuffer.h"
#include "utils/ToolSet.h"
NS_FGUI_BEGIN
USING_NS_CC;
using namespace std;
GComponent::GComponent() : _container(nullptr),
2020-11-26 17:40:32 +08:00
_scrollPane(nullptr),
_childrenRenderOrder(ChildrenRenderOrder::ASCENT),
_apexIndex(0),
_boundsChanged(false),
_trackBounds(false),
_opaque(false),
_sortingChildCount(0),
_applyingController(nullptr),
_buildingDisplayList(false),
_maskOwner(nullptr),
_hitArea(nullptr)
2020-08-04 12:31:33 +08:00
{
}
GComponent::~GComponent()
{
for (auto& child : _children)
child->_parent = nullptr;
_children.clear();
_controllers.clear();
_transitions.clear();
CC_SAFE_RELEASE(_maskOwner);
CC_SAFE_RELEASE(_container);
CC_SAFE_RELEASE(_scrollPane);
CC_SAFE_DELETE(_hitArea);
CALL_LATER_CANCEL(GComponent, doUpdateBounds);
CALL_LATER_CANCEL(GComponent, buildNativeDisplayList);
}
void GComponent::handleInit()
{
FUIContainer* c = FUIContainer::create();
c->retain();
c->gOwner = this;
_displayObject = c;
_container = FUIInnerContainer::create();
_container->retain();
_container->setCascadeOpacityEnabled(true);
_displayObject->addChild(_container);
}
GObject* GComponent::addChild(GObject* child)
{
addChildAt(child, (int)_children.size());
return child;
}
GObject* GComponent::addChildAt(GObject* child, int index)
{
CCASSERT(child != nullptr, "Argument must be non-nil");
if (child->_parent == this)
{
setChildIndex(child, index);
}
else
{
child->retain();
child->removeFromParent();
child->_parent = this;
int cnt = (int)_children.size();
if (child->_sortingOrder != 0)
{
_sortingChildCount++;
index = getInsertPosForSortingChild(child);
}
else if (_sortingChildCount > 0)
{
if (index > (cnt - _sortingChildCount))
index = cnt - _sortingChildCount;
}
if (index == cnt)
_children.pushBack(child);
else
_children.insert(index, child);
child->release();
childStateChanged(child);
setBoundsChangedFlag();
}
return child;
}
int GComponent::getInsertPosForSortingChild(GObject* target)
{
size_t cnt = _children.size();
size_t i;
for (i = 0; i < cnt; i++)
{
GObject* child = _children.at(i);
if (child == target)
continue;
if (target->_sortingOrder < child->_sortingOrder)
break;
}
return (int)i;
}
void GComponent::removeChild(GObject* child)
{
CCASSERT(child != nullptr, "Argument must be non-nil");
int childIndex = (int)_children.getIndex(child);
if (childIndex != -1)
removeChildAt(childIndex);
}
void GComponent::removeChildAt(int index)
{
CCASSERT(index >= 0 && index < _children.size(), "Invalid child index");
GObject* child = _children.at(index);
child->_parent = nullptr;
if (child->_sortingOrder != 0)
_sortingChildCount--;
child->setGroup(nullptr);
if (child->_displayObject->getParent() != nullptr)
{
_container->removeChild(child->_displayObject, false);
if (_childrenRenderOrder == ChildrenRenderOrder::ARCH)
CALL_LATER(GComponent, buildNativeDisplayList);
}
_children.erase(index);
setBoundsChangedFlag();
}
void GComponent::removeChildren(int beginIndex, int endIndex)
{
if (endIndex < 0 || endIndex >= _children.size())
endIndex = (int)_children.size() - 1;
for (int i = beginIndex; i <= endIndex; ++i)
removeChildAt(beginIndex);
}
GObject* GComponent::getChildAt(int index) const
{
CCASSERT(index >= 0 && index < _children.size(), "Invalid child index");
return _children.at(index);
}
GObject* GComponent::getChild(const std::string& name) const
{
for (const auto& child : _children)
{
if (child->name.compare(name) == 0)
return child;
}
return nullptr;
}
GObject* GComponent::getChildByPath(const std::string& path) const
{
const GComponent* gcom = this;
GObject* obj = nullptr;
FastSplitter fs;
fs.start(path.data(), path.length(), '.');
std::string str;
while (fs.next())
{
if (gcom == nullptr)
{
gcom = dynamic_cast<GComponent*>(obj);
if (gcom == nullptr)
{
obj = nullptr;
break;
}
}
str.append(fs.getText(), fs.getTextLength());
obj = gcom->getChild(std::string(fs.getText(), fs.getTextLength()));
if (!obj)
break;
gcom = nullptr;
}
return obj;
}
GObject* GComponent::getChildInGroup(const GGroup* group, const std::string& name) const
{
CCASSERT(group != nullptr, "Argument must be non-nil");
for (const auto& child : _children)
{
if (child->_group == group && child->name.compare(name) == 0)
return child;
}
return nullptr;
}
GObject* GComponent::getChildById(const std::string& id) const
{
for (const auto& child : _children)
{
if (child->id.compare(id) == 0)
return child;
}
return nullptr;
}
int GComponent::getChildIndex(const GObject* child) const
{
CCASSERT(child != nullptr, "Argument must be non-nil");
return (int)_children.getIndex((GObject*)child);
}
void GComponent::setChildIndex(GObject* child, int index)
{
CCASSERT(child != nullptr, "Argument must be non-nil");
int oldIndex = (int)_children.getIndex(child);
CCASSERT(oldIndex != -1, "Not a child of this container");
if (child->_sortingOrder != 0) //no effect
return;
int cnt = (int)_children.size();
if (_sortingChildCount > 0)
{
if (index > (cnt - _sortingChildCount - 1))
index = cnt - _sortingChildCount - 1;
}
moveChild(child, oldIndex, index);
}
int GComponent::setChildIndexBefore(GObject* child, int index)
{
CCASSERT(child != nullptr, "Argument must be non-nil");
int oldIndex = (int)_children.getIndex(child);
CCASSERT(oldIndex != -1, "Not a child of this container");
if (child->_sortingOrder != 0) //no effect
return oldIndex;
int cnt = (int)_children.size();
if (_sortingChildCount > 0)
{
if (index > (cnt - _sortingChildCount - 1))
index = cnt - _sortingChildCount - 1;
}
if (oldIndex < index)
return moveChild(child, oldIndex, index - 1);
else
return moveChild(child, oldIndex, index);
}
int GComponent::moveChild(GObject* child, int oldIndex, int index)
{
int cnt = (int)_children.size();
if (index > cnt)
index = cnt;
if (oldIndex == index)
return oldIndex;
child->retain();
_children.erase(oldIndex);
if (index >= cnt)
_children.pushBack(child);
else
_children.insert(index, child);
child->release();
if (child->_displayObject->getParent() != nullptr)
{
if (_childrenRenderOrder == ChildrenRenderOrder::ASCENT)
{
int fromIndex = MIN(index, oldIndex);
int toIndex = MIN(max(index, oldIndex), cnt - 1);
for (int i = fromIndex; i <= toIndex; i++)
{
GObject* g = _children.at(i);
if (g->_displayObject->getParent() != nullptr)
g->_displayObject->setLocalZOrder(i);
}
}
else if (_childrenRenderOrder == ChildrenRenderOrder::DESCENT)
{
int fromIndex = MIN(index, oldIndex);
int toIndex = MIN(max(index, oldIndex), cnt - 1);
for (int i = fromIndex; i <= toIndex; i++)
{
GObject* g = _children.at(i);
if (g->_displayObject->getParent() != nullptr)
g->_displayObject->setLocalZOrder(cnt - 1 - i);
}
}
else
CALL_LATER(GComponent, buildNativeDisplayList);
setBoundsChangedFlag();
}
return index;
}
void GComponent::swapChildren(GObject* child1, GObject* child2)
{
CCASSERT(child1 != nullptr, "Argument1 must be non-nil");
CCASSERT(child2 != nullptr, "Argument2 must be non-nil");
int index1 = (int)_children.getIndex(child1);
int index2 = (int)_children.getIndex(child2);
CCASSERT(index1 != -1, "Not a child of this container");
CCASSERT(index2 != -1, "Not a child of this container");
swapChildrenAt(index1, index2);
}
void GComponent::swapChildrenAt(int index1, int index2)
{
GObject* child1 = _children.at(index1);
GObject* child2 = _children.at(index2);
setChildIndex(child1, index2);
setChildIndex(child2, index1);
}
int GComponent::numChildren() const
{
return (int)_children.size();
}
bool GComponent::isAncestorOf(const GObject* obj) const
{
if (obj == nullptr)
return false;
GComponent* p = obj->_parent;
while (p != nullptr)
{
if (p == this)
return true;
p = p->_parent;
}
return false;
}
bool GComponent::isChildInView(GObject* child)
{
if (_scrollPane != nullptr)
{
return _scrollPane->isChildInView(child);
}
else if (((FUIContainer*)_displayObject)->isClippingEnabled())
{
return child->_position.x + child->_size.width >= 0 && child->_position.x <= _size.width && child->_position.y + child->_size.height >= 0 && child->_position.y <= _size.height;
}
else
return true;
}
int GComponent::getFirstChildInView()
{
int i = 0;
for (auto& child : _children)
{
if (isChildInView(child))
return i;
i++;
}
return -1;
}
GController* GComponent::getController(const std::string& name) const
{
for (const auto& c : _controllers)
{
if (c->name.compare(name) == 0)
return c;
}
return nullptr;
}
void GComponent::addController(GController* c)
{
CCASSERT(c != nullptr, "Argument must be non-nil");
_controllers.pushBack(c);
}
GController* GComponent::getControllerAt(int index) const
{
CCASSERT(index >= 0 && index < _controllers.size(), "Invalid controller index");
return _controllers.at(index);
}
void GComponent::removeController(GController* c)
{
CCASSERT(c != nullptr, "Argument must be non-nil");
ssize_t index = _controllers.getIndex(c);
CCASSERT(index != -1, "controller not exists");
c->setParent(nullptr);
applyController(c);
_controllers.erase(index);
}
void GComponent::applyController(GController* c)
{
_applyingController = c;
ssize_t count = _children.size();
for (ssize_t i = 0; i < count; i++)
2020-11-26 17:40:32 +08:00
_children.at(i)->handleControllerChanged(c);
2020-08-04 12:31:33 +08:00
_applyingController = nullptr;
c->runActions();
}
void GComponent::applyAllControllers()
{
for (const auto& c : _controllers)
applyController(c);
}
Transition* GComponent::getTransition(const std::string& name) const
{
for (const auto& c : _transitions)
{
if (c->name.compare(name) == 0)
return c;
}
return nullptr;
}
Transition* GComponent::getTransitionAt(int index) const
{
CCASSERT(index >= 0 && index < _transitions.size(), "Invalid transition index");
return _transitions.at(index);
}
void GComponent::adjustRadioGroupDepth(GObject* obj, GController* c)
{
ssize_t cnt = (ssize_t)_children.size();
ssize_t i;
GObject* child;
ssize_t myIndex = -1, maxIndex = -1;
for (i = 0; i < cnt; i++)
{
child = _children.at(i);
if (child == obj)
{
myIndex = i;
}
else if (dynamic_cast<GButton*>(child) && ((GButton*)child)->getRelatedController() == c)
{
if (i > maxIndex)
maxIndex = i;
}
}
if (myIndex < maxIndex)
{
if (_applyingController != nullptr)
_children.at(maxIndex)->handleControllerChanged(_applyingController);
swapChildrenAt((int)myIndex, (int)maxIndex);
}
}
void GComponent::setOpaque(bool value)
{
_opaque = value;
}
void GComponent::setMargin(const Margin& value)
{
_margin = value;
}
void GComponent::setChildrenRenderOrder(ChildrenRenderOrder value)
{
if (_childrenRenderOrder != value)
{
_childrenRenderOrder = value;
CALL_LATER(GComponent, buildNativeDisplayList);
}
}
void GComponent::setApexIndex(int value)
{
if (_apexIndex != value)
{
_apexIndex = value;
if (_childrenRenderOrder == ChildrenRenderOrder::ARCH)
CALL_LATER(GComponent, buildNativeDisplayList);
}
}
cocos2d::Node* GComponent::getMask() const
{
return ((FUIContainer*)_displayObject)->getStencil();
}
void GComponent::setMask(cocos2d::Node* value, bool inverted)
{
if (_maskOwner)
{
_maskOwner->_alignToBL = false;
childStateChanged(_maskOwner);
_maskOwner->handlePositionChanged();
_maskOwner->release();
_maskOwner = nullptr;
}
if (value)
{
for (auto& child : _children)
{
if (child->_displayObject == value)
{
_maskOwner = child;
if (value->getParent())
value->getParent()->removeChild(value, false);
_maskOwner->_alignToBL = true;
_maskOwner->handlePositionChanged();
_maskOwner->retain();
break;
}
}
}
((FUIContainer*)_displayObject)->setStencil(value);
if (value)
{
((FUIContainer*)_displayObject)->setAlphaThreshold(0.05f);
((FUIContainer*)_displayObject)->setInverted(inverted);
}
}
void GComponent::setHitArea(IHitTest* value)
{
if (_hitArea != value)
{
CC_SAFE_DELETE(_hitArea);
_hitArea = value;
}
}
float GComponent::getViewWidth() const
{
if (_scrollPane != nullptr)
return _scrollPane->getViewSize().width;
else
return _size.width - _margin.left - _margin.right;
}
void GComponent::setViewWidth(float value)
{
if (_scrollPane != nullptr)
_scrollPane->setViewWidth(value);
else
setWidth(value + _margin.left + _margin.right);
}
float GComponent::getViewHeight() const
{
if (_scrollPane != nullptr)
return _scrollPane->getViewSize().height;
else
return _size.height - _margin.top - _margin.bottom;
}
void GComponent::setViewHeight(float value)
{
if (_scrollPane != nullptr)
_scrollPane->setViewHeight(value);
else
setHeight(value + _margin.top + _margin.bottom);
}
void GComponent::setBoundsChangedFlag()
{
if (_scrollPane == nullptr && !_trackBounds)
return;
_boundsChanged = true;
CALL_LATER(GComponent, doUpdateBounds);
}
void GComponent::ensureBoundsCorrect()
{
if (_boundsChanged)
updateBounds();
}
void GComponent::updateBounds()
{
float ax, ay, aw, ah;
if (!_children.empty())
{
ax = FLT_MAX;
ay = FLT_MAX;
float ar = -FLT_MAX, ab = -FLT_MAX;
float tmp;
size_t cnt = _children.size();
for (size_t i = 0; i < cnt; ++i)
{
GObject* child = _children.at(i);
tmp = child->getX();
if (tmp < ax)
ax = tmp;
tmp = child->getY();
if (tmp < ay)
ay = tmp;
tmp = child->getX() + child->getWidth();
if (tmp > ar)
ar = tmp;
tmp = child->getY() + child->getHeight();
if (tmp > ab)
ab = tmp;
}
aw = ar - ax;
ah = ab - ay;
}
else
{
ax = 0;
ay = 0;
aw = 0;
ah = 0;
}
setBounds(ax, ay, aw, ah);
}
void GComponent::setBounds(float ax, float ay, float aw, float ah)
{
_boundsChanged = false;
if (_scrollPane != nullptr)
_scrollPane->setContentSize(ceil(ax + aw), ceil(ay + ah));
}
void GComponent::doUpdateBounds()
{
if (_boundsChanged)
updateBounds();
}
void GComponent::childStateChanged(GObject* child)
{
if (_buildingDisplayList)
return;
int cnt = (int)_children.size();
if (dynamic_cast<GGroup*>(child) != nullptr)
{
for (int i = 0; i < cnt; ++i)
{
GObject* g = _children.at(i);
if (g->_group == child)
childStateChanged(g);
}
}
if (child->_displayObject == nullptr || child == _maskOwner)
return;
if (child->internalVisible())
{
if (child->_displayObject->getParent() == nullptr)
{
if (_childrenRenderOrder == ChildrenRenderOrder::ASCENT)
{
int index = (int)_children.getIndex(child);
_container->addChild(child->_displayObject, index);
size_t cnt = _children.size();
for (size_t i = index + 1; i < cnt; i++)
{
child = _children.at(i);
if (child->_displayObject->getParent() != nullptr)
child->_displayObject->setLocalZOrder((int)i);
}
}
else if (_childrenRenderOrder == ChildrenRenderOrder::DESCENT)
{
ssize_t index = _children.getIndex(child);
_container->addChild(child->_displayObject, (int)(cnt - 1 - index));
for (ssize_t i = 0; i < index; i++)
{
child = _children.at(i);
if (child->_displayObject->getParent() != nullptr)
child->_displayObject->setLocalZOrder((int)(cnt - 1 - i));
}
}
else
{
CALL_LATER(GComponent, buildNativeDisplayList);
}
}
}
else
{
if (child->_displayObject->getParent() != nullptr)
{
_container->removeChild(child->_displayObject, false);
if (_childrenRenderOrder == ChildrenRenderOrder::ARCH)
{
CALL_LATER(GComponent, buildNativeDisplayList);
}
}
}
}
void GComponent::childSortingOrderChanged(GObject* child, int oldValue, int newValue)
{
if (newValue == 0)
{
_sortingChildCount--;
setChildIndex(child, (int)_children.size());
}
else
{
if (oldValue == 0)
_sortingChildCount++;
int oldIndex = (int)_children.getIndex(child);
int index = getInsertPosForSortingChild(child);
if (oldIndex < index)
moveChild(child, oldIndex, index - 1);
else
moveChild(child, oldIndex, index);
}
}
void GComponent::buildNativeDisplayList()
{
int cnt = (int)_children.size();
if (cnt == 0)
return;
switch (_childrenRenderOrder)
{
case ChildrenRenderOrder::ASCENT:
{
for (int i = 0; i < cnt; i++)
{
GObject* child = _children.at(i);
if (child->_displayObject != nullptr && child != _maskOwner && child->internalVisible())
_container->addChild(child->_displayObject, i);
}
}
break;
case ChildrenRenderOrder::DESCENT:
{
for (int i = 0; i < cnt; i++)
{
GObject* child = _children.at(i);
if (child->_displayObject != nullptr && child != _maskOwner && child->internalVisible())
_container->addChild(child->_displayObject, cnt - 1 - i);
}
}
break;
case ChildrenRenderOrder::ARCH:
{
int ai = MIN(_apexIndex, cnt);
for (int i = 0; i < ai; i++)
{
GObject* child = _children.at(i);
if (child->_displayObject != nullptr && child != _maskOwner && child->internalVisible())
{
if (child->_displayObject->getParent() == nullptr)
_container->addChild(child->_displayObject, i);
else
child->_displayObject->setLocalZOrder((int)i);
}
}
for (int i = cnt - 1; i >= ai; i--)
{
GObject* child = _children.at(i);
if (child->_displayObject != nullptr && child != _maskOwner && child->internalVisible())
{
if (child->_displayObject->getParent() == nullptr)
_container->addChild(child->_displayObject, ai + cnt - 1 - i);
else
child->_displayObject->setLocalZOrder(ai + cnt - 1 - i);
}
}
}
break;
}
}
cocos2d::Vec2 GComponent::getSnappingPosition(const cocos2d::Vec2& pt)
{
int cnt = (int)_children.size();
if (cnt == 0)
return pt;
ensureBoundsCorrect();
GObject* obj = nullptr;
Vec2 ret = pt;
int i = 0;
if (ret.y != 0)
{
for (; i < cnt; i++)
{
obj = _children.at(i);
if (ret.y < obj->getY())
{
if (i == 0)
{
ret.y = 0;
break;
}
else
{
GObject* prev = _children.at(i - 1);
if (ret.y < prev->getY() + prev->getHeight() / 2) //top half part
ret.y = prev->getY();
else //bottom half part
ret.y = obj->getY();
break;
}
}
}
if (i == cnt)
ret.y = obj->getY();
}
if (ret.x != 0)
{
if (i > 0)
i--;
for (; i < cnt; i++)
{
obj = _children.at(i);
if (ret.x < obj->getX())
{
if (i == 0)
{
ret.x = 0;
break;
}
else
{
GObject* prev = _children.at(i - 1);
if (ret.x < prev->getX() + prev->getWidth() / 2) // top half part
ret.x = prev->getX();
else //bottom half part
ret.x = obj->getX();
break;
}
}
}
if (i == cnt)
ret.x = obj->getX();
}
return ret;
}
GObject* GComponent::hitTest(const Vec2& worldPoint, const Camera* camera)
{
if (_touchDisabled || !_touchable || !_displayObject->isVisible() || !_displayObject->getParent())
return nullptr;
GObject* target = nullptr;
if (_maskOwner)
{
if (_maskOwner->hitTest(worldPoint, camera) != nullptr)
{
if (((FUIContainer*)_displayObject)->isInverted())
return nullptr;
}
else
{
if (!((FUIContainer*)_displayObject)->isInverted())
return nullptr;
}
}
Rect rect;
int flag = 0;
if (_hitArea)
{
Rect rect;
rect.size = _size;
Vec2 localPoint = _displayObject->convertToNodeSpace(worldPoint);
flag = rect.containsPoint(localPoint) ? 1 : 2;
if (!_hitArea->hitTest(this, localPoint))
return nullptr;
}
else
{
if (((FUIContainer*)_displayObject)->isClippingEnabled())
{
Rect rect;
rect.size = _size;
Vec2 localPoint = _displayObject->convertToNodeSpace(worldPoint);
flag = rect.containsPoint(localPoint) ? 1 : 2;
const Rect& clipRect = ((FUIContainer*)_displayObject)->getClippingRegion();
if (!clipRect.containsPoint(localPoint))
return nullptr;
}
}
if (_scrollPane)
{
target = _scrollPane->hitTest(worldPoint, camera);
if (!target)
return nullptr;
if (target != this)
return target;
}
int cnt = (int)_children.size();
switch (_childrenRenderOrder)
{
case ChildrenRenderOrder::ASCENT:
{
for (int i = cnt - 1; i >= 0; i--)
{
GObject* child = _children.at(i);
if (!child->_displayObject || child == _maskOwner)
continue;
target = child->hitTest(worldPoint, camera);
if (target)
return target;
}
}
break;
case ChildrenRenderOrder::DESCENT:
{
for (int i = 0; i < cnt; i++)
{
GObject* child = _children.at(i);
if (!child->_displayObject || child == _maskOwner)
continue;
target = child->hitTest(worldPoint, camera);
if (target)
return target;
}
}
break;
case ChildrenRenderOrder::ARCH:
{
int ai = MIN(_apexIndex, cnt);
for (int i = ai; i < cnt; i++)
{
GObject* child = _children.at(i);
if (!child->_displayObject || child == _maskOwner)
continue;
target = child->hitTest(worldPoint, camera);
if (target)
return target;
}
for (int i = ai - 1; i >= 0; i--)
{
GObject* child = _children.at(i);
if (!child->_displayObject || child == _maskOwner)
continue;
target = child->hitTest(worldPoint, camera);
if (target)
return target;
}
}
}
if (_opaque)
{
if (flag == 0)
{
rect.size = _size;
flag = rect.containsPoint(_displayObject->convertToNodeSpace(worldPoint)) ? 1 : 2;
}
if (flag == 1)
return this;
else
return nullptr;
}
else
return nullptr;
}
void GComponent::setupOverflow(OverflowType overflow)
{
if (overflow == OverflowType::HIDDEN)
{
((FUIContainer*)_displayObject)->setClippingEnabled(true);
((FUIContainer*)_displayObject)->setClippingRegion(Rect(_margin.left, _margin.top, _size.width - _margin.left - _margin.right, _size.height - _margin.top - _margin.bottom));
}
_container->setPosition2(_margin.left, _margin.top);
}
void GComponent::setupScroll(ByteBuffer* buffer)
{
_scrollPane = new ScrollPane(this);
_scrollPane->setup(buffer);
}
void GComponent::handleSizeChanged()
{
GObject::handleSizeChanged();
if (_scrollPane != nullptr)
_scrollPane->onOwnerSizeChanged();
else
_container->setPosition2(_margin.left, _margin.top);
if (_maskOwner)
_maskOwner->handlePositionChanged();
if (((FUIContainer*)_displayObject)->isClippingEnabled())
((FUIContainer*)_displayObject)->setClippingRegion(Rect(_margin.left, _margin.top, _size.width - _margin.left - _margin.right, _size.height - _margin.top - _margin.bottom));
if (_hitArea)
{
PixelHitTest* test = dynamic_cast<PixelHitTest*>(_hitArea);
if (sourceSize.width != 0)
test->scaleX = _size.width / sourceSize.width;
if (sourceSize.height != 0)
test->scaleY = _size.height / sourceSize.height;
}
}
void GComponent::handleGrayedChanged()
{
GObject::handleGrayedChanged();
GController* cc = getController("grayed");
if (cc != nullptr)
cc->setSelectedIndex(isGrayed() ? 1 : 0);
else
{
for (auto& child : _children)
child->handleGrayedChanged();
}
}
void GComponent::handleControllerChanged(GController* c)
{
GObject::handleControllerChanged(c);
if (_scrollPane != nullptr)
_scrollPane->handleControllerChanged(c);
}
void GComponent::onEnter()
{
GObject::onEnter();
if (!_transitions.empty())
{
for (auto& trans : _transitions)
trans->onOwnerAddedToStage();
}
}
void GComponent::onExit()
{
GObject::onExit();
if (!_transitions.empty())
{
for (auto& trans : _transitions)
trans->onOwnerRemovedFromStage();
}
}
void GComponent::constructFromResource()
{
constructFromResource(nullptr, 0);
}
void GComponent::constructFromResource(std::vector<GObject*>* objectPool, int poolIndex)
{
PackageItem* contentItem = _packageItem->getBranch();
if (!contentItem->translated)
{
contentItem->translated = true;
TranslationHelper::translateComponent(contentItem);
}
ByteBuffer* buffer = contentItem->rawData;
buffer->seek(0, 0);
_underConstruct = true;
sourceSize.width = buffer->readInt();
sourceSize.height = buffer->readInt();
initSize = sourceSize;
setSize(sourceSize.width, sourceSize.height);
if (buffer->readBool())
{
minSize.width = buffer->readInt();
maxSize.width = buffer->readInt();
minSize.height = buffer->readInt();
maxSize.height = buffer->readInt();
}
if (buffer->readBool())
{
float f1 = buffer->readFloat();
float f2 = buffer->readFloat();
setPivot(f1, f2, buffer->readBool());
}
if (buffer->readBool())
{
_margin.top = buffer->readInt();
_margin.bottom = buffer->readInt();
_margin.left = buffer->readInt();
_margin.right = buffer->readInt();
}
OverflowType overflow = (OverflowType)buffer->readByte();
if (overflow == OverflowType::SCROLL)
{
int savedPos = buffer->getPos();
buffer->seek(0, 7);
setupScroll(buffer);
buffer->setPos(savedPos);
}
else
setupOverflow(overflow);
if (buffer->readBool()) //clipsoft
buffer->skip(8);
_buildingDisplayList = true;
buffer->seek(0, 1);
int controllerCount = buffer->readShort();
for (int i = 0; i < controllerCount; i++)
{
2021-07-17 19:51:27 +08:00
int nextPos = buffer->readUshort();
2020-08-04 12:31:33 +08:00
nextPos += buffer->getPos();
GController* controller = new GController();
_controllers.pushBack(controller);
controller->setParent(this);
controller->setup(buffer);
controller->release();
buffer->setPos(nextPos);
}
buffer->seek(0, 2);
GObject* child;
int childCount = buffer->readShort();
for (int i = 0; i < childCount; i++)
{
2021-07-17 19:51:27 +08:00
int dataLen = buffer->readUshort();
2020-08-04 12:31:33 +08:00
int curPos = buffer->getPos();
if (objectPool != nullptr)
child = (*objectPool)[poolIndex + i];
else
{
buffer->seek(curPos, 0);
ObjectType type = (ObjectType)buffer->readByte();
const string& src = buffer->readS();
const string& pkgId = buffer->readS();
PackageItem* pi = nullptr;
if (!src.empty())
{
UIPackage* pkg;
if (!pkgId.empty())
pkg = UIPackage::getById(pkgId);
else
pkg = contentItem->owner;
pi = pkg != nullptr ? pkg->getItem(src) : nullptr;
}
if (pi != nullptr)
{
child = UIObjectFactory::newObject(pi);
child->constructFromResource();
}
else
child = UIObjectFactory::newObject(type);
}
child->_underConstruct = true;
child->setup_beforeAdd(buffer, curPos);
child->_parent = this;
_children.pushBack(child);
buffer->setPos(curPos + dataLen);
}
buffer->seek(0, 3);
_relations->setup(buffer, true);
buffer->seek(0, 2);
buffer->skip(2);
for (int i = 0; i < childCount; i++)
{
2021-07-17 19:51:27 +08:00
int nextPos = buffer->readUshort();
2020-08-04 12:31:33 +08:00
nextPos += buffer->getPos();
buffer->seek(buffer->getPos(), 3);
_children.at(i)->relations()->setup(buffer, false);
buffer->setPos(nextPos);
}
buffer->seek(0, 2);
buffer->skip(2);
for (int i = 0; i < childCount; i++)
{
2021-07-17 19:51:27 +08:00
int nextPos = buffer->readUshort();
2020-08-04 12:31:33 +08:00
nextPos += buffer->getPos();
child = _children.at(i);
child->setup_afterAdd(buffer, buffer->getPos());
child->_underConstruct = false;
buffer->setPos(nextPos);
}
buffer->seek(0, 4);
buffer->skip(2); //customData
_opaque = buffer->readBool();
int maskId = buffer->readShort();
if (maskId != -1)
{
bool inverted = buffer->readBool();
setMask(getChildAt(maskId)->displayObject(), inverted);
}
const string& hitTestId = buffer->readS();
int i1 = buffer->readInt();
int i2 = buffer->readInt();
if (!hitTestId.empty())
{
PackageItem* pi = contentItem->owner->getItem(hitTestId);
if (pi != nullptr && pi->pixelHitTestData != nullptr)
setHitArea(new PixelHitTest(pi->pixelHitTestData, i1, i2));
}
else if (i1 != 0 && i2 != -1)
{
//setHitArea(new ChildHitArea(getChildAt(i2)));
}
buffer->seek(0, 5);
int transitionCount = buffer->readShort();
for (int i = 0; i < transitionCount; i++)
{
2021-07-17 19:51:27 +08:00
int nextPos = buffer->readUshort();
2020-08-04 12:31:33 +08:00
nextPos += buffer->getPos();
Transition* trans = new Transition(this);
trans->setup(buffer);
_transitions.pushBack(trans);
trans->release();
buffer->setPos(nextPos);
}
applyAllControllers();
_buildingDisplayList = false;
_underConstruct = false;
buildNativeDisplayList();
setBoundsChangedFlag();
if (contentItem->objectType != ObjectType::COMPONENT)
constructExtension(buffer);
onConstruct();
}
void GComponent::constructExtension(ByteBuffer* buffer)
{
}
void GComponent::onConstruct()
{
}
void GComponent::setup_afterAdd(ByteBuffer* buffer, int beginPos)
{
GObject::setup_afterAdd(buffer, beginPos);
buffer->seek(beginPos, 4);
int pageController = buffer->readShort();
if (pageController != -1 && _scrollPane != nullptr && _scrollPane->isPageMode())
_scrollPane->setPageController(_parent->getControllerAt(pageController));
int cnt = buffer->readShort();
for (int i = 0; i < cnt; i++)
{
GController* cc = getController(buffer->readS());
const string& pageId = buffer->readS();
if (cc)
cc->setSelectedPageId(pageId);
}
if (buffer->version >= 2)
{
cnt = buffer->readShort();
for (int i = 0; i < cnt; i++)
{
std::string target = buffer->readS();
ObjectPropID propId = (ObjectPropID)buffer->readShort();
std::string value = buffer->readS();
GObject* obj = getChildByPath(target);
if (obj != nullptr)
obj->setProp(propId, Value(value));
}
}
}
NS_FGUI_END