mirror of https://github.com/axmolengine/axmol.git
Add extension fairygui support
This commit is contained in:
parent
2b24a1cb6f
commit
8531a1914d
|
@ -13,6 +13,8 @@ option(BUILD_EXTENSION_DRAGONBONES "Build extension DragonBones" OFF)
|
|||
|
||||
option(BUILD_EXTENSION_COCOSTUDIO "Build extension cocostudio" ON)
|
||||
|
||||
option(BUILD_EXTENSION_FAIRYGUI "Build extension FairyGUI" ON)
|
||||
|
||||
function(setup_cocos_extension_config target_name)
|
||||
if(ANDROID)
|
||||
target_link_libraries(${target_name} INTERFACE cocos2d)
|
||||
|
@ -59,4 +61,8 @@ if(BUILD_EXTENSION_COCOSTUDIO)
|
|||
add_subdirectory(cocostudio)
|
||||
endif()
|
||||
|
||||
if(BUILD_EXTENSION_FAIRYGUI)
|
||||
add_subdirectory(fairygui)
|
||||
endif()
|
||||
|
||||
message(STATUS "CC_EXTENSION_LIBS:${CC_EXTENSION_LIBS}")
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
set(target_name fairygui)
|
||||
|
||||
FILE(GLOB_RECURSE FAIRYGUI_SOURCES *.h;*.cpp)
|
||||
|
||||
add_library(${target_name} STATIC ${FAIRYGUI_SOURCES})
|
||||
|
||||
target_include_directories(${target_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
setup_cocos_extension_config(${target_name})
|
|
@ -0,0 +1,204 @@
|
|||
#include "Controller.h"
|
||||
#include "GComponent.h"
|
||||
#include "controller_action/ControllerAction.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GController::GController() : changing(false),
|
||||
autoRadioGroupDepth(false),
|
||||
_parent(nullptr),
|
||||
_selectedIndex(-1),
|
||||
_previousIndex(-1)
|
||||
{
|
||||
}
|
||||
|
||||
GController::~GController()
|
||||
{
|
||||
for (auto& it : _actions)
|
||||
delete it;
|
||||
}
|
||||
|
||||
void GController::setSelectedIndex(int value, bool triggerEvent)
|
||||
{
|
||||
if (_selectedIndex != value)
|
||||
{
|
||||
CCASSERT(value < (int)_pageIds.size(), "Invalid selected index");
|
||||
|
||||
changing = true;
|
||||
|
||||
_previousIndex = _selectedIndex;
|
||||
_selectedIndex = value;
|
||||
_parent->applyController(this);
|
||||
|
||||
if (triggerEvent)
|
||||
dispatchEvent(UIEventType::Changed);
|
||||
|
||||
changing = false;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& GController::getSelectedPage() const
|
||||
{
|
||||
if (_selectedIndex == -1)
|
||||
return STD_STRING_EMPTY;
|
||||
else
|
||||
return _pageNames[_selectedIndex];
|
||||
}
|
||||
|
||||
void GController::setSelectedPage(const std::string& value, bool triggerEvent)
|
||||
{
|
||||
int i = ToolSet::findInStringArray(_pageNames, value);
|
||||
if (i == -1)
|
||||
i = 0;
|
||||
setSelectedIndex(i, triggerEvent);
|
||||
}
|
||||
|
||||
const std::string& GController::getSelectedPageId() const
|
||||
{
|
||||
if (_selectedIndex == -1)
|
||||
return STD_STRING_EMPTY;
|
||||
else
|
||||
return _pageIds[_selectedIndex];
|
||||
}
|
||||
|
||||
void GController::setSelectedPageId(const std::string& value, bool triggerEvent)
|
||||
{
|
||||
int i = ToolSet::findInStringArray(_pageIds, value);
|
||||
if (i != -1)
|
||||
setSelectedIndex(i, triggerEvent);
|
||||
}
|
||||
|
||||
const std::string& GController::getPreviousPage() const
|
||||
{
|
||||
if (_previousIndex == -1)
|
||||
return STD_STRING_EMPTY;
|
||||
else
|
||||
return _pageNames[_previousIndex];
|
||||
}
|
||||
|
||||
const std::string& GController::getPreviousPageId() const
|
||||
{
|
||||
if (_previousIndex == -1)
|
||||
return STD_STRING_EMPTY;
|
||||
else
|
||||
return _pageIds[_previousIndex];
|
||||
}
|
||||
|
||||
int GController::getPageCount() const
|
||||
{
|
||||
return (int)_pageIds.size();
|
||||
}
|
||||
|
||||
bool GController::hasPage(const std::string& aName) const
|
||||
{
|
||||
return ToolSet::findInStringArray(_pageNames, aName) != -1;
|
||||
}
|
||||
|
||||
int GController::getPageIndexById(const std::string& value) const
|
||||
{
|
||||
return ToolSet::findInStringArray(_pageIds, value);
|
||||
}
|
||||
|
||||
const std::string& GController::getPageNameById(const std::string& value) const
|
||||
{
|
||||
int i = ToolSet::findInStringArray(_pageIds, value);
|
||||
if (i != -1)
|
||||
return _pageNames[i];
|
||||
else
|
||||
return STD_STRING_EMPTY;
|
||||
}
|
||||
|
||||
const std::string& GController::getPageId(int index) const
|
||||
{
|
||||
return _pageIds[index];
|
||||
}
|
||||
|
||||
void GController::setOppositePageId(const std::string& value)
|
||||
{
|
||||
int i = ToolSet::findInStringArray(_pageIds, value);
|
||||
if (i > 0)
|
||||
setSelectedIndex(0);
|
||||
else if (_pageIds.size() > 1)
|
||||
setSelectedIndex(1);
|
||||
}
|
||||
|
||||
void GController::runActions()
|
||||
{
|
||||
if (_actions.empty())
|
||||
return;
|
||||
|
||||
for (auto& it : _actions)
|
||||
it->run(this, getPreviousPageId(), getSelectedPageId());
|
||||
}
|
||||
|
||||
void GController::setup(ByteBuffer* buffer)
|
||||
{
|
||||
int beginPos = buffer->getPos();
|
||||
buffer->seek(beginPos, 0);
|
||||
|
||||
name = buffer->readS();
|
||||
autoRadioGroupDepth = buffer->readBool();
|
||||
|
||||
buffer->seek(beginPos, 1);
|
||||
|
||||
int cnt = buffer->readShort();
|
||||
_pageIds.resize(cnt);
|
||||
_pageNames.resize(cnt);
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
_pageIds[i].assign(buffer->readS());
|
||||
_pageNames[i].assign(buffer->readS());
|
||||
}
|
||||
|
||||
int homePageIndex = 0;
|
||||
if (buffer->version >= 2)
|
||||
{
|
||||
int homePageType = buffer->readByte();
|
||||
switch (homePageType)
|
||||
{
|
||||
case 1:
|
||||
homePageIndex = buffer->readShort();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
homePageIndex = ToolSet::findInStringArray(_pageNames, UIPackage::getBranch());
|
||||
if (homePageIndex == -1)
|
||||
homePageIndex = 0;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
homePageIndex = ToolSet::findInStringArray(_pageNames, UIPackage::getVar(buffer->readS()));
|
||||
if (homePageIndex == -1)
|
||||
homePageIndex = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buffer->seek(beginPos, 2);
|
||||
|
||||
cnt = buffer->readShort();
|
||||
if (cnt > 0)
|
||||
{
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
int nextPos = buffer->readShort();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
ControllerAction* action = ControllerAction::createAction(buffer->readByte());
|
||||
action->setup(buffer);
|
||||
_actions.push_back(action);
|
||||
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
}
|
||||
|
||||
if (_parent != nullptr && _pageIds.size() > 0)
|
||||
_selectedIndex = homePageIndex;
|
||||
else
|
||||
_selectedIndex = -1;
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef __GCONTROLLER_H__
|
||||
#define __GCONTROLLER_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
#include "event/UIEventDispatcher.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GComponent;
|
||||
class ControllerAction;
|
||||
class ByteBuffer;
|
||||
|
||||
class GController : public UIEventDispatcher
|
||||
{
|
||||
public:
|
||||
GController();
|
||||
virtual ~GController();
|
||||
|
||||
GComponent* getParent() const { return _parent; }
|
||||
void setParent(GComponent* value) { _parent = value; }
|
||||
|
||||
int getSelectedIndex() const { return _selectedIndex; }
|
||||
void setSelectedIndex(int value, bool triggerEvent = true);
|
||||
|
||||
const std::string& getSelectedPage() const;
|
||||
void setSelectedPage(const std::string& value, bool triggerEvent = true);
|
||||
|
||||
const std::string& getSelectedPageId() const;
|
||||
void setSelectedPageId(const std::string& value, bool triggerEvent = true);
|
||||
|
||||
int getPrevisousIndex() const { return _previousIndex; }
|
||||
const std::string& getPreviousPage() const;
|
||||
const std::string& getPreviousPageId() const;
|
||||
|
||||
int getPageCount() const;
|
||||
bool hasPage(const std::string& aName) const;
|
||||
int getPageIndexById(const std::string& value) const;
|
||||
const std::string& getPageNameById(const std::string& value) const;
|
||||
const std::string& getPageId(int index) const;
|
||||
void setOppositePageId(const std::string& value);
|
||||
void runActions();
|
||||
|
||||
void setup(ByteBuffer* buffer);
|
||||
|
||||
std::string name;
|
||||
bool changing;
|
||||
bool autoRadioGroupDepth;
|
||||
|
||||
private:
|
||||
GComponent* _parent;
|
||||
int _selectedIndex;
|
||||
int _previousIndex;
|
||||
std::vector<std::string> _pageIds;
|
||||
std::vector<std::string> _pageNames;
|
||||
std::vector<ControllerAction*> _actions;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,85 @@
|
|||
#include "DragDropManager.h"
|
||||
#include "UIObjectFactory.h"
|
||||
#include "GRoot.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
DragDropManager* DragDropManager::_inst = nullptr;
|
||||
|
||||
DragDropManager::DragDropManager() :
|
||||
_agent(nullptr)
|
||||
{
|
||||
_agent = (GLoader*)UIObjectFactory::newObject(ObjectType::LOADER);
|
||||
_agent->retain();
|
||||
_agent->setTouchable(false);
|
||||
_agent->setDraggable(true);
|
||||
_agent->setSize(100, 100);
|
||||
_agent->setPivot(0.5f, 0.5f, true);
|
||||
_agent->setAlign(TextHAlignment::CENTER);
|
||||
_agent->setVerticalAlign(TextVAlignment::CENTER);
|
||||
_agent->setSortingOrder(INT_MAX);
|
||||
_agent->addEventListener(UIEventType::DragEnd, CC_CALLBACK_1(DragDropManager::onDragEnd, this));
|
||||
}
|
||||
|
||||
DragDropManager::~DragDropManager()
|
||||
{
|
||||
CC_SAFE_RELEASE(_agent);
|
||||
}
|
||||
|
||||
DragDropManager* DragDropManager::getInstance()
|
||||
{
|
||||
if (_inst == nullptr)
|
||||
_inst = new DragDropManager();
|
||||
|
||||
return _inst;
|
||||
}
|
||||
|
||||
void DragDropManager::startDrag(const std::string & icon, const Value& sourceData, int touchPointID)
|
||||
{
|
||||
if (_agent->getParent() != nullptr)
|
||||
return;
|
||||
|
||||
_sourceData = sourceData;
|
||||
_agent->setURL(icon);
|
||||
UIRoot->addChild(_agent);
|
||||
Vec2 pt = UIRoot->globalToLocal(UIRoot->getTouchPosition(touchPointID));
|
||||
_agent->setPosition(pt.x, pt.y);
|
||||
_agent->startDrag(touchPointID);
|
||||
}
|
||||
|
||||
void DragDropManager::cancel()
|
||||
{
|
||||
if (_agent->getParent() != nullptr)
|
||||
{
|
||||
_agent->stopDrag();
|
||||
UIRoot->removeChild(_agent);
|
||||
_sourceData = Value::Null;
|
||||
}
|
||||
}
|
||||
|
||||
void DragDropManager::onDragEnd(EventContext * context)
|
||||
{
|
||||
if (_agent->getParent() == nullptr) //cancelled
|
||||
return;
|
||||
|
||||
UIRoot->removeChild(_agent);
|
||||
|
||||
GObject* obj = UIRoot->getTouchTarget();
|
||||
while (obj != nullptr)
|
||||
{
|
||||
if (dynamic_cast<GComponent*>(obj))
|
||||
{
|
||||
if (obj->hasEventListener(UIEventType::Drop))
|
||||
{
|
||||
//obj->requestFocus();
|
||||
obj->dispatchEvent(UIEventType::Drop, nullptr, _sourceData);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
obj = obj->getParent();
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef __DRAGDROPMANAGER_H__
|
||||
#define __DRAGDROPMANAGER_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
#include "GLoader.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class DragDropManager
|
||||
{
|
||||
public:
|
||||
DragDropManager();
|
||||
~DragDropManager();
|
||||
|
||||
static DragDropManager* getInstance();
|
||||
|
||||
GLoader* getAgent() const { return _agent; }
|
||||
bool isDragging() const { return _agent->getParent() != nullptr; }
|
||||
void startDrag(const std::string& icon, const cocos2d::Value& sourceData = cocos2d::Value::Null, int touchPointID = -1);
|
||||
void cancel();
|
||||
|
||||
private:
|
||||
void onDragEnd(EventContext* context);
|
||||
|
||||
static DragDropManager* _inst;
|
||||
|
||||
GLoader* _agent;
|
||||
cocos2d::Value _sourceData;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef __FAIRYGUI_H__
|
||||
#define __FAIRYGUI_H__
|
||||
|
||||
#include "UIConfig.h"
|
||||
#include "UIPackage.h"
|
||||
#include "GImage.h"
|
||||
#include "GMovieClip.h"
|
||||
#include "GTextField.h"
|
||||
#include "GRichTextField.h"
|
||||
#include "GTextInput.h"
|
||||
#include "GGraph.h"
|
||||
#include "GLoader.h"
|
||||
#include "GGroup.h"
|
||||
#include "GComponent.h"
|
||||
#include "GLabel.h"
|
||||
#include "GButton.h"
|
||||
#include "GComboBox.h"
|
||||
#include "GProgressBar.h"
|
||||
#include "GSlider.h"
|
||||
#include "GScrollBar.h"
|
||||
#include "GList.h"
|
||||
#include "GTree.h"
|
||||
#include "GRoot.h"
|
||||
#include "Window.h"
|
||||
#include "PopupMenu.h"
|
||||
#include "UIObjectFactory.h"
|
||||
#include "GObjectPool.h"
|
||||
#include "DragDropManager.h"
|
||||
#include "tween/GTween.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef __FAIRYGUIMACROS_H__
|
||||
#define __FAIRYGUIMACROS_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
|
||||
#define NS_FGUI_BEGIN namespace fairygui {
|
||||
#define NS_FGUI_END }
|
||||
#define USING_NS_FGUI using namespace fairygui
|
||||
|
||||
#define CALL_LATER_FUNC(__TYPE__,__FUNC__) \
|
||||
void __selector_##__FUNC__(float dt) \
|
||||
{\
|
||||
cocos2d::Director::getInstance()->getScheduler()->unschedule(CC_SCHEDULE_SELECTOR(__TYPE__::__selector_##__FUNC__), this);\
|
||||
__FUNC__(); \
|
||||
}\
|
||||
void __FUNC__()
|
||||
|
||||
#define CALL_LATER(__TYPE__,__FUNC__,...) \
|
||||
if (!cocos2d::Director::getInstance()->getScheduler()->isScheduled(CC_SCHEDULE_SELECTOR(__TYPE__::__selector_##__FUNC__), this))\
|
||||
cocos2d::Director::getInstance()->getScheduler()->schedule(CC_SCHEDULE_SELECTOR(__TYPE__::__selector_##__FUNC__), this, (__VA_ARGS__+0), false)
|
||||
|
||||
#define CALL_LATER_CANCEL(__TYPE__,__FUNC__) \
|
||||
cocos2d::Director::getInstance()->getScheduler()->unschedule(CC_SCHEDULE_SELECTOR(__TYPE__::__selector_##__FUNC__), this)
|
||||
|
||||
#define CALL_PER_FRAME(__TYPE__,__FUNC__) \
|
||||
if (!cocos2d::Director::getInstance()->getScheduler()->isScheduled(CC_SCHEDULE_SELECTOR(__TYPE__::__FUNC__), this))\
|
||||
cocos2d::Director::getInstance()->getScheduler()->schedule(CC_SCHEDULE_SELECTOR(__TYPE__::__FUNC__), this, 0, false)
|
||||
|
||||
#define CALL_PER_FRAME_CANCEL(__TYPE__,__FUNC__) \
|
||||
cocos2d::Director::getInstance()->getScheduler()->unschedule(CC_SCHEDULE_SELECTOR(__TYPE__::__FUNC__), this)
|
||||
|
||||
#define UIRoot GRoot::getInstance()
|
||||
|
||||
#include "FieldTypes.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,201 @@
|
|||
#ifndef __FIELDTYPES_H__
|
||||
#define __FIELDTYPES_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
enum class PackageItemType
|
||||
{
|
||||
IMAGE,
|
||||
MOVIECLIP,
|
||||
SOUND,
|
||||
COMPONENT,
|
||||
ATLAS,
|
||||
FONT,
|
||||
SWF,
|
||||
MISC,
|
||||
UNKNOWN,
|
||||
SPINE,
|
||||
DRAGONBONES
|
||||
};
|
||||
|
||||
enum class ObjectType
|
||||
{
|
||||
IMAGE,
|
||||
MOVIECLIP,
|
||||
SWF,
|
||||
GRAPH,
|
||||
LOADER,
|
||||
GROUP,
|
||||
TEXT,
|
||||
RICHTEXT,
|
||||
INPUTTEXT,
|
||||
COMPONENT,
|
||||
LIST,
|
||||
LABEL,
|
||||
BUTTON,
|
||||
COMBOBOX,
|
||||
PROGRESSBAR,
|
||||
SLIDER,
|
||||
SCROLLBAR,
|
||||
TREE,
|
||||
LOADER3D
|
||||
};
|
||||
|
||||
enum class ButtonMode
|
||||
{
|
||||
COMMON,
|
||||
CHECK,
|
||||
RADIO
|
||||
};
|
||||
|
||||
enum class ChildrenRenderOrder
|
||||
{
|
||||
ASCENT,
|
||||
DESCENT,
|
||||
ARCH,
|
||||
};
|
||||
|
||||
enum class OverflowType
|
||||
{
|
||||
VISIBLE,
|
||||
HIDDEN,
|
||||
SCROLL
|
||||
};
|
||||
|
||||
enum class ScrollType
|
||||
{
|
||||
HORIZONTAL,
|
||||
VERTICAL,
|
||||
BOTH
|
||||
};
|
||||
|
||||
enum ScrollBarDisplayType
|
||||
{
|
||||
DEFAULT,
|
||||
VISIBLE,
|
||||
AUTO,
|
||||
HIDDEN
|
||||
};
|
||||
|
||||
enum class LoaderFillType
|
||||
{
|
||||
NONE,
|
||||
SCALE,
|
||||
SCALE_MATCH_HEIGHT,
|
||||
SCALE_MATCH_WIDTH,
|
||||
SCALE_FREE,
|
||||
SCALE_NO_BORDER
|
||||
};
|
||||
|
||||
enum class ProgressTitleType
|
||||
{
|
||||
PERCENT,
|
||||
VALUE_MAX,
|
||||
VALUE,
|
||||
MAX
|
||||
};
|
||||
|
||||
enum class ListLayoutType
|
||||
{
|
||||
SINGLE_COLUMN,
|
||||
SINGLE_ROW,
|
||||
FLOW_HORIZONTAL,
|
||||
FLOW_VERTICAL,
|
||||
PAGINATION
|
||||
};
|
||||
|
||||
enum class ListSelectionMode
|
||||
{
|
||||
SINGLE,
|
||||
MULTIPLE,
|
||||
MULTIPLE_SINGLECLICK,
|
||||
NONE
|
||||
};
|
||||
|
||||
enum class GroupLayoutType
|
||||
{
|
||||
NONE,
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
};
|
||||
|
||||
enum class PopupDirection
|
||||
{
|
||||
AUTO,
|
||||
UP,
|
||||
DOWN
|
||||
};
|
||||
|
||||
enum class AutoSizeType
|
||||
{
|
||||
NONE,
|
||||
BOTH,
|
||||
HEIGHT,
|
||||
SHRINK
|
||||
};
|
||||
|
||||
enum class FlipType
|
||||
{
|
||||
NONE,
|
||||
HORIZONTAL,
|
||||
VERTICAL,
|
||||
BOTH
|
||||
};
|
||||
|
||||
enum class TransitionActionType
|
||||
{
|
||||
XY,
|
||||
Size,
|
||||
Scale,
|
||||
Pivot,
|
||||
Alpha,
|
||||
Rotation,
|
||||
Color,
|
||||
Animation,
|
||||
Visible,
|
||||
Sound,
|
||||
Transition,
|
||||
Shake,
|
||||
ColorFilter,
|
||||
Skew,
|
||||
Text,
|
||||
Icon,
|
||||
Unknown
|
||||
};
|
||||
|
||||
enum class FillMethod
|
||||
{
|
||||
None,
|
||||
Horizontal,
|
||||
Vertical,
|
||||
Radial90,
|
||||
Radial180,
|
||||
Radial360,
|
||||
};
|
||||
|
||||
enum class FillOrigin
|
||||
{
|
||||
Top,
|
||||
Bottom,
|
||||
Left,
|
||||
Right
|
||||
};
|
||||
|
||||
enum class ObjectPropID {
|
||||
Text,
|
||||
Icon,
|
||||
Color,
|
||||
OutlineColor,
|
||||
Playing,
|
||||
Frame,
|
||||
DeltaTime,
|
||||
TimeScale,
|
||||
FontSize,
|
||||
Selected
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,453 @@
|
|||
#include "GButton.h"
|
||||
#include "GLabel.h"
|
||||
#include "GRoot.h"
|
||||
#include "GTextField.h"
|
||||
#include "PackageItem.h"
|
||||
#include "UIConfig.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
const std::string GButton::UP = "up";
|
||||
const std::string GButton::DOWN = "down";
|
||||
const std::string GButton::OVER = "over";
|
||||
const std::string GButton::SELECTED_OVER = "selectedOver";
|
||||
const std::string GButton::DISABLED = "disabled";
|
||||
const std::string GButton::SELECTED_DISABLED = "selectedDisabled";
|
||||
|
||||
GButton::GButton() : _mode(ButtonMode::COMMON),
|
||||
_titleObject(nullptr),
|
||||
_iconObject(nullptr),
|
||||
_buttonController(nullptr),
|
||||
_relatedController(nullptr),
|
||||
_selected(false),
|
||||
_over(false),
|
||||
_down(false),
|
||||
_downEffect(0),
|
||||
_downScaled(false),
|
||||
_downEffectValue(0.8f),
|
||||
_changeStateOnClick(true)
|
||||
{
|
||||
_sound = UIConfig::buttonSound;
|
||||
_soundVolumeScale = UIConfig::buttonSoundVolumeScale;
|
||||
}
|
||||
|
||||
GButton::~GButton()
|
||||
{
|
||||
}
|
||||
|
||||
void GButton::setTitle(const std::string& value)
|
||||
{
|
||||
_title = value;
|
||||
if (_titleObject != nullptr)
|
||||
_titleObject->setText((_selected && _selectedTitle.length() > 0) ? _selectedTitle : _title);
|
||||
updateGear(6);
|
||||
}
|
||||
|
||||
void GButton::setIcon(const std::string& value)
|
||||
{
|
||||
_icon = value;
|
||||
if (_iconObject != nullptr)
|
||||
_iconObject->setIcon((_selected && _selectedIcon.length() > 0) ? _selectedIcon : _icon);
|
||||
updateGear(7);
|
||||
}
|
||||
|
||||
void GButton::setSelectedTitle(const std::string& value)
|
||||
{
|
||||
_selectedTitle = value;
|
||||
if (_titleObject != nullptr)
|
||||
_titleObject->setText((_selected && _selectedTitle.length() > 0) ? _selectedTitle : _title);
|
||||
}
|
||||
|
||||
void GButton::setSelectedIcon(const std::string& value)
|
||||
{
|
||||
_selectedIcon = value;
|
||||
if (_iconObject != nullptr)
|
||||
_iconObject->setIcon((_selected && _selectedIcon.length() > 0) ? _selectedIcon : _icon);
|
||||
}
|
||||
|
||||
cocos2d::Color3B GButton::getTitleColor() const
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
return tf->getColor();
|
||||
else
|
||||
return Color3B::BLACK;
|
||||
}
|
||||
|
||||
void GButton::setTitleColor(const cocos2d::Color3B& value)
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
tf->setColor(value);
|
||||
}
|
||||
|
||||
int GButton::getTitleFontSize() const
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
return tf->getFontSize();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GButton::setTitleFontSize(int value)
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
tf->setFontSize(value);
|
||||
}
|
||||
|
||||
void GButton::setSelected(bool value)
|
||||
{
|
||||
if (_mode == ButtonMode::COMMON)
|
||||
return;
|
||||
|
||||
if (_selected != value)
|
||||
{
|
||||
_selected = value;
|
||||
setCurrentState();
|
||||
if (!_selectedTitle.empty() && _titleObject != nullptr)
|
||||
_titleObject->setText(_selected ? _selectedTitle : _title);
|
||||
if (!_selectedIcon.empty())
|
||||
{
|
||||
const std::string& str = _selected ? _selectedIcon : _icon;
|
||||
if (_iconObject != nullptr)
|
||||
_iconObject->setIcon(str);
|
||||
}
|
||||
if (_relatedController != nullptr && getParent() != nullptr && !getParent()->_buildingDisplayList)
|
||||
{
|
||||
if (_selected)
|
||||
{
|
||||
_relatedController->setSelectedPageId(_relatedPageId);
|
||||
if (_relatedController->autoRadioGroupDepth)
|
||||
getParent()->adjustRadioGroupDepth(this, _relatedController);
|
||||
}
|
||||
else if (_mode == ButtonMode::CHECK && _relatedController->getSelectedPageId().compare(_relatedPageId) == 0)
|
||||
_relatedController->setOppositePageId(_relatedPageId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GButton::setRelatedController(GController* c)
|
||||
{
|
||||
_relatedController = c;
|
||||
}
|
||||
|
||||
void GButton::setState(const std::string& value)
|
||||
{
|
||||
if (_buttonController != nullptr)
|
||||
_buttonController->setSelectedPage(value);
|
||||
|
||||
if (_downEffect == 1)
|
||||
{
|
||||
int cnt = this->numChildren();
|
||||
if (value == DOWN || value == SELECTED_OVER || value == SELECTED_DISABLED)
|
||||
{
|
||||
int c = _downEffectValue * 255;
|
||||
Value color = Value((c << 16) + (c << 8) + c);
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* obj = this->getChildAt(i);
|
||||
if (dynamic_cast<GTextField*>(obj) == nullptr)
|
||||
obj->setProp(ObjectPropID::Color, color);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Value color = Value(0xFFFFFF);
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* obj = this->getChildAt(i);
|
||||
if (dynamic_cast<GTextField*>(obj) == nullptr)
|
||||
obj->setProp(ObjectPropID::Color, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_downEffect == 2)
|
||||
{
|
||||
if (value == DOWN || value == SELECTED_OVER || value == SELECTED_DISABLED)
|
||||
{
|
||||
if (!_downScaled)
|
||||
{
|
||||
_downScaled = true;
|
||||
setScale(getScaleX() * _downEffectValue, getScaleY() * _downEffectValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_downScaled)
|
||||
{
|
||||
_downScaled = false;
|
||||
setScale(getScaleX() / _downEffectValue, getScaleY() / _downEffectValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GButton::setCurrentState()
|
||||
{
|
||||
if (isGrayed() && _buttonController != nullptr && _buttonController->hasPage(DISABLED))
|
||||
{
|
||||
if (_selected)
|
||||
setState(SELECTED_DISABLED);
|
||||
else
|
||||
setState(DISABLED);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_selected)
|
||||
setState(_over ? SELECTED_OVER : DOWN);
|
||||
else
|
||||
setState(_over ? OVER : UP);
|
||||
}
|
||||
}
|
||||
|
||||
GTextField* GButton::getTextField() const
|
||||
{
|
||||
if (dynamic_cast<GTextField*>(_titleObject))
|
||||
return dynamic_cast<GTextField*>(_titleObject);
|
||||
else if (dynamic_cast<GLabel*>(_titleObject))
|
||||
return dynamic_cast<GLabel*>(_titleObject)->getTextField();
|
||||
else if (dynamic_cast<GButton*>(_titleObject))
|
||||
return dynamic_cast<GButton*>(_titleObject)->getTextField();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cocos2d::Value GButton::getProp(ObjectPropID propId)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
return Value(ToolSet::colorToInt(getTitleColor()));
|
||||
case ObjectPropID::OutlineColor:
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf != nullptr)
|
||||
return Value(ToolSet::colorToInt(tf->getOutlineColor()));
|
||||
else
|
||||
return Value::Null;
|
||||
}
|
||||
case ObjectPropID::FontSize:
|
||||
return Value(getTitleFontSize());
|
||||
case ObjectPropID::Selected:
|
||||
return Value(isSelected());
|
||||
default:
|
||||
return GComponent::getProp(propId);
|
||||
}
|
||||
}
|
||||
|
||||
void GButton::setProp(ObjectPropID propId, const cocos2d::Value& value)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
setTitleColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
case ObjectPropID::OutlineColor:
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf != nullptr)
|
||||
tf->setOutlineColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
}
|
||||
case ObjectPropID::FontSize:
|
||||
setTitleFontSize(value.asInt());
|
||||
break;
|
||||
case ObjectPropID::Selected:
|
||||
setSelected(value.asBool());
|
||||
break;
|
||||
default:
|
||||
GComponent::setProp(propId, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GButton::constructExtension(ByteBuffer* buffer)
|
||||
{
|
||||
buffer->seek(0, 6);
|
||||
|
||||
_mode = (ButtonMode)buffer->readByte();
|
||||
buffer->readS(_sound);
|
||||
_soundVolumeScale = buffer->readFloat();
|
||||
_downEffect = buffer->readByte();
|
||||
_downEffectValue = buffer->readFloat();
|
||||
if (_downEffect == 2)
|
||||
setPivot(0.5f, 0.5f, isPivotAsAnchor());
|
||||
|
||||
_buttonController = getController("button");
|
||||
_titleObject = getChild("title");
|
||||
_iconObject = getChild("icon");
|
||||
if (_titleObject != nullptr)
|
||||
_title = _titleObject->getText();
|
||||
if (_iconObject != nullptr)
|
||||
_icon = _iconObject->getIcon();
|
||||
|
||||
if (_mode == ButtonMode::COMMON)
|
||||
setState(UP);
|
||||
|
||||
addEventListener(UIEventType::RollOver, CC_CALLBACK_1(GButton::onRollOver, this));
|
||||
addEventListener(UIEventType::RollOut, CC_CALLBACK_1(GButton::onRollOut, this));
|
||||
addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GButton::onTouchBegin, this));
|
||||
addEventListener(UIEventType::TouchEnd, CC_CALLBACK_1(GButton::onTouchEnd, this));
|
||||
addEventListener(UIEventType::Click, CC_CALLBACK_1(GButton::onClick, this));
|
||||
addEventListener(UIEventType::Exit, CC_CALLBACK_1(GButton::onExit, this));
|
||||
}
|
||||
|
||||
void GButton::setup_afterAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GComponent::setup_afterAdd(buffer, beginPos);
|
||||
|
||||
if (!buffer->seek(beginPos, 6))
|
||||
return;
|
||||
|
||||
if ((ObjectType)buffer->readByte() != _packageItem->objectType)
|
||||
return;
|
||||
|
||||
const std::string* str;
|
||||
|
||||
if ((str = buffer->readSP()))
|
||||
setTitle(*str);
|
||||
if ((str = buffer->readSP()))
|
||||
setSelectedTitle(*str);
|
||||
if ((str = buffer->readSP()))
|
||||
setIcon(*str);
|
||||
if ((str = buffer->readSP()))
|
||||
setSelectedIcon(*str);
|
||||
if (buffer->readBool())
|
||||
setTitleColor((Color3B)buffer->readColor());
|
||||
int iv = buffer->readInt();
|
||||
if (iv != 0)
|
||||
setTitleFontSize(iv);
|
||||
iv = buffer->readShort();
|
||||
if (iv >= 0)
|
||||
_relatedController = _parent->getControllerAt(iv);
|
||||
_relatedPageId = buffer->readS();
|
||||
|
||||
buffer->readS(_sound);
|
||||
if (buffer->readBool())
|
||||
_soundVolumeScale = buffer->readFloat();
|
||||
|
||||
setSelected(buffer->readBool());
|
||||
}
|
||||
|
||||
void GButton::handleControllerChanged(GController* c)
|
||||
{
|
||||
GObject::handleControllerChanged(c);
|
||||
|
||||
if (_relatedController == c)
|
||||
setSelected(_relatedPageId.compare(c->getSelectedPageId()) == 0);
|
||||
}
|
||||
|
||||
void GButton::onRollOver(EventContext* context)
|
||||
{
|
||||
if (_buttonController == nullptr || !_buttonController->hasPage(OVER))
|
||||
return;
|
||||
|
||||
_over = true;
|
||||
if (_down)
|
||||
return;
|
||||
|
||||
if (isGrayed() && _buttonController->hasPage(DISABLED))
|
||||
return;
|
||||
|
||||
setState(_selected ? SELECTED_OVER : OVER);
|
||||
}
|
||||
|
||||
void GButton::onRollOut(EventContext* context)
|
||||
{
|
||||
if (_buttonController == nullptr || !_buttonController->hasPage(OVER))
|
||||
return;
|
||||
|
||||
_over = false;
|
||||
if (_down)
|
||||
return;
|
||||
|
||||
if (isGrayed() && _buttonController->hasPage(DISABLED))
|
||||
return;
|
||||
|
||||
setState(_selected ? DOWN : UP);
|
||||
}
|
||||
|
||||
void GButton::onTouchBegin(EventContext* context)
|
||||
{
|
||||
if (context->getInput()->getButton() != EventMouse::MouseButton::BUTTON_LEFT)
|
||||
return;
|
||||
|
||||
_down = true;
|
||||
context->captureTouch();
|
||||
|
||||
if (_mode == ButtonMode::COMMON)
|
||||
{
|
||||
if (isGrayed() && _buttonController != nullptr && _buttonController->hasPage(DISABLED))
|
||||
setState(SELECTED_DISABLED);
|
||||
else
|
||||
setState(DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
void GButton::onTouchEnd(EventContext* context)
|
||||
{
|
||||
if (context->getInput()->getButton() != EventMouse::MouseButton::BUTTON_LEFT)
|
||||
return;
|
||||
|
||||
if (_down)
|
||||
{
|
||||
_down = false;
|
||||
if (_mode == ButtonMode::COMMON)
|
||||
{
|
||||
if (isGrayed() && _buttonController != nullptr && _buttonController->hasPage(DISABLED))
|
||||
setState(DISABLED);
|
||||
else if (_over)
|
||||
setState(OVER);
|
||||
else
|
||||
setState(UP);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_over && _buttonController != nullptr && (_buttonController->getSelectedPage() == OVER || _buttonController->getSelectedPage() == SELECTED_OVER))
|
||||
{
|
||||
setCurrentState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GButton::onClick(EventContext* context)
|
||||
{
|
||||
if (!_sound.empty())
|
||||
UIRoot->playSound(_sound, _soundVolumeScale);
|
||||
|
||||
if (_mode == ButtonMode::CHECK)
|
||||
{
|
||||
if (_changeStateOnClick)
|
||||
{
|
||||
setSelected(!_selected);
|
||||
dispatchEvent(UIEventType::Changed);
|
||||
}
|
||||
}
|
||||
else if (_mode == ButtonMode::RADIO)
|
||||
{
|
||||
if (_changeStateOnClick && !_selected)
|
||||
{
|
||||
setSelected(true);
|
||||
dispatchEvent(UIEventType::Changed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_relatedController != nullptr)
|
||||
_relatedController->setSelectedPageId(_relatedPageId);
|
||||
}
|
||||
}
|
||||
|
||||
void GButton::onExit(EventContext* context)
|
||||
{
|
||||
if (_over)
|
||||
onRollOut(context);
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,101 @@
|
|||
#ifndef __GBUTTON_H
|
||||
#define __GBUTTON_H
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GComponent.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GTextField;
|
||||
|
||||
class GButton : public GComponent
|
||||
{
|
||||
public:
|
||||
static const std::string UP;
|
||||
static const std::string DOWN;
|
||||
static const std::string OVER;
|
||||
static const std::string SELECTED_OVER;
|
||||
static const std::string DISABLED;
|
||||
static const std::string SELECTED_DISABLED;
|
||||
|
||||
GButton();
|
||||
virtual ~GButton();
|
||||
|
||||
CREATE_FUNC(GButton);
|
||||
|
||||
const std::string& getTitle() { return _title; }
|
||||
void setTitle(const std::string& value);
|
||||
|
||||
virtual const std::string& getText() const override { return _title; }
|
||||
virtual void setText(const std::string& value) override { setTitle(value); }
|
||||
|
||||
virtual const std::string& getIcon() const override { return _icon; }
|
||||
virtual void setIcon(const std::string& value) override;
|
||||
|
||||
const std::string& getSelectedTitle() const { return _selectedTitle; }
|
||||
void setSelectedTitle(const std::string& value);
|
||||
|
||||
const std::string& getSelectedIcon() const { return _selectedIcon; }
|
||||
void setSelectedIcon(const std::string& value);
|
||||
|
||||
cocos2d::Color3B getTitleColor() const;
|
||||
void setTitleColor(const cocos2d::Color3B& value);
|
||||
|
||||
int getTitleFontSize() const;
|
||||
void setTitleFontSize(int value);
|
||||
|
||||
bool isSelected() const { return _selected; }
|
||||
void setSelected(bool value);
|
||||
|
||||
GController* getRelatedController() const { return _relatedController; }
|
||||
void setRelatedController(GController* c);
|
||||
|
||||
bool isChangeStateOnClick() { return _changeStateOnClick; }
|
||||
void setChangeStateOnClick(bool value) { _changeStateOnClick = value; }
|
||||
|
||||
GTextField* getTextField() const;
|
||||
|
||||
virtual cocos2d::Value getProp(ObjectPropID propId) override;
|
||||
virtual void setProp(ObjectPropID propId, const cocos2d::Value& value) override;
|
||||
|
||||
protected:
|
||||
virtual void constructExtension(ByteBuffer* buffer) override;
|
||||
virtual void setup_afterAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual void handleControllerChanged(GController* c) override;
|
||||
|
||||
void setState(const std::string& value);
|
||||
void setCurrentState();
|
||||
|
||||
private:
|
||||
void onRollOver(EventContext* context);
|
||||
void onRollOut(EventContext* context);
|
||||
void onTouchBegin(EventContext* context);
|
||||
void onTouchEnd(EventContext* context);
|
||||
void onClick(EventContext* context);
|
||||
void onExit(EventContext* context);
|
||||
|
||||
ButtonMode _mode;
|
||||
GObject* _titleObject;
|
||||
GObject* _iconObject;
|
||||
GController* _buttonController;
|
||||
GController* _relatedController;
|
||||
std::string _relatedPageId;
|
||||
std::string _title;
|
||||
std::string _selectedTitle;
|
||||
std::string _icon;
|
||||
std::string _selectedIcon;
|
||||
std::string _sound;
|
||||
float _soundVolumeScale;
|
||||
bool _selected;
|
||||
bool _over;
|
||||
bool _down;
|
||||
int _downEffect;
|
||||
bool _downScaled;
|
||||
float _downEffectValue;
|
||||
bool _changeStateOnClick;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,452 @@
|
|||
#include "GComboBox.h"
|
||||
#include "GRoot.h"
|
||||
#include "PackageItem.h"
|
||||
#include "UIConfig.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GComboBox::GComboBox()
|
||||
: _dropdown(nullptr),
|
||||
_titleObject(nullptr),
|
||||
_iconObject(nullptr),
|
||||
_list(nullptr),
|
||||
_selectionController(nullptr),
|
||||
_itemsUpdated(true),
|
||||
_selectedIndex(-1),
|
||||
popupDirection(PopupDirection::AUTO)
|
||||
{
|
||||
visibleItemCount = UIConfig::defaultComboBoxVisibleItemCount;
|
||||
}
|
||||
|
||||
GComboBox::~GComboBox()
|
||||
{
|
||||
CC_SAFE_RELEASE(_dropdown);
|
||||
}
|
||||
|
||||
const std::string& GComboBox::getTitle() const
|
||||
{
|
||||
if (_titleObject != nullptr)
|
||||
return _titleObject->getText();
|
||||
else
|
||||
return STD_STRING_EMPTY;
|
||||
}
|
||||
|
||||
void GComboBox::setTitle(const std::string& value)
|
||||
{
|
||||
if (_titleObject != nullptr)
|
||||
_titleObject->setText(value);
|
||||
updateGear(6);
|
||||
}
|
||||
|
||||
const cocos2d::Color3B GComboBox::getTitleColor() const
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
return tf->getColor();
|
||||
else
|
||||
return Color3B::BLACK;
|
||||
}
|
||||
|
||||
void GComboBox::setTitleColor(const cocos2d::Color3B& value)
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
tf->setColor(value);
|
||||
}
|
||||
|
||||
int GComboBox::getTitleFontSize() const
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
return tf->getFontSize();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GComboBox::setTitleFontSize(int value)
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
tf->setFontSize(value);
|
||||
}
|
||||
|
||||
const std::string& GComboBox::getIcon() const
|
||||
{
|
||||
if (_iconObject != nullptr)
|
||||
return _iconObject->getIcon();
|
||||
else
|
||||
return STD_STRING_EMPTY;
|
||||
}
|
||||
|
||||
void GComboBox::setIcon(const std::string& value)
|
||||
{
|
||||
if (_iconObject != nullptr)
|
||||
_iconObject->setIcon(value);
|
||||
updateGear(7);
|
||||
}
|
||||
|
||||
const std::string& GComboBox::getValue() const
|
||||
{
|
||||
if (_selectedIndex >= 0 && _selectedIndex < (int)_values.size())
|
||||
return _values[_selectedIndex];
|
||||
else
|
||||
return STD_STRING_EMPTY;
|
||||
}
|
||||
|
||||
void GComboBox::setValue(const std::string& value)
|
||||
{
|
||||
setSelectedIndex(ToolSet::findInStringArray(_values, value));
|
||||
}
|
||||
|
||||
void GComboBox::setSelectedIndex(int value)
|
||||
{
|
||||
if (_selectedIndex == value)
|
||||
return;
|
||||
|
||||
_selectedIndex = value;
|
||||
if (_selectedIndex >= 0 && _selectedIndex < (int)_items.size())
|
||||
{
|
||||
setText(_items[_selectedIndex]);
|
||||
if (!_icons.empty() && _selectedIndex != -1 && _selectedIndex < (int)_icons.size())
|
||||
setIcon(_icons[_selectedIndex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTitle(STD_STRING_EMPTY);
|
||||
if (!_icons.empty())
|
||||
setIcon(STD_STRING_EMPTY);
|
||||
}
|
||||
|
||||
updateSelectionController();
|
||||
}
|
||||
|
||||
void GComboBox::refresh()
|
||||
{
|
||||
if (!_items.empty())
|
||||
{
|
||||
if (_selectedIndex >= (int)_items.size())
|
||||
_selectedIndex = (int)_items.size() - 1;
|
||||
else if (_selectedIndex == -1)
|
||||
_selectedIndex = 0;
|
||||
setTitle(_items[_selectedIndex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTitle(STD_STRING_EMPTY);
|
||||
_selectedIndex = -1;
|
||||
}
|
||||
|
||||
if (!_icons.empty())
|
||||
{
|
||||
if (_selectedIndex != -1 && _selectedIndex < (int)_icons.size())
|
||||
setIcon(_icons[_selectedIndex]);
|
||||
else
|
||||
setIcon(STD_STRING_EMPTY);
|
||||
}
|
||||
|
||||
_itemsUpdated = true;
|
||||
}
|
||||
|
||||
void GComboBox::setState(const std::string& value)
|
||||
{
|
||||
if (_buttonController != nullptr)
|
||||
_buttonController->setSelectedPage(value);
|
||||
}
|
||||
|
||||
void GComboBox::setCurrentState()
|
||||
{
|
||||
if (isGrayed() && _buttonController != nullptr && _buttonController->hasPage(GButton::DISABLED))
|
||||
setState(GButton::DISABLED);
|
||||
else if (_dropdown != nullptr && _dropdown->getParent() != nullptr)
|
||||
setState(GButton::DOWN);
|
||||
else
|
||||
setState(_over ? GButton::OVER : GButton::UP);
|
||||
}
|
||||
|
||||
void GComboBox::updateSelectionController()
|
||||
{
|
||||
if (_selectionController != nullptr && !_selectionController->changing && _selectedIndex < _selectionController->getPageCount())
|
||||
{
|
||||
GController* c = _selectionController;
|
||||
_selectionController = nullptr;
|
||||
c->setSelectedIndex(_selectedIndex);
|
||||
_selectionController = c;
|
||||
}
|
||||
}
|
||||
|
||||
void GComboBox::updateDropdownList()
|
||||
{
|
||||
if (_itemsUpdated)
|
||||
{
|
||||
_itemsUpdated = false;
|
||||
renderDropdownList();
|
||||
_list->resizeToFit(visibleItemCount);
|
||||
}
|
||||
}
|
||||
|
||||
void GComboBox::showDropdown()
|
||||
{
|
||||
updateDropdownList();
|
||||
if (_list->getSelectionMode() == ListSelectionMode::SINGLE)
|
||||
_list->setSelectedIndex(-1);
|
||||
_dropdown->setWidth(_size.width);
|
||||
_list->ensureBoundsCorrect();
|
||||
|
||||
UIRoot->togglePopup(_dropdown, this, popupDirection);
|
||||
if (_dropdown->getParent() != nullptr)
|
||||
setState(GButton::DOWN);
|
||||
}
|
||||
|
||||
void GComboBox::renderDropdownList()
|
||||
{
|
||||
_list->removeChildrenToPool();
|
||||
size_t cnt = _items.size();
|
||||
for (size_t i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* item = _list->addItemFromPool();
|
||||
item->setText(_items[i]);
|
||||
item->setIcon((!_icons.empty() && i < _icons.size()) ? _icons[i] : STD_STRING_EMPTY);
|
||||
item->name = i < _values.size() ? _values[i] : STD_STRING_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
void GComboBox::handleControllerChanged(GController* c)
|
||||
{
|
||||
GComponent::handleControllerChanged(c);
|
||||
|
||||
if (_selectionController == c)
|
||||
setSelectedIndex(c->getSelectedIndex());
|
||||
}
|
||||
|
||||
void GComboBox::handleGrayedChanged()
|
||||
{
|
||||
if (_buttonController != nullptr && _buttonController->hasPage(GButton::DISABLED))
|
||||
{
|
||||
if (isGrayed())
|
||||
setState(GButton::DISABLED);
|
||||
else
|
||||
setState(GButton::UP);
|
||||
}
|
||||
else
|
||||
GComponent::handleGrayedChanged();
|
||||
}
|
||||
|
||||
GTextField* GComboBox::getTextField() const
|
||||
{
|
||||
if (dynamic_cast<GTextField*>(_titleObject))
|
||||
return dynamic_cast<GTextField*>(_titleObject);
|
||||
else if (dynamic_cast<GLabel*>(_titleObject))
|
||||
return dynamic_cast<GLabel*>(_titleObject)->getTextField();
|
||||
else if (dynamic_cast<GButton*>(_titleObject))
|
||||
return dynamic_cast<GButton*>(_titleObject)->getTextField();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cocos2d::Value GComboBox::getProp(ObjectPropID propId)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
return Value(ToolSet::colorToInt(getTitleColor()));
|
||||
case ObjectPropID::OutlineColor:
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf != nullptr)
|
||||
return Value(ToolSet::colorToInt(tf->getOutlineColor()));
|
||||
else
|
||||
return Value::Null;
|
||||
}
|
||||
case ObjectPropID::FontSize:
|
||||
return Value(getTitleFontSize());
|
||||
default:
|
||||
return GComponent::getProp(propId);
|
||||
}
|
||||
}
|
||||
|
||||
void GComboBox::setProp(ObjectPropID propId, const cocos2d::Value& value)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
setTitleColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
case ObjectPropID::OutlineColor:
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf != nullptr)
|
||||
tf->setOutlineColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
}
|
||||
case ObjectPropID::FontSize:
|
||||
setTitleFontSize(value.asInt());
|
||||
break;
|
||||
default:
|
||||
GComponent::setProp(propId, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GComboBox::constructExtension(ByteBuffer* buffer)
|
||||
{
|
||||
buffer->seek(0, 6);
|
||||
|
||||
_buttonController = getController("button");
|
||||
_titleObject = getChild("title");
|
||||
_iconObject = getChild("icon");
|
||||
|
||||
const std::string& dropdown = buffer->readS();
|
||||
if (!dropdown.empty())
|
||||
{
|
||||
_dropdown = dynamic_cast<GComponent*>(UIPackage::createObjectFromURL(dropdown));
|
||||
CCASSERT(_dropdown != nullptr, "FairyGUI: should be a component.");
|
||||
|
||||
_dropdown->retain();
|
||||
|
||||
_list = dynamic_cast<GList*>(_dropdown->getChild("list"));
|
||||
CCASSERT(_list != nullptr, "FairyGUI: should container a list component named list.");
|
||||
|
||||
_list->addEventListener(UIEventType::ClickItem, CC_CALLBACK_1(GComboBox::onClickItem, this));
|
||||
|
||||
_list->addRelation(_dropdown, RelationType::Width);
|
||||
_list->removeRelation(_dropdown, RelationType::Height);
|
||||
|
||||
_dropdown->addRelation(_list, RelationType::Height);
|
||||
_dropdown->removeRelation(_list, RelationType::Width);
|
||||
|
||||
_dropdown->addEventListener(UIEventType::Exit, CC_CALLBACK_1(GComboBox::onPopupWinClosed, this));
|
||||
}
|
||||
|
||||
addEventListener(UIEventType::RollOver, CC_CALLBACK_1(GComboBox::onRollover, this));
|
||||
addEventListener(UIEventType::RollOut, CC_CALLBACK_1(GComboBox::onRollout, this));
|
||||
addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GComboBox::onTouchBegin, this));
|
||||
addEventListener(UIEventType::TouchEnd, CC_CALLBACK_1(GComboBox::onTouchEnd, this));
|
||||
}
|
||||
|
||||
void GComboBox::setup_afterAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GComponent::setup_afterAdd(buffer, beginPos);
|
||||
|
||||
if (!buffer->seek(beginPos, 6))
|
||||
return;
|
||||
|
||||
if ((ObjectType)buffer->readByte() != _packageItem->objectType)
|
||||
return;
|
||||
|
||||
const std::string* str;
|
||||
bool hasIcon = false;
|
||||
int itemCount = buffer->readShort();
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
{
|
||||
int nextPos = buffer->readShort();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
_items.push_back(buffer->readS());
|
||||
_values.push_back(buffer->readS());
|
||||
if ((str = buffer->readSP()))
|
||||
{
|
||||
if (!hasIcon)
|
||||
{
|
||||
for (int i = 0; i < (int)_items.size() - 1; i++)
|
||||
_icons.push_back(STD_STRING_EMPTY);
|
||||
}
|
||||
_icons.push_back(*str);
|
||||
}
|
||||
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
|
||||
if ((str = buffer->readSP()))
|
||||
{
|
||||
setTitle(*str);
|
||||
_selectedIndex = ToolSet::findInStringArray(_items, *str);
|
||||
}
|
||||
else if (!_items.empty())
|
||||
{
|
||||
_selectedIndex = 0;
|
||||
setTitle(_items[0]);
|
||||
}
|
||||
else
|
||||
_selectedIndex = -1;
|
||||
|
||||
if ((str = buffer->readSP()))
|
||||
setIcon(*str);
|
||||
|
||||
if (buffer->readBool())
|
||||
setTitleColor((Color3B)buffer->readColor());
|
||||
int iv = buffer->readInt();
|
||||
if (iv > 0)
|
||||
visibleItemCount = iv;
|
||||
popupDirection = (PopupDirection)buffer->readByte();
|
||||
|
||||
iv = buffer->readShort();
|
||||
if (iv >= 0)
|
||||
_selectionController = _parent->getControllerAt(iv);
|
||||
}
|
||||
|
||||
void GComboBox::onClickItem(EventContext* context)
|
||||
{
|
||||
if (dynamic_cast<GRoot*>(_dropdown->getParent()))
|
||||
((GRoot*)_dropdown->getParent())->hidePopup(_dropdown);
|
||||
_selectedIndex = INT_MIN;
|
||||
setSelectedIndex(_list->getChildIndex((GObject*)context->getData()));
|
||||
|
||||
dispatchEvent(UIEventType::Changed);
|
||||
}
|
||||
|
||||
void GComboBox::onRollover(EventContext* context)
|
||||
{
|
||||
_over = true;
|
||||
if (_down || (_dropdown != nullptr && _dropdown->getParent() != nullptr))
|
||||
return;
|
||||
|
||||
setCurrentState();
|
||||
}
|
||||
|
||||
void GComboBox::onRollout(EventContext* context)
|
||||
{
|
||||
_over = false;
|
||||
if (_down || (_dropdown != nullptr && _dropdown->getParent() != nullptr))
|
||||
return;
|
||||
|
||||
setCurrentState();
|
||||
}
|
||||
|
||||
void GComboBox::onTouchBegin(EventContext* context)
|
||||
{
|
||||
if (context->getInput()->getButton() != EventMouse::MouseButton::BUTTON_LEFT)
|
||||
return;
|
||||
|
||||
if (dynamic_cast<GTextInput*>(context->getInput()->getTarget()))
|
||||
return;
|
||||
|
||||
_down = true;
|
||||
|
||||
if (_dropdown != nullptr)
|
||||
showDropdown();
|
||||
|
||||
context->captureTouch();
|
||||
}
|
||||
|
||||
void GComboBox::onTouchEnd(EventContext* context)
|
||||
{
|
||||
if (context->getInput()->getButton() != EventMouse::MouseButton::BUTTON_LEFT)
|
||||
return;
|
||||
|
||||
if (_down)
|
||||
{
|
||||
_down = false;
|
||||
if (_dropdown != nullptr && _dropdown->getParent() != nullptr)
|
||||
setCurrentState();
|
||||
}
|
||||
}
|
||||
|
||||
void GComboBox::onPopupWinClosed(EventContext* context)
|
||||
{
|
||||
setCurrentState();
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,102 @@
|
|||
#ifndef __GCOMBOBOX_H__
|
||||
#define __GCOMBOBOX_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GComponent.h"
|
||||
#include "GList.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GTextField;
|
||||
|
||||
class GComboBox : public GComponent
|
||||
{
|
||||
public:
|
||||
GComboBox();
|
||||
virtual ~GComboBox();
|
||||
|
||||
CREATE_FUNC(GComboBox);
|
||||
|
||||
const std::string& getTitle() const;
|
||||
void setTitle(const std::string& value);
|
||||
|
||||
virtual const std::string& getText() const override { return getTitle(); }
|
||||
virtual void setText(const std::string& value) override { setTitle(value); }
|
||||
|
||||
const cocos2d::Color3B getTitleColor() const;
|
||||
void setTitleColor(const cocos2d::Color3B& value);
|
||||
|
||||
int getTitleFontSize() const;
|
||||
void setTitleFontSize(int value);
|
||||
|
||||
virtual const std::string& getIcon() const override;
|
||||
virtual void setIcon(const std::string& value) override;
|
||||
|
||||
const std::string& getValue() const;
|
||||
void setValue(const std::string& value);
|
||||
|
||||
int getSelectedIndex() const { return _selectedIndex; }
|
||||
void setSelectedIndex(int value);
|
||||
|
||||
GController* getSelectionController() const { return _selectionController; }
|
||||
void setSelectionController(GController* value) { _selectionController = value; }
|
||||
|
||||
std::vector<std::string>& getItems() { return _items; }
|
||||
std::vector<std::string>& getIcons() { return _icons; }
|
||||
std::vector<std::string>& getValues() { return _values; }
|
||||
|
||||
GObject* getDropdown() const { return _dropdown; }
|
||||
|
||||
void refresh();
|
||||
|
||||
int visibleItemCount;
|
||||
PopupDirection popupDirection;
|
||||
|
||||
GTextField* getTextField() const;
|
||||
|
||||
virtual cocos2d::Value getProp(ObjectPropID propId) override;
|
||||
virtual void setProp(ObjectPropID propId, const cocos2d::Value& value) override;
|
||||
|
||||
protected:
|
||||
virtual void constructExtension(ByteBuffer* buffer) override;
|
||||
virtual void setup_afterAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual void handleControllerChanged(GController* c) override;
|
||||
virtual void handleGrayedChanged() override;
|
||||
|
||||
void setState(const std::string& value);
|
||||
void setCurrentState();
|
||||
void updateSelectionController();
|
||||
void updateDropdownList();
|
||||
void showDropdown();
|
||||
void renderDropdownList();
|
||||
|
||||
GComponent* _dropdown;
|
||||
GObject* _titleObject;
|
||||
GObject* _iconObject;
|
||||
GList* _list;
|
||||
GController* _selectionController;
|
||||
|
||||
std::vector<std::string> _items;
|
||||
std::vector<std::string> _icons;
|
||||
std::vector<std::string> _values;
|
||||
|
||||
private:
|
||||
|
||||
void onClickItem(EventContext* context);
|
||||
void onRollover(EventContext* context);
|
||||
void onRollout(EventContext* context);
|
||||
void onTouchBegin(EventContext* context);
|
||||
void onTouchEnd(EventContext* context);
|
||||
void onPopupWinClosed(EventContext* context);
|
||||
|
||||
bool _itemsUpdated;
|
||||
int _selectedIndex;
|
||||
GController* _buttonController;
|
||||
bool _down;
|
||||
bool _over;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,150 @@
|
|||
#ifndef __GCOMPONENT_H__
|
||||
#define __GCOMPONENT_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GObject.h"
|
||||
#include "Margin.h"
|
||||
#include "ScrollPane.h"
|
||||
#include "Transition.h"
|
||||
#include "cocos2d.h"
|
||||
#include "display/FUIContainer.h"
|
||||
#include "event/HitTest.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GComponent : public GObject
|
||||
{
|
||||
public:
|
||||
GComponent();
|
||||
virtual ~GComponent();
|
||||
|
||||
CREATE_FUNC(GComponent);
|
||||
|
||||
GObject* addChild(GObject* child);
|
||||
virtual GObject* addChildAt(GObject* child, int index);
|
||||
|
||||
void removeChild(GObject* child);
|
||||
virtual void removeChildAt(int index);
|
||||
void removeChildren() { removeChildren(0, -1); }
|
||||
void removeChildren(int beginIndex, int endIndex);
|
||||
|
||||
GObject* getChildAt(int index) const;
|
||||
GObject* getChild(const std::string& name) const;
|
||||
GObject* getChildByPath(const std::string& path) const;
|
||||
GObject* getChildInGroup(const GGroup* group, const std::string& name) const;
|
||||
GObject* getChildById(const std::string& id) const;
|
||||
const cocos2d::Vector<GObject*>& getChildren() const { return _children; }
|
||||
|
||||
int getChildIndex(const GObject* child) const;
|
||||
void setChildIndex(GObject* child, int index);
|
||||
int setChildIndexBefore(GObject* child, int index);
|
||||
void swapChildren(GObject* child1, GObject* child2);
|
||||
void swapChildrenAt(int index1, int index2);
|
||||
|
||||
int numChildren() const;
|
||||
bool isAncestorOf(const GObject* obj) const;
|
||||
|
||||
virtual bool isChildInView(GObject* child);
|
||||
virtual int getFirstChildInView();
|
||||
|
||||
void addController(GController* c);
|
||||
GController* getControllerAt(int index) const;
|
||||
GController* getController(const std::string& name) const;
|
||||
const cocos2d::Vector<GController*>& getControllers() const { return _controllers; }
|
||||
void removeController(GController* c);
|
||||
void applyController(GController* c);
|
||||
void applyAllControllers();
|
||||
|
||||
Transition* getTransition(const std::string& name) const;
|
||||
Transition* getTransitionAt(int index) const;
|
||||
const cocos2d::Vector<Transition*>& getTransitions() const { return _transitions; }
|
||||
|
||||
bool getOpaque() const { return _opaque; }
|
||||
void setOpaque(bool value);
|
||||
|
||||
const Margin& getMargin() { return _margin; }
|
||||
void setMargin(const Margin& value);
|
||||
|
||||
ChildrenRenderOrder getChildrenRenderOrder() const { return _childrenRenderOrder; }
|
||||
void setChildrenRenderOrder(ChildrenRenderOrder value);
|
||||
int getApexIndex() const { return _apexIndex; }
|
||||
void setApexIndex(int value);
|
||||
|
||||
cocos2d::Node* getMask() const;
|
||||
void setMask(cocos2d::Node* value, bool inverted = false);
|
||||
|
||||
IHitTest* getHitArea() const { return _hitArea; }
|
||||
void setHitArea(IHitTest* value);
|
||||
|
||||
ScrollPane* getScrollPane() const { return _scrollPane; }
|
||||
|
||||
float getViewWidth() const;
|
||||
void setViewWidth(float value);
|
||||
float getViewHeight() const;
|
||||
void setViewHeight(float value);
|
||||
|
||||
void setBoundsChangedFlag();
|
||||
void ensureBoundsCorrect();
|
||||
|
||||
virtual GObject* hitTest(const cocos2d::Vec2& worldPoint, const cocos2d::Camera* camera) override;
|
||||
virtual cocos2d::Vec2 getSnappingPosition(const cocos2d::Vec2& pt);
|
||||
|
||||
//internal use
|
||||
void childSortingOrderChanged(GObject* child, int oldValue, int newValue);
|
||||
void childStateChanged(GObject* child);
|
||||
void adjustRadioGroupDepth(GObject* obj, GController* c);
|
||||
|
||||
virtual void constructFromResource() override;
|
||||
void constructFromResource(std::vector<GObject*>* objectPool, int poolIndex);
|
||||
|
||||
bool _buildingDisplayList;
|
||||
|
||||
protected:
|
||||
virtual void constructExtension(ByteBuffer* buffer);
|
||||
virtual void onConstruct();
|
||||
virtual void setup_afterAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual void handleInit() override;
|
||||
virtual void handleSizeChanged() override;
|
||||
virtual void handleGrayedChanged() override;
|
||||
virtual void handleControllerChanged(GController* c) override;
|
||||
|
||||
virtual void onEnter() override;
|
||||
virtual void onExit() override;
|
||||
|
||||
virtual void updateBounds();
|
||||
void setBounds(float ax, float ay, float aw, float ah);
|
||||
|
||||
void setupOverflow(OverflowType overflow);
|
||||
void setupScroll(ByteBuffer* buffer);
|
||||
|
||||
cocos2d::Vector<GObject*> _children;
|
||||
cocos2d::Vector<GController*> _controllers;
|
||||
cocos2d::Vector<Transition*> _transitions;
|
||||
FUIInnerContainer* _container;
|
||||
ScrollPane* _scrollPane;
|
||||
Margin _margin;
|
||||
cocos2d::Vec2 _alignOffset;
|
||||
ChildrenRenderOrder _childrenRenderOrder;
|
||||
int _apexIndex;
|
||||
bool _boundsChanged;
|
||||
bool _trackBounds;
|
||||
GObject* _maskOwner;
|
||||
IHitTest* _hitArea;
|
||||
|
||||
private:
|
||||
int getInsertPosForSortingChild(GObject* target);
|
||||
int moveChild(GObject* child, int oldIndex, int index);
|
||||
|
||||
CALL_LATER_FUNC(GComponent, doUpdateBounds);
|
||||
CALL_LATER_FUNC(GComponent, buildNativeDisplayList);
|
||||
|
||||
bool _opaque;
|
||||
int _sortingChildCount;
|
||||
GController* _applyingController;
|
||||
|
||||
friend class ScrollPane;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,290 @@
|
|||
#include "GGraph.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
static void drawVertRect(cocos2d::DrawNode* shape, float x, float y, float width, float height, const cocos2d::Color4F& color)
|
||||
{
|
||||
float mx = x + width;
|
||||
float my = y + height;
|
||||
shape->drawTriangle(Vec2(x, y), Vec2(mx, y), Vec2(x, my), color);
|
||||
shape->drawTriangle(Vec2(mx, y), Vec2(mx, my), Vec2(x, my), color);
|
||||
}
|
||||
|
||||
GGraph::GGraph() : _shape(nullptr),
|
||||
_type(0),
|
||||
_lineSize(1),
|
||||
_lineColor(Color4F::BLACK),
|
||||
_fillColor(Color4F::WHITE),
|
||||
_cornerRadius(nullptr),
|
||||
_polygonPoints(nullptr),
|
||||
_distances(nullptr)
|
||||
{
|
||||
_touchDisabled = true;
|
||||
}
|
||||
|
||||
GGraph::~GGraph()
|
||||
{
|
||||
CC_SAFE_DELETE(_cornerRadius);
|
||||
CC_SAFE_DELETE(_polygonPoints);
|
||||
CC_SAFE_DELETE(_distances);
|
||||
}
|
||||
|
||||
void GGraph::handleInit()
|
||||
{
|
||||
_shape = DrawNode::create();
|
||||
_shape->retain();
|
||||
|
||||
_displayObject = _shape;
|
||||
}
|
||||
|
||||
void GGraph::drawRect(float aWidth, float aHeight, int lineSize, const cocos2d::Color4F& lineColor, const cocos2d::Color4F& fillColor)
|
||||
{
|
||||
_type = 0; //avoid updateshape call in handleSizeChange
|
||||
setSize(aWidth, aHeight);
|
||||
_type = 1;
|
||||
_lineSize = lineSize;
|
||||
_lineColor = lineColor;
|
||||
_fillColor = fillColor;
|
||||
updateShape();
|
||||
}
|
||||
|
||||
void GGraph::drawEllipse(float aWidth, float aHeight, int lineSize, const cocos2d::Color4F& lineColor, const cocos2d::Color4F& fillColor)
|
||||
{
|
||||
_type = 0; //avoid updateshape call in handleSizeChange
|
||||
setSize(aWidth, aHeight);
|
||||
_type = 2;
|
||||
_lineSize = lineSize;
|
||||
_lineColor = lineColor;
|
||||
_fillColor = fillColor;
|
||||
updateShape();
|
||||
}
|
||||
|
||||
void GGraph::drawPolygon(int lineSize, const cocos2d::Color4F& lineColor, const cocos2d::Color4F& fillColor, const cocos2d::Vec2* points, int count)
|
||||
{
|
||||
_type = 3;
|
||||
_lineSize = lineSize;
|
||||
_lineColor = lineColor;
|
||||
_fillColor = fillColor;
|
||||
if (_polygonPoints == nullptr)
|
||||
_polygonPoints = new std::vector<Vec2>();
|
||||
else
|
||||
_polygonPoints->clear();
|
||||
float h = getHeight();
|
||||
_polygonPointOffset = h;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Vec2 pt = *(points + i);
|
||||
pt.y = h - pt.y;
|
||||
_polygonPoints->push_back(*(points + i));
|
||||
}
|
||||
updateShape();
|
||||
}
|
||||
|
||||
void GGraph::drawRegularPolygon(int lineSize, const cocos2d::Color4F& lineColor, const cocos2d::Color4F& fillColor,
|
||||
int sides, float startAngle, const float* distances, int count)
|
||||
{
|
||||
_type = 4;
|
||||
_lineSize = lineSize;
|
||||
_lineColor = lineColor;
|
||||
_fillColor = fillColor;
|
||||
_sides = sides;
|
||||
_startAngle = startAngle;
|
||||
if (distances != nullptr)
|
||||
{
|
||||
if (_distances == nullptr)
|
||||
_distances = new std::vector<float>();
|
||||
else
|
||||
_distances->clear();
|
||||
for (int i = 0; i < count; i++)
|
||||
_distances->push_back(*(distances + i));
|
||||
}
|
||||
else if (_distances != nullptr)
|
||||
_distances->clear();
|
||||
}
|
||||
|
||||
void GGraph::updateShape()
|
||||
{
|
||||
_shape->clear();
|
||||
if (_type == 0)
|
||||
{
|
||||
_touchDisabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_type)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if (_lineSize > 0)
|
||||
{
|
||||
float wl = _size.width - _lineSize;
|
||||
float hl = _size.height - _lineSize;
|
||||
drawVertRect(_shape, 0, 0, wl, _lineSize, _lineColor);
|
||||
drawVertRect(_shape, wl, 0, _lineSize, hl, _lineColor);
|
||||
drawVertRect(_shape, _lineSize, hl, wl, _lineSize, _lineColor);
|
||||
drawVertRect(_shape, 0, _lineSize, _lineSize, hl, _lineColor);
|
||||
|
||||
drawVertRect(_shape, _lineSize, _lineSize, _size.width - _lineSize * 2, _size.height - _lineSize * 2, _fillColor);
|
||||
}
|
||||
else
|
||||
drawVertRect(_shape, 0, 0, _size.width, _size.height, _fillColor);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (_lineSize > 0)
|
||||
{
|
||||
_shape->setLineWidth(_lineSize);
|
||||
_shape->drawCircle(Vec2(_size.width / 2, _size.height / 2), _size.width / 2, 0, 360, false, 1, _size.height / _size.width, _lineColor);
|
||||
}
|
||||
_shape->drawSolidCircle(Vec2(_size.width / 2, _size.height / 2), _size.width / 2, 0, 360, 1, _size.height / _size.width, _fillColor);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
_shape->drawPolygon(_polygonPoints->data(), (int)_polygonPoints->size(), _fillColor, _lineSize * 0.5f, _lineColor);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
float h = getHeight();
|
||||
_polygonPointOffset = h;
|
||||
if (_polygonPoints == nullptr)
|
||||
_polygonPoints = new std::vector<Vec2>();
|
||||
else
|
||||
_polygonPoints->clear();
|
||||
|
||||
float radius = MIN(getWidth(), getHeight()) * 0.5f;
|
||||
float angle = MATH_DEG_TO_RAD(_startAngle);
|
||||
float deltaAngle = 2 * M_PI / _sides;
|
||||
float dist;
|
||||
for (int i = 0; i < _sides; i++)
|
||||
{
|
||||
if (_distances != nullptr && i < (int)_distances->size())
|
||||
dist = (*_distances)[i];
|
||||
else
|
||||
dist = 1;
|
||||
|
||||
float xv = radius + radius * dist * cos(angle);
|
||||
float yv = h - (radius + radius * dist * sin(angle));
|
||||
_polygonPoints->push_back(Vec2(xv, yv));
|
||||
|
||||
angle += deltaAngle;
|
||||
}
|
||||
|
||||
_shape->drawPolygon(_polygonPoints->data(), (int)_polygonPoints->size(), _fillColor, _lineSize * 0.5f, _lineColor);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cocos2d::Color3B GGraph::getColor() const
|
||||
{
|
||||
return (Color3B)_fillColor;
|
||||
}
|
||||
|
||||
void GGraph::setColor(const cocos2d::Color3B& value)
|
||||
{
|
||||
_fillColor = Color4F(value, _fillColor.a);
|
||||
updateShape();
|
||||
}
|
||||
|
||||
cocos2d::Value GGraph::getProp(ObjectPropID propId)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
return Value(ToolSet::colorToInt(getColor()));
|
||||
default:
|
||||
return GObject::getProp(propId);
|
||||
}
|
||||
}
|
||||
|
||||
void GGraph::setProp(ObjectPropID propId, const cocos2d::Value& value)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
setColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
default:
|
||||
GObject::setProp(propId, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GGraph::handleSizeChanged()
|
||||
{
|
||||
GObject::handleSizeChanged();
|
||||
|
||||
if (_type == 3 || _type == 4)
|
||||
{
|
||||
float h = getHeight();
|
||||
int count = (int)_polygonPoints->size();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Vec2 pt = (*_polygonPoints)[i];
|
||||
pt.y = h - (_polygonPointOffset - pt.y);
|
||||
(*_polygonPoints)[i] = pt;
|
||||
}
|
||||
_polygonPointOffset = h;
|
||||
}
|
||||
|
||||
updateShape();
|
||||
}
|
||||
|
||||
void GGraph::setup_beforeAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GObject::setup_beforeAdd(buffer, beginPos);
|
||||
|
||||
buffer->seek(beginPos, 5);
|
||||
|
||||
_type = buffer->readByte();
|
||||
if (_type != 0)
|
||||
{
|
||||
_lineSize = buffer->readInt();
|
||||
_lineColor = (Color4F)buffer->readColor();
|
||||
_fillColor = (Color4F)buffer->readColor();
|
||||
if (buffer->readBool())
|
||||
{
|
||||
_cornerRadius = new float[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
_cornerRadius[i] = buffer->readFloat();
|
||||
}
|
||||
|
||||
if (_type == 3)
|
||||
{
|
||||
int cnt = buffer->readShort() / 2;
|
||||
_polygonPoints = new std::vector<Vec2>(cnt);
|
||||
float h = getHeight();
|
||||
_polygonPointOffset = h;
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
float f1 = buffer->readFloat();
|
||||
float f2 = h - buffer->readFloat();
|
||||
(*_polygonPoints)[i] = Vec2(f1, f2);
|
||||
}
|
||||
}
|
||||
else if (_type == 4)
|
||||
{
|
||||
_sides = buffer->readShort();
|
||||
_startAngle = buffer->readFloat();
|
||||
int cnt = buffer->readShort();
|
||||
if (cnt > 0)
|
||||
{
|
||||
_distances = new std::vector<float>(cnt);
|
||||
for (int i = 0; i < cnt; i++)
|
||||
(*_distances)[i] = buffer->readFloat();
|
||||
}
|
||||
}
|
||||
|
||||
updateShape();
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef __GGRAPH_H__
|
||||
#define __GGRAPH_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GObject.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GGraph : public GObject
|
||||
{
|
||||
public:
|
||||
GGraph();
|
||||
virtual ~GGraph();
|
||||
|
||||
CREATE_FUNC(GGraph);
|
||||
|
||||
void drawRect(float aWidth, float aHeight, int lineSize, const cocos2d::Color4F& lineColor, const cocos2d::Color4F& fillColor);
|
||||
void drawEllipse(float aWidth, float aHeight, int lineSize, const cocos2d::Color4F& lineColor, const cocos2d::Color4F& fillColor);
|
||||
void drawPolygon(int lineSize, const cocos2d::Color4F& lineColor, const cocos2d::Color4F& fillColor, const cocos2d::Vec2* points, int count);
|
||||
void drawRegularPolygon(int lineSize, const cocos2d::Color4F& lineColor, const cocos2d::Color4F& fillColor, int sides, float startAngle = 0, const float* distances = nullptr, int distanceCount = 0);
|
||||
bool isEmpty() const { return _type == 0; }
|
||||
|
||||
cocos2d::Color3B getColor() const;
|
||||
void setColor(const cocos2d::Color3B& value);
|
||||
|
||||
virtual cocos2d::Value getProp(ObjectPropID propId) override;
|
||||
virtual void setProp(ObjectPropID propId, const cocos2d::Value& value) override;
|
||||
|
||||
protected:
|
||||
virtual void handleInit() override;
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual void handleSizeChanged() override;
|
||||
|
||||
private:
|
||||
void updateShape();
|
||||
|
||||
int _type;
|
||||
cocos2d::Color4F _lineColor;
|
||||
cocos2d::Color4F _fillColor;
|
||||
int _lineSize;
|
||||
float* _cornerRadius;
|
||||
std::vector<cocos2d::Vec2>* _polygonPoints;
|
||||
float _polygonPointOffset;
|
||||
int _sides;
|
||||
float _startAngle;
|
||||
std::vector<float>* _distances;
|
||||
|
||||
cocos2d::DrawNode* _shape;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,467 @@
|
|||
#include "GGroup.h"
|
||||
#include "GComponent.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GGroup::GGroup() : _layout(GroupLayoutType::NONE),
|
||||
_lineGap(0),
|
||||
_columnGap(0),
|
||||
_excludeInvisibles(false),
|
||||
_autoSizeDisabled(false),
|
||||
_mainGridIndex(-1),
|
||||
_mainGridMinSize(10),
|
||||
_mainChildIndex(-1),
|
||||
_totalSize(0),
|
||||
_numChildren(0),
|
||||
_percentReady(false),
|
||||
_boundsChanged(false),
|
||||
_updating(false)
|
||||
{
|
||||
_touchDisabled = true;
|
||||
}
|
||||
|
||||
GGroup::~GGroup()
|
||||
{
|
||||
CALL_LATER_CANCEL(GGroup, ensureBoundsCorrect);
|
||||
}
|
||||
|
||||
void GGroup::setLayout(GroupLayoutType value)
|
||||
{
|
||||
if (_layout != value)
|
||||
{
|
||||
_layout = value;
|
||||
setBoundsChangedFlag(true);
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::setColumnGap(int value)
|
||||
{
|
||||
if (_columnGap != value)
|
||||
{
|
||||
_columnGap = value;
|
||||
setBoundsChangedFlag();
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::setLineGap(int value)
|
||||
{
|
||||
if (_lineGap != value)
|
||||
{
|
||||
_lineGap = value;
|
||||
setBoundsChangedFlag();
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::setExcludeInvisibles(bool value)
|
||||
{
|
||||
if (_excludeInvisibles != value)
|
||||
{
|
||||
_excludeInvisibles = value;
|
||||
setBoundsChangedFlag();
|
||||
}
|
||||
}
|
||||
void GGroup::setAutoSizeDisabled(bool value)
|
||||
{
|
||||
if (_autoSizeDisabled != value)
|
||||
{
|
||||
_autoSizeDisabled = value;
|
||||
setBoundsChangedFlag();
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::setMainGridIndex(int value)
|
||||
{
|
||||
if (_mainGridIndex != value)
|
||||
{
|
||||
_mainGridIndex = value;
|
||||
setBoundsChangedFlag();
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::setMainGridMinSize(int value)
|
||||
{
|
||||
if (_mainGridMinSize != value)
|
||||
{
|
||||
_mainGridMinSize = value;
|
||||
setBoundsChangedFlag();
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::setBoundsChangedFlag(bool positionChangedOnly)
|
||||
{
|
||||
if (_updating == 0 && _parent != nullptr)
|
||||
{
|
||||
if (!positionChangedOnly)
|
||||
_percentReady = false;
|
||||
|
||||
if (!_boundsChanged)
|
||||
{
|
||||
_boundsChanged = true;
|
||||
|
||||
if (_layout != GroupLayoutType::NONE)
|
||||
CALL_LATER(GGroup, ensureBoundsCorrect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::ensureBoundsCorrect()
|
||||
{
|
||||
if (_parent == nullptr || !_boundsChanged)
|
||||
return;
|
||||
|
||||
CALL_LATER_CANCEL(GGroup, ensureBoundsCorrect);
|
||||
_boundsChanged = false;
|
||||
|
||||
if (_autoSizeDisabled)
|
||||
resizeChildren(0, 0);
|
||||
else
|
||||
{
|
||||
handleLayout();
|
||||
updateBounds();
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::updateBounds()
|
||||
{
|
||||
int cnt = _parent->numChildren();
|
||||
int i;
|
||||
GObject* child;
|
||||
float ax = FLT_MAX, ay = FLT_MAX;
|
||||
float ar = FLT_MIN, ab = FLT_MIN;
|
||||
float tmp;
|
||||
bool empty = true;
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
child = _parent->getChildAt(i);
|
||||
if (child->_group != this || (_excludeInvisibles && !child->internalVisible3()))
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
empty = false;
|
||||
}
|
||||
|
||||
float w;
|
||||
float h;
|
||||
if (!empty)
|
||||
{
|
||||
_updating |= 1;
|
||||
setPosition(ax, ay);
|
||||
_updating &= 2;
|
||||
|
||||
w = ar - ax;
|
||||
h = ab - ay;
|
||||
}
|
||||
else
|
||||
w = h = 0;
|
||||
|
||||
if ((_updating & 2) == 0)
|
||||
{
|
||||
_updating |= 2;
|
||||
setSize(w, h);
|
||||
_updating &= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_updating &= 1;
|
||||
resizeChildren(getWidth() - w, getHeight() - h);
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::handleLayout()
|
||||
{
|
||||
_updating |= 1;
|
||||
|
||||
if (_layout == GroupLayoutType::HORIZONTAL)
|
||||
{
|
||||
float curX = getX();
|
||||
int cnt = _parent->numChildren();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(i);
|
||||
if (child->_group != this)
|
||||
continue;
|
||||
if (_excludeInvisibles && !child->internalVisible3())
|
||||
continue;
|
||||
|
||||
child->setXMin(curX);
|
||||
if (child->getWidth() != 0)
|
||||
curX += child->getWidth() + _columnGap;
|
||||
}
|
||||
}
|
||||
else if (_layout == GroupLayoutType::VERTICAL)
|
||||
{
|
||||
float curY = getY();
|
||||
int cnt = _parent->numChildren();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(i);
|
||||
if (child->_group != this)
|
||||
continue;
|
||||
if (_excludeInvisibles && !child->internalVisible3())
|
||||
continue;
|
||||
|
||||
child->setYMin(curY);
|
||||
if (child->getHeight() != 0)
|
||||
curY += child->getHeight() + _lineGap;
|
||||
}
|
||||
}
|
||||
|
||||
_updating &= 2;
|
||||
}
|
||||
|
||||
void GGroup::moveChildren(float dx, float dy)
|
||||
{
|
||||
if ((_updating & 1) != 0 || _parent == nullptr)
|
||||
return;
|
||||
|
||||
_updating |= 1;
|
||||
|
||||
int cnt = _parent->numChildren();
|
||||
int i;
|
||||
GObject* child;
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
child = _parent->getChildAt(i);
|
||||
if (child->_group == this)
|
||||
{
|
||||
child->setPosition(child->getX() + dx, child->getY() + dy);
|
||||
}
|
||||
}
|
||||
|
||||
_updating &= 2;
|
||||
}
|
||||
|
||||
void GGroup::resizeChildren(float dw, float dh)
|
||||
{
|
||||
if (_layout == GroupLayoutType::NONE || (_updating & 2) != 0 || _parent == nullptr)
|
||||
return;
|
||||
|
||||
_updating |= 2;
|
||||
|
||||
if (_boundsChanged)
|
||||
{
|
||||
_boundsChanged = false;
|
||||
if (!_autoSizeDisabled)
|
||||
{
|
||||
updateBounds();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int cnt = _parent->numChildren();
|
||||
|
||||
if (!_percentReady)
|
||||
{
|
||||
_percentReady = true;
|
||||
_numChildren = 0;
|
||||
_totalSize = 0;
|
||||
_mainChildIndex = -1;
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(i);
|
||||
if (child->_group != this)
|
||||
continue;
|
||||
|
||||
if (!_excludeInvisibles || child->internalVisible3())
|
||||
{
|
||||
if (j == _mainGridIndex)
|
||||
_mainChildIndex = i;
|
||||
|
||||
_numChildren++;
|
||||
|
||||
if (_layout == GroupLayoutType::HORIZONTAL)
|
||||
_totalSize += child->getWidth();
|
||||
else
|
||||
_totalSize += child->getHeight();
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
if (_mainChildIndex != -1)
|
||||
{
|
||||
if (_layout == GroupLayoutType::HORIZONTAL)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(_mainChildIndex);
|
||||
_totalSize += _mainGridMinSize - child->getWidth();
|
||||
child->_sizePercentInGroup = _mainGridMinSize / _totalSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
GObject* child = _parent->getChildAt(_mainChildIndex);
|
||||
_totalSize += _mainGridMinSize - child->getHeight();
|
||||
child->_sizePercentInGroup = _mainGridMinSize / _totalSize;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(i);
|
||||
if (child->_group != this)
|
||||
continue;
|
||||
|
||||
if (i == _mainChildIndex)
|
||||
continue;
|
||||
|
||||
if (_totalSize > 0)
|
||||
child->_sizePercentInGroup = (_layout == GroupLayoutType::HORIZONTAL ? child->getWidth() : child->getHeight()) / _totalSize;
|
||||
else
|
||||
child->_sizePercentInGroup = 0;
|
||||
}
|
||||
}
|
||||
|
||||
float remainSize = 0;
|
||||
float remainPercent = 1;
|
||||
bool priorHandled = false;
|
||||
|
||||
if (_layout == GroupLayoutType::HORIZONTAL)
|
||||
{
|
||||
remainSize = getWidth() - (_numChildren - 1) * _columnGap;
|
||||
if (_mainChildIndex != -1 && remainSize >= _totalSize)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(_mainChildIndex);
|
||||
child->setSize(remainSize - (_totalSize - _mainGridMinSize), child->_rawSize.height + dh, true);
|
||||
remainSize -= child->getWidth();
|
||||
remainPercent -= child->_sizePercentInGroup;
|
||||
priorHandled = true;
|
||||
}
|
||||
|
||||
float curX = getX();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(i);
|
||||
if (child->_group != this)
|
||||
continue;
|
||||
|
||||
if (_excludeInvisibles && !child->internalVisible3())
|
||||
{
|
||||
child->setSize(child->_rawSize.width, child->_rawSize.height + dh, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!priorHandled || i != _mainChildIndex)
|
||||
{
|
||||
child->setSize(round(child->_sizePercentInGroup / remainPercent * remainSize), child->_rawSize.height + dh, true);
|
||||
remainPercent -= child->_sizePercentInGroup;
|
||||
remainSize -= child->getWidth();
|
||||
}
|
||||
|
||||
child->setXMin(curX);
|
||||
if (child->getWidth() != 0)
|
||||
curX += child->getWidth() + _columnGap;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
remainSize = getHeight() - (_numChildren - 1) * _lineGap;
|
||||
if (_mainChildIndex != -1 && remainSize >= _totalSize)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(_mainChildIndex);
|
||||
child->setSize(child->_rawSize.width + dw, remainSize - (_totalSize - _mainGridMinSize), true);
|
||||
remainSize -= child->getHeight();
|
||||
remainPercent -= child->_sizePercentInGroup;
|
||||
priorHandled = true;
|
||||
}
|
||||
|
||||
float curY = getY();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(i);
|
||||
if (child->_group != this)
|
||||
continue;
|
||||
|
||||
if (_excludeInvisibles && !child->internalVisible3())
|
||||
{
|
||||
child->setSize(child->_rawSize.width + dw, child->_rawSize.height, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!priorHandled || i != _mainChildIndex)
|
||||
{
|
||||
child->setSize(child->_rawSize.width + dw, round(child->_sizePercentInGroup / remainPercent * remainSize), true);
|
||||
remainPercent -= child->_sizePercentInGroup;
|
||||
remainSize -= child->getHeight();
|
||||
}
|
||||
|
||||
child->setYMin(curY);
|
||||
if (child->getHeight() != 0)
|
||||
curY += child->getHeight() + _lineGap;
|
||||
}
|
||||
}
|
||||
|
||||
_updating &= 1;
|
||||
}
|
||||
|
||||
void GGroup::handleAlphaChanged()
|
||||
{
|
||||
GObject::handleAlphaChanged();
|
||||
|
||||
if (_underConstruct)
|
||||
return;
|
||||
|
||||
int cnt = _parent->numChildren();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(i);
|
||||
if (child->_group == this)
|
||||
child->setAlpha(_alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::handleVisibleChanged()
|
||||
{
|
||||
if (!_parent)
|
||||
return;
|
||||
|
||||
int cnt = _parent->numChildren();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* child = _parent->getChildAt(i);
|
||||
if (child->_group == this)
|
||||
child->handleVisibleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::setup_beforeAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GObject::setup_beforeAdd(buffer, beginPos);
|
||||
|
||||
buffer->seek(beginPos, 5);
|
||||
|
||||
_layout = (GroupLayoutType)buffer->readByte();
|
||||
_lineGap = buffer->readInt();
|
||||
_columnGap = buffer->readInt();
|
||||
if (buffer->version >= 2)
|
||||
{
|
||||
_excludeInvisibles = buffer->readBool();
|
||||
_autoSizeDisabled = buffer->readBool();
|
||||
_mainChildIndex = buffer->readShort();
|
||||
}
|
||||
}
|
||||
|
||||
void GGroup::setup_afterAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GObject::setup_afterAdd(buffer, beginPos);
|
||||
|
||||
if (!_visible)
|
||||
handleVisibleChanged();
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef __GGROUP_H__
|
||||
#define __GGROUP_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GObject.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GGroup : public GObject
|
||||
{
|
||||
public:
|
||||
GGroup();
|
||||
virtual ~GGroup();
|
||||
|
||||
CREATE_FUNC(GGroup);
|
||||
|
||||
GroupLayoutType getLayout() { return _layout; }
|
||||
void setLayout(GroupLayoutType value);
|
||||
|
||||
int getColumnGap() { return _columnGap; }
|
||||
void setColumnGap(int value);
|
||||
|
||||
int getLineGap() { return _lineGap; }
|
||||
void setLineGap(int value);
|
||||
|
||||
bool isExcludeInvisibles() { return _excludeInvisibles; }
|
||||
void setExcludeInvisibles(bool value);
|
||||
|
||||
bool isAutoSizeDisabled() { return _autoSizeDisabled; }
|
||||
void setAutoSizeDisabled(bool value);
|
||||
|
||||
int getMainGridIndex() { return _mainGridIndex; }
|
||||
void setMainGridIndex(int value);
|
||||
|
||||
int getMainGridMinSize() { return _mainGridMinSize; }
|
||||
void setMainGridMinSize(int value);
|
||||
|
||||
void setBoundsChangedFlag(bool positionChangedOnly = false);
|
||||
void moveChildren(float dx, float dy);
|
||||
void resizeChildren(float dw, float dh);
|
||||
|
||||
int _updating;
|
||||
|
||||
protected:
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual void setup_afterAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual void handleAlphaChanged() override;
|
||||
virtual void handleVisibleChanged() override;
|
||||
|
||||
private:
|
||||
void updateBounds();
|
||||
void handleLayout();
|
||||
CALL_LATER_FUNC(GGroup, ensureBoundsCorrect);
|
||||
|
||||
GroupLayoutType _layout;
|
||||
int _lineGap;
|
||||
int _columnGap;
|
||||
bool _excludeInvisibles;
|
||||
bool _autoSizeDisabled;
|
||||
int _mainGridIndex;
|
||||
int _mainGridMinSize;
|
||||
|
||||
bool _percentReady;
|
||||
bool _boundsChanged;
|
||||
int _mainChildIndex;
|
||||
float _totalSize;
|
||||
int _numChildren;
|
||||
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,164 @@
|
|||
#include "GImage.h"
|
||||
#include "PackageItem.h"
|
||||
#include "display/FUISprite.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GImage::GImage() : _content(nullptr)
|
||||
{
|
||||
_touchDisabled = true;
|
||||
}
|
||||
|
||||
GImage::~GImage()
|
||||
{
|
||||
}
|
||||
|
||||
void GImage::handleInit()
|
||||
{
|
||||
_content = FUISprite::create();
|
||||
_content->retain();
|
||||
|
||||
_displayObject = _content;
|
||||
}
|
||||
|
||||
FlipType GImage::getFlip() const
|
||||
{
|
||||
if (_content->isFlippedX() && _content->isFlippedY())
|
||||
return FlipType::BOTH;
|
||||
else if (_content->isFlippedX())
|
||||
return FlipType::HORIZONTAL;
|
||||
else if (_content->isFlippedY())
|
||||
return FlipType::VERTICAL;
|
||||
else
|
||||
return FlipType::NONE;
|
||||
}
|
||||
|
||||
void GImage::setFlip(FlipType value)
|
||||
{
|
||||
_content->setFlippedX(value == FlipType::HORIZONTAL || value == FlipType::BOTH);
|
||||
_content->setFlippedY(value == FlipType::VERTICAL || value == FlipType::BOTH);
|
||||
}
|
||||
|
||||
void GImage::handleGrayedChanged()
|
||||
{
|
||||
GObject::handleGrayedChanged();
|
||||
|
||||
((FUISprite*)_content)->setGrayed(_finalGrayed);
|
||||
}
|
||||
|
||||
cocos2d::Color3B GImage::getColor() const
|
||||
{
|
||||
return _content->getColor();
|
||||
}
|
||||
|
||||
void GImage::setColor(const cocos2d::Color3B& value)
|
||||
{
|
||||
_content->setColor(value);
|
||||
}
|
||||
|
||||
FillMethod GImage::getFillMethod() const
|
||||
{
|
||||
return _content->getFillMethod();
|
||||
}
|
||||
|
||||
void GImage::setFillMethod(FillMethod value)
|
||||
{
|
||||
_content->setFillMethod(value);
|
||||
}
|
||||
|
||||
FillOrigin GImage::getFillOrigin() const
|
||||
{
|
||||
return _content->getFillOrigin();
|
||||
}
|
||||
|
||||
void GImage::setFillOrigin(FillOrigin value)
|
||||
{
|
||||
_content->setFillOrigin(value);
|
||||
}
|
||||
|
||||
bool GImage::isFillClockwise() const
|
||||
{
|
||||
return _content->isFillClockwise();
|
||||
}
|
||||
|
||||
void GImage::setFillClockwise(bool value)
|
||||
{
|
||||
_content->setFillClockwise(value);
|
||||
}
|
||||
|
||||
float GImage::getFillAmount() const
|
||||
{
|
||||
return _content->getFillAmount();
|
||||
}
|
||||
|
||||
void GImage::setFillAmount(float value)
|
||||
{
|
||||
_content->setFillAmount(value);
|
||||
}
|
||||
|
||||
cocos2d::Value GImage::getProp(ObjectPropID propId)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
return Value(ToolSet::colorToInt(getColor()));
|
||||
default:
|
||||
return GObject::getProp(propId);
|
||||
}
|
||||
}
|
||||
|
||||
void GImage::setProp(ObjectPropID propId, const cocos2d::Value& value)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
setColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
default:
|
||||
GObject::setProp(propId, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GImage::constructFromResource()
|
||||
{
|
||||
PackageItem* contentItem = _packageItem->getBranch();
|
||||
sourceSize.width = contentItem->width;
|
||||
sourceSize.height = contentItem->height;
|
||||
initSize = sourceSize;
|
||||
|
||||
contentItem = contentItem->getHighResolution();
|
||||
contentItem->load();
|
||||
|
||||
_content->setSpriteFrame(contentItem->spriteFrame);
|
||||
if (contentItem->scale9Grid)
|
||||
((FUISprite*)_content)->setScale9Grid(contentItem->scale9Grid);
|
||||
else if (contentItem->scaleByTile)
|
||||
((FUISprite*)_content)->setScaleByTile(true);
|
||||
|
||||
setSize(sourceSize.width, sourceSize.height);
|
||||
}
|
||||
|
||||
void GImage::setup_beforeAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GObject::setup_beforeAdd(buffer, beginPos);
|
||||
|
||||
buffer->seek(beginPos, 5);
|
||||
|
||||
if (buffer->readBool())
|
||||
setColor((Color3B)buffer->readColor());
|
||||
setFlip((FlipType)buffer->readByte());
|
||||
int fillMethod = buffer->readByte();
|
||||
if (fillMethod != 0)
|
||||
{
|
||||
_content->setFillMethod((FillMethod)fillMethod);
|
||||
_content->setFillOrigin((FillOrigin)buffer->readByte());
|
||||
_content->setFillClockwise(buffer->readBool());
|
||||
_content->setFillAmount(buffer->readFloat());
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef __GIMAGE_H__
|
||||
#define __GIMAGE_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GObject.h"
|
||||
#include "cocos2d.h"
|
||||
#include "ui/UIScale9Sprite.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class FUISprite;
|
||||
|
||||
class GImage : public GObject
|
||||
{
|
||||
public:
|
||||
GImage();
|
||||
virtual ~GImage();
|
||||
|
||||
CREATE_FUNC(GImage);
|
||||
|
||||
FlipType getFlip() const;
|
||||
void setFlip(FlipType value);
|
||||
|
||||
cocos2d::Color3B getColor() const;
|
||||
void setColor(const cocos2d::Color3B& value);
|
||||
|
||||
FillMethod getFillMethod() const;
|
||||
void setFillMethod(FillMethod value);
|
||||
|
||||
FillOrigin getFillOrigin() const;
|
||||
void setFillOrigin(FillOrigin value);
|
||||
|
||||
bool isFillClockwise() const;
|
||||
void setFillClockwise(bool value);
|
||||
|
||||
float getFillAmount() const;
|
||||
void setFillAmount(float value);
|
||||
|
||||
virtual void constructFromResource() override;
|
||||
|
||||
virtual cocos2d::Value getProp(ObjectPropID propId) override;
|
||||
virtual void setProp(ObjectPropID propId, const cocos2d::Value& value) override;
|
||||
|
||||
protected:
|
||||
virtual void handleInit() override;
|
||||
virtual void handleGrayedChanged() override;
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
|
||||
private:
|
||||
FUISprite* _content;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,190 @@
|
|||
#include "GLabel.h"
|
||||
#include "GButton.h"
|
||||
#include "GTextField.h"
|
||||
#include "GTextInput.h"
|
||||
#include "PackageItem.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GLabel::GLabel() :
|
||||
_titleObject(nullptr),
|
||||
_iconObject(nullptr)
|
||||
{
|
||||
}
|
||||
GLabel::~GLabel()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& GLabel::getText() const
|
||||
{
|
||||
if (_titleObject != nullptr)
|
||||
return _titleObject->getText();
|
||||
else
|
||||
return STD_STRING_EMPTY;
|
||||
}
|
||||
|
||||
void GLabel::setText(const std::string & value)
|
||||
{
|
||||
if (_titleObject != nullptr)
|
||||
_titleObject->setText(value);
|
||||
updateGear(6);
|
||||
}
|
||||
|
||||
const std::string& GLabel::getIcon() const
|
||||
{
|
||||
if (_iconObject != nullptr)
|
||||
return _iconObject->getIcon();
|
||||
else
|
||||
return STD_STRING_EMPTY;
|
||||
}
|
||||
|
||||
void GLabel::setIcon(const std::string & value)
|
||||
{
|
||||
if (_iconObject != nullptr)
|
||||
_iconObject->setIcon(value);
|
||||
updateGear(7);
|
||||
}
|
||||
|
||||
cocos2d::Color3B GLabel::getTitleColor() const
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
return tf->getColor();
|
||||
else
|
||||
return Color3B::BLACK;
|
||||
}
|
||||
|
||||
void GLabel::setTitleColor(const cocos2d::Color3B & value)
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
tf->setColor(value);
|
||||
}
|
||||
|
||||
int GLabel::getTitleFontSize() const
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
return tf->getFontSize();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GLabel::setTitleFontSize(int value)
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf)
|
||||
tf->setFontSize(value);
|
||||
}
|
||||
|
||||
GTextField * GLabel::getTextField() const
|
||||
{
|
||||
if (dynamic_cast<GTextField*>(_titleObject))
|
||||
return dynamic_cast<GTextField*>(_titleObject);
|
||||
else if (dynamic_cast<GLabel*>(_titleObject))
|
||||
return dynamic_cast<GLabel*>(_titleObject)->getTextField();
|
||||
else if (dynamic_cast<GButton*>(_titleObject))
|
||||
return dynamic_cast<GButton*>(_titleObject)->getTextField();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cocos2d::Value GLabel::getProp(ObjectPropID propId)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
return Value(ToolSet::colorToInt(getTitleColor()));
|
||||
case ObjectPropID::OutlineColor:
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf != nullptr)
|
||||
return Value(ToolSet::colorToInt(tf->getOutlineColor()));
|
||||
else
|
||||
return Value::Null;
|
||||
}
|
||||
case ObjectPropID::FontSize:
|
||||
return Value(getTitleFontSize());
|
||||
default:
|
||||
return GComponent::getProp(propId);
|
||||
}
|
||||
}
|
||||
|
||||
void GLabel::setProp(ObjectPropID propId, const cocos2d::Value& value)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
setTitleColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
case ObjectPropID::OutlineColor:
|
||||
{
|
||||
GTextField* tf = getTextField();
|
||||
if (tf != nullptr)
|
||||
tf->setOutlineColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
}
|
||||
case ObjectPropID::FontSize:
|
||||
setTitleFontSize(value.asInt());
|
||||
break;
|
||||
default:
|
||||
GComponent::setProp(propId, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GLabel::constructExtension(ByteBuffer* buffer)
|
||||
{
|
||||
_titleObject = getChild("title");
|
||||
_iconObject = getChild("icon");
|
||||
}
|
||||
|
||||
void GLabel::setup_afterAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GComponent::setup_afterAdd(buffer, beginPos);
|
||||
|
||||
if (!buffer->seek(beginPos, 6))
|
||||
return;
|
||||
|
||||
if ((ObjectType)buffer->readByte() != _packageItem->objectType)
|
||||
return;
|
||||
|
||||
const std::string* str;
|
||||
|
||||
if ((str = buffer->readSP()))
|
||||
setTitle(*str);
|
||||
if ((str = buffer->readSP()))
|
||||
setIcon(*str);
|
||||
if (buffer->readBool())
|
||||
setTitleColor((Color3B)buffer->readColor());
|
||||
int iv = buffer->readInt();
|
||||
if (iv != 0)
|
||||
setTitleFontSize(iv);
|
||||
|
||||
if (buffer->readBool())
|
||||
{
|
||||
GTextInput* input = dynamic_cast<GTextInput*>(getTextField());
|
||||
if (input)
|
||||
{
|
||||
if ((str = buffer->readSP()))
|
||||
input->setPrompt(*str);
|
||||
if ((str = buffer->readSP()))
|
||||
input->setRestrict(*str);
|
||||
iv = buffer->readInt();
|
||||
if (iv != 0)
|
||||
input->setMaxLength(iv);
|
||||
iv = buffer->readInt();
|
||||
if (iv != 0)
|
||||
input->setKeyboardType(iv);
|
||||
if (buffer->readBool())
|
||||
input->setPassword(true);
|
||||
}
|
||||
else
|
||||
buffer->skip(13);
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef __GLABEL_H__
|
||||
#define __GLABEL_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GComponent.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GTextField;
|
||||
|
||||
class GLabel : public GComponent
|
||||
{
|
||||
public:
|
||||
GLabel();
|
||||
virtual ~GLabel();
|
||||
|
||||
CREATE_FUNC(GLabel);
|
||||
|
||||
const std::string& getTitle() { return getText(); }
|
||||
void setTitle(const std::string& value) { setText(value); };
|
||||
|
||||
virtual const std::string& getText() const override;
|
||||
virtual void setText(const std::string& value) override;
|
||||
|
||||
virtual const std::string& getIcon() const override;
|
||||
virtual void setIcon(const std::string& value) override;
|
||||
|
||||
cocos2d::Color3B getTitleColor() const;
|
||||
void setTitleColor(const cocos2d::Color3B& value);
|
||||
|
||||
int getTitleFontSize() const;
|
||||
void setTitleFontSize(int value);
|
||||
|
||||
GTextField* getTextField() const;
|
||||
|
||||
virtual cocos2d::Value getProp(ObjectPropID propId) override;
|
||||
virtual void setProp(ObjectPropID propId, const cocos2d::Value& value) override;
|
||||
|
||||
protected:
|
||||
virtual void constructExtension(ByteBuffer* buffer) override;
|
||||
virtual void setup_afterAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
|
||||
private:
|
||||
GObject* _titleObject;
|
||||
GObject* _iconObject;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,190 @@
|
|||
#ifndef __GLIST_H__
|
||||
#define __GLIST_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GComponent.h"
|
||||
#include "GObjectPool.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GList : public GComponent
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(int, GObject*)> ListItemRenderer;
|
||||
typedef std::function<std::string(int)> ListItemProvider;
|
||||
|
||||
GList();
|
||||
virtual ~GList();
|
||||
|
||||
CREATE_FUNC(GList);
|
||||
|
||||
const std::string& getDefaultItem() const { return _defaultItem; }
|
||||
void setDefaultItem(const std::string& value) { _defaultItem = value; }
|
||||
|
||||
ListLayoutType getLayout() const { return _layout; }
|
||||
void setLayout(ListLayoutType value);
|
||||
|
||||
int getLineCount() const { return _lineCount; }
|
||||
void setLineCount(int value);
|
||||
|
||||
int getColumnCount() { return _columnCount; }
|
||||
void setColumnCount(int value);
|
||||
|
||||
int getColumnGap() const { return _columnGap; }
|
||||
void setColumnGap(int value);
|
||||
|
||||
int getLineGap() const { return _lineGap; }
|
||||
void setLineGap(int value);
|
||||
|
||||
cocos2d::TextHAlignment getAlign() const { return _align; }
|
||||
void setAlign(cocos2d::TextHAlignment value);
|
||||
|
||||
cocos2d::TextVAlignment getVerticalAlign() const { return _verticalAlign; }
|
||||
void setVerticalAlign(cocos2d::TextVAlignment value);
|
||||
|
||||
bool getAutoResizeItem() const { return _autoResizeItem; }
|
||||
void setAutoResizeItem(bool value);
|
||||
|
||||
ListSelectionMode getSelectionMode() const { return _selectionMode; }
|
||||
void setSelectionMode(ListSelectionMode value) { _selectionMode = value; }
|
||||
|
||||
GObjectPool* getItemPool() const { return _pool; }
|
||||
GObject* getFromPool() { return getFromPool(cocos2d::STD_STRING_EMPTY); }
|
||||
GObject* getFromPool(const std::string& url);
|
||||
void returnToPool(GObject* obj);
|
||||
GObject* addItemFromPool() { return addItemFromPool(cocos2d::STD_STRING_EMPTY); }
|
||||
GObject* addItemFromPool(const std::string& url);
|
||||
|
||||
GObject* addChildAt(GObject* child, int index) override;
|
||||
void removeChildAt(int index) override;
|
||||
void removeChildToPoolAt(int index);
|
||||
void removeChildToPool(GObject* child);
|
||||
void removeChildrenToPool();
|
||||
void removeChildrenToPool(int beginIndex, int endIndex);
|
||||
|
||||
int getSelectedIndex() const;
|
||||
void setSelectedIndex(int value);
|
||||
|
||||
void getSelection(std::vector<int>& result) const;
|
||||
void addSelection(int index, bool scrollItToView);
|
||||
void removeSelection(int index);
|
||||
void clearSelection();
|
||||
void selectAll();
|
||||
void selectReverse();
|
||||
|
||||
void handleArrowKey(int dir);
|
||||
|
||||
void resizeToFit(int itemCount) { resizeToFit(itemCount, 0); }
|
||||
void resizeToFit(int itemCount, int minSize);
|
||||
|
||||
virtual int getFirstChildInView() override;
|
||||
|
||||
void scrollToView(int index, bool ani = false, bool setFirst = false);
|
||||
|
||||
GController* getSelectionController() const { return _selectionController; }
|
||||
void setSelectionController(GController* value);
|
||||
|
||||
void setVirtual();
|
||||
void setVirtualAndLoop();
|
||||
bool isVirtual() { return _virtual; }
|
||||
void refreshVirtualList();
|
||||
|
||||
int getNumItems();
|
||||
void setNumItems(int value);
|
||||
|
||||
int childIndexToItemIndex(int index);
|
||||
int itemIndexToChildIndex(int index);
|
||||
|
||||
virtual cocos2d::Vec2 getSnappingPosition(const cocos2d::Vec2& pt) override;
|
||||
|
||||
ListItemRenderer itemRenderer;
|
||||
ListItemProvider itemProvider;
|
||||
bool scrollItemToViewOnClick;
|
||||
bool foldInvisibleItems;
|
||||
|
||||
protected:
|
||||
virtual void handleControllerChanged(GController* c) override;
|
||||
virtual void handleSizeChanged() override;
|
||||
virtual void updateBounds() override;
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual void setup_afterAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
|
||||
virtual void dispatchItemEvent(GObject* item, EventContext* context);
|
||||
virtual void readItems(ByteBuffer* buffer);
|
||||
virtual void setupItem(ByteBuffer* buffer, GObject* obj);
|
||||
|
||||
private:
|
||||
void clearSelectionExcept(GObject* g);
|
||||
void setSelectionOnEvent(GObject* item, InputEvent* evt);
|
||||
|
||||
void onItemTouchBegin(EventContext* context);
|
||||
void onClickItem(EventContext* context);
|
||||
|
||||
void updateSelectionController(int index);
|
||||
|
||||
void setVirtual(bool loop);
|
||||
void checkVirtualList();
|
||||
void setVirtualListChangedFlag(bool layoutChanged);
|
||||
CALL_LATER_FUNC(GList, doRefreshVirtualList);
|
||||
|
||||
void onScroll(EventContext* context);
|
||||
|
||||
int getIndexOnPos1(float& pos, bool forceUpdate);
|
||||
int getIndexOnPos2(float& pos, bool forceUpdate);
|
||||
int getIndexOnPos3(float& pos, bool forceUpdate);
|
||||
|
||||
void handleScroll(bool forceUpdate);
|
||||
bool handleScroll1(bool forceUpdate);
|
||||
bool handleScroll2(bool forceUpdate);
|
||||
void handleScroll3(bool forceUpdate);
|
||||
|
||||
void handleArchOrder1();
|
||||
void handleArchOrder2();
|
||||
|
||||
void handleAlign(float contentWidth, float contentHeight);
|
||||
|
||||
ListLayoutType _layout;
|
||||
int _lineCount;
|
||||
int _columnCount;
|
||||
int _lineGap;
|
||||
int _columnGap;
|
||||
cocos2d::TextHAlignment _align;
|
||||
cocos2d::TextVAlignment _verticalAlign;
|
||||
bool _autoResizeItem;
|
||||
ListSelectionMode _selectionMode;
|
||||
std::string _defaultItem;
|
||||
GController* _selectionController;
|
||||
|
||||
GObjectPool* _pool;
|
||||
bool _selectionHandled;
|
||||
int _lastSelectedIndex;
|
||||
|
||||
//Virtual List support
|
||||
bool _virtual;
|
||||
bool _loop;
|
||||
int _numItems;
|
||||
int _realNumItems;
|
||||
int _firstIndex; //the top left index
|
||||
int _curLineItemCount; //item count in one line
|
||||
int _curLineItemCount2; //item count in vertical direction,only pagination layout
|
||||
cocos2d::Vec2 _itemSize;
|
||||
int _virtualListChanged; //1-content changed, 2-size changed
|
||||
bool _eventLocked;
|
||||
uint32_t _itemInfoVer;
|
||||
|
||||
struct ItemInfo
|
||||
{
|
||||
cocos2d::Vec2 size;
|
||||
GObject* obj;
|
||||
uint32_t updateFlag;
|
||||
bool selected;
|
||||
|
||||
ItemInfo();
|
||||
};
|
||||
std::vector<ItemInfo> _virtualItems;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,603 @@
|
|||
#include "GLoader.h"
|
||||
#include "GComponent.h"
|
||||
#include "GMovieClip.h"
|
||||
#include "UIPackage.h"
|
||||
#include "display/FUISprite.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GLoader::GLoader()
|
||||
: _autoSize(false),
|
||||
_align(TextHAlignment::LEFT),
|
||||
_verticalAlign(TextVAlignment::TOP),
|
||||
_fill(LoaderFillType::NONE),
|
||||
_shrinkOnly(false),
|
||||
_updatingLayout(false),
|
||||
_contentItem(nullptr),
|
||||
_contentStatus(0),
|
||||
_content(nullptr),
|
||||
_content2(nullptr),
|
||||
_playAction(nullptr),
|
||||
_playing(true),
|
||||
_frame(0)
|
||||
{
|
||||
}
|
||||
|
||||
GLoader::~GLoader()
|
||||
{
|
||||
CC_SAFE_RELEASE(_playAction);
|
||||
CC_SAFE_RELEASE(_content);
|
||||
CC_SAFE_RELEASE(_content2);
|
||||
}
|
||||
|
||||
void GLoader::handleInit()
|
||||
{
|
||||
_content = FUISprite::create();
|
||||
_content->retain();
|
||||
_content->setAnchorPoint(Vec2::ZERO);
|
||||
_content->setCascadeOpacityEnabled(true);
|
||||
|
||||
FUIContainer* c = FUIContainer::create();
|
||||
c->retain();
|
||||
c->gOwner = this;
|
||||
|
||||
_displayObject = c;
|
||||
_displayObject->addChild(_content);
|
||||
}
|
||||
|
||||
void GLoader::setURL(const std::string& value)
|
||||
{
|
||||
if (_url.compare(value) == 0)
|
||||
return;
|
||||
|
||||
_url = value;
|
||||
loadContent();
|
||||
updateGear(7);
|
||||
}
|
||||
|
||||
void GLoader::setAlign(cocos2d::TextHAlignment value)
|
||||
{
|
||||
if (_align != value)
|
||||
{
|
||||
_align = value;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader::setVerticalAlign(cocos2d::TextVAlignment value)
|
||||
{
|
||||
if (_verticalAlign != value)
|
||||
{
|
||||
_verticalAlign = value;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader::setAutoSize(bool value)
|
||||
{
|
||||
if (_autoSize != value)
|
||||
{
|
||||
_autoSize = value;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader::setFill(LoaderFillType value)
|
||||
{
|
||||
if (_fill != value)
|
||||
{
|
||||
_fill = value;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader::setShrinkOnly(bool value)
|
||||
{
|
||||
if (_shrinkOnly != value)
|
||||
{
|
||||
_shrinkOnly = value;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
const cocos2d::Size & GLoader::getContentSize()
|
||||
{
|
||||
return _content->getContentSize();
|
||||
}
|
||||
|
||||
cocos2d::Color3B GLoader::getColor() const
|
||||
{
|
||||
return _content->getColor();
|
||||
}
|
||||
|
||||
void GLoader::setColor(const cocos2d::Color3B& value)
|
||||
{
|
||||
_content->setColor(value);
|
||||
}
|
||||
|
||||
void GLoader::setPlaying(bool value)
|
||||
{
|
||||
if (_playing != value)
|
||||
{
|
||||
_playing = value;
|
||||
if (_playAction)
|
||||
{
|
||||
if (_playing)
|
||||
_content->runAction(_playAction);
|
||||
else
|
||||
_content->stopAction(_playAction);
|
||||
}
|
||||
updateGear(5);
|
||||
}
|
||||
}
|
||||
|
||||
int GLoader::getFrame() const
|
||||
{
|
||||
return _frame;
|
||||
}
|
||||
|
||||
void GLoader::setFrame(int value)
|
||||
{
|
||||
if (_frame != value)
|
||||
{
|
||||
_frame = value;
|
||||
if (_playAction)
|
||||
_playAction->setFrame(value);
|
||||
updateGear(5);
|
||||
}
|
||||
}
|
||||
|
||||
FillMethod GLoader::getFillMethod() const
|
||||
{
|
||||
return _content->getFillMethod();
|
||||
}
|
||||
|
||||
void GLoader::setFillMethod(FillMethod value)
|
||||
{
|
||||
_content->setFillMethod(value);
|
||||
}
|
||||
|
||||
FillOrigin GLoader::getFillOrigin() const
|
||||
{
|
||||
return _content->getFillOrigin();
|
||||
}
|
||||
|
||||
void GLoader::setFillOrigin(FillOrigin value)
|
||||
{
|
||||
_content->setFillOrigin(value);
|
||||
}
|
||||
|
||||
bool GLoader::isFillClockwise() const
|
||||
{
|
||||
return _content->isFillClockwise();
|
||||
}
|
||||
|
||||
void GLoader::setFillClockwise(bool value)
|
||||
{
|
||||
_content->setFillClockwise(value);
|
||||
}
|
||||
|
||||
float GLoader::getFillAmount() const
|
||||
{
|
||||
return _content->getFillAmount();
|
||||
}
|
||||
|
||||
void GLoader::setFillAmount(float value)
|
||||
{
|
||||
_content->setFillAmount(value);
|
||||
}
|
||||
|
||||
void GLoader::loadContent()
|
||||
{
|
||||
clearContent();
|
||||
|
||||
if (_url.length() == 0)
|
||||
return;
|
||||
|
||||
if (_url.compare(0, 5, "ui://") == 0)
|
||||
loadFromPackage();
|
||||
else
|
||||
{
|
||||
_contentStatus = 3;
|
||||
loadExternal();
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader::loadFromPackage()
|
||||
{
|
||||
_contentItem = UIPackage::getItemByURL(_url);
|
||||
|
||||
if (_contentItem != nullptr)
|
||||
{
|
||||
_contentItem = _contentItem->getBranch();
|
||||
sourceSize.width = _contentItem->width;
|
||||
sourceSize.height = _contentItem->height;
|
||||
_contentItem = _contentItem->getHighResolution();
|
||||
_contentItem->load();
|
||||
|
||||
if (_contentItem->type == PackageItemType::IMAGE)
|
||||
{
|
||||
_contentStatus = 1;
|
||||
_content->initWithSpriteFrame(_contentItem->spriteFrame);
|
||||
if (_contentItem->scale9Grid)
|
||||
((FUISprite*)_content)->setScale9Grid(_contentItem->scale9Grid);
|
||||
updateLayout();
|
||||
}
|
||||
else if (_contentItem->type == PackageItemType::MOVIECLIP)
|
||||
{
|
||||
_contentStatus = 2;
|
||||
if (_playAction == nullptr)
|
||||
{
|
||||
_playAction = ActionMovieClip::create(_contentItem->animation, _contentItem->repeatDelay);
|
||||
_playAction->retain();
|
||||
}
|
||||
else
|
||||
_playAction->setAnimation(_contentItem->animation, _contentItem->repeatDelay);
|
||||
if (_playing)
|
||||
_content->runAction(_playAction);
|
||||
else
|
||||
_playAction->setFrame(_frame);
|
||||
|
||||
updateLayout();
|
||||
}
|
||||
else if (_contentItem->type == PackageItemType::COMPONENT)
|
||||
{
|
||||
GObject* obj = UIPackage::createObjectFromURL(_url);
|
||||
if (obj == nullptr)
|
||||
setErrorState();
|
||||
else if (dynamic_cast<GComponent*>(obj) == nullptr)
|
||||
{
|
||||
setErrorState();
|
||||
}
|
||||
else
|
||||
{
|
||||
_content2 = obj->as<GComponent>();
|
||||
_content2->retain();
|
||||
_content2->addEventListener(UIEventType::SizeChange, [this](EventContext*) {
|
||||
if (!_updatingLayout)
|
||||
updateLayout();
|
||||
});
|
||||
_displayObject->addChild(_content2->displayObject());
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_autoSize)
|
||||
setSize(_contentItem->width, _contentItem->height);
|
||||
|
||||
setErrorState();
|
||||
}
|
||||
}
|
||||
else
|
||||
setErrorState();
|
||||
}
|
||||
|
||||
void GLoader::loadExternal()
|
||||
{
|
||||
auto tex = Director::getInstance()->getTextureCache()->addImage(_url);
|
||||
if (tex)
|
||||
{
|
||||
auto sf = SpriteFrame::createWithTexture(tex, Rect(Vec2::ZERO, tex->getContentSize()));
|
||||
onExternalLoadSuccess(sf);
|
||||
}
|
||||
else
|
||||
onExternalLoadFailed();
|
||||
}
|
||||
|
||||
void GLoader::freeExternal(cocos2d::SpriteFrame* spriteFrame)
|
||||
{
|
||||
}
|
||||
|
||||
void GLoader::onExternalLoadSuccess(cocos2d::SpriteFrame* spriteFrame)
|
||||
{
|
||||
_contentStatus = 4;
|
||||
_content->setSpriteFrame(spriteFrame);
|
||||
sourceSize = spriteFrame->getRectInPixels().size;
|
||||
updateLayout();
|
||||
}
|
||||
|
||||
void GLoader::onExternalLoadFailed()
|
||||
{
|
||||
setErrorState();
|
||||
}
|
||||
|
||||
void GLoader::clearContent()
|
||||
{
|
||||
clearErrorState();
|
||||
|
||||
if (_contentStatus == 4)
|
||||
freeExternal(_content->getSpriteFrame());
|
||||
|
||||
if (_contentStatus == 2)
|
||||
{
|
||||
_playAction->setAnimation(nullptr);
|
||||
_content->stopAction(_playAction);
|
||||
}
|
||||
|
||||
if (_content2 != nullptr)
|
||||
{
|
||||
_displayObject->removeChild(_content2->displayObject());
|
||||
CC_SAFE_RELEASE(_content2);
|
||||
}
|
||||
((FUISprite*)_content)->clearContent();
|
||||
|
||||
_contentItem = nullptr;
|
||||
_contentStatus = 0;
|
||||
}
|
||||
|
||||
void GLoader::updateLayout()
|
||||
{
|
||||
if (_content2 == nullptr && _contentStatus == 0)
|
||||
{
|
||||
if (_autoSize)
|
||||
{
|
||||
_updatingLayout = true;
|
||||
setSize(50, 30);
|
||||
_updatingLayout = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Size contentSize = sourceSize;
|
||||
|
||||
if (_autoSize)
|
||||
{
|
||||
_updatingLayout = true;
|
||||
if (contentSize.width == 0)
|
||||
contentSize.width = 50;
|
||||
if (contentSize.height == 0)
|
||||
contentSize.height = 30;
|
||||
setSize(contentSize.width, contentSize.height);
|
||||
_updatingLayout = false;
|
||||
|
||||
if (_size.equals(contentSize))
|
||||
{
|
||||
if (_content2 != nullptr)
|
||||
{
|
||||
_content2->setScale(1, 1);
|
||||
_content2->setPosition(0, -_size.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
_content->setScale(1, 1);
|
||||
_content->setAnchorPoint(Vec2::ZERO);
|
||||
_content->setPosition(0, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float sx = 1, sy = 1;
|
||||
if (_fill != LoaderFillType::NONE)
|
||||
{
|
||||
sx = _size.width / sourceSize.width;
|
||||
sy = _size.height / sourceSize.height;
|
||||
|
||||
if (sx != 1 || sy != 1)
|
||||
{
|
||||
if (_fill == LoaderFillType::SCALE_MATCH_HEIGHT)
|
||||
sx = sy;
|
||||
else if (_fill == LoaderFillType::SCALE_MATCH_WIDTH)
|
||||
sy = sx;
|
||||
else if (_fill == LoaderFillType::SCALE)
|
||||
{
|
||||
if (sx > sy)
|
||||
sx = sy;
|
||||
else
|
||||
sy = sx;
|
||||
}
|
||||
else if (_fill == LoaderFillType::SCALE_NO_BORDER)
|
||||
{
|
||||
if (sx > sy)
|
||||
sy = sx;
|
||||
else
|
||||
sx = sy;
|
||||
}
|
||||
|
||||
if (_shrinkOnly)
|
||||
{
|
||||
if (sx > 1)
|
||||
sx = 1;
|
||||
if (sy > 1)
|
||||
sy = 1;
|
||||
}
|
||||
contentSize.width = floor(sourceSize.width * sx);
|
||||
contentSize.height = floor(sourceSize.height * sy);
|
||||
}
|
||||
}
|
||||
|
||||
if (_content2 != nullptr)
|
||||
{
|
||||
_content2->setScale(sx, sy);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_contentItem != nullptr)
|
||||
{
|
||||
if (_contentItem->scale9Grid)
|
||||
{
|
||||
_content->setScale(1, 1);
|
||||
_content->setContentSize(contentSize);
|
||||
}
|
||||
else if (_contentItem->scaleByTile)
|
||||
{
|
||||
_content->setScale(1, 1);
|
||||
_content->setContentSize(sourceSize);
|
||||
_content->setTextureRect(Rect(Vec2::ZERO, contentSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
_content->setContentSize(sourceSize);
|
||||
_content->setScale(sx, sy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_content->setContentSize(sourceSize);
|
||||
_content->setScale(sx, sy);
|
||||
}
|
||||
_content->setAnchorPoint(Vec2::ZERO);
|
||||
}
|
||||
|
||||
float nx;
|
||||
float ny;
|
||||
if (_align == TextHAlignment::CENTER)
|
||||
nx = floor((_size.width - contentSize.width) / 2);
|
||||
else if (_align == TextHAlignment::RIGHT)
|
||||
nx = floor(_size.width - contentSize.width);
|
||||
else
|
||||
nx = 0;
|
||||
|
||||
if (_content2 != nullptr)
|
||||
{
|
||||
if (_verticalAlign == TextVAlignment::CENTER)
|
||||
ny = floor(-contentSize.height - (_size.height - contentSize.height) / 2);
|
||||
else if (_verticalAlign == TextVAlignment::BOTTOM)
|
||||
ny = -contentSize.height;
|
||||
else
|
||||
ny = -_size.height;
|
||||
|
||||
_content2->setPosition(nx, ny);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_verticalAlign == TextVAlignment::CENTER)
|
||||
ny = floor((_size.height - contentSize.height) / 2);
|
||||
else if (_verticalAlign == TextVAlignment::BOTTOM)
|
||||
ny = 0;
|
||||
else
|
||||
ny = _size.height - contentSize.height;
|
||||
|
||||
_content->setPosition(nx, ny);
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader::setErrorState()
|
||||
{
|
||||
}
|
||||
|
||||
void GLoader::clearErrorState()
|
||||
{
|
||||
}
|
||||
|
||||
void GLoader::handleSizeChanged()
|
||||
{
|
||||
GObject::handleSizeChanged();
|
||||
|
||||
if (!_updatingLayout)
|
||||
updateLayout();
|
||||
}
|
||||
|
||||
void GLoader::handleGrayedChanged()
|
||||
{
|
||||
GObject::handleGrayedChanged();
|
||||
|
||||
((FUISprite*)_content)->setGrayed(_finalGrayed);
|
||||
if (_content2 != nullptr)
|
||||
_content2->setGrayed(_finalGrayed);
|
||||
}
|
||||
|
||||
cocos2d::Value GLoader::getProp(ObjectPropID propId)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
return Value(ToolSet::colorToInt(getColor()));
|
||||
case ObjectPropID::Playing:
|
||||
return Value(isPlaying());
|
||||
case ObjectPropID::Frame:
|
||||
return Value(getFrame());
|
||||
case ObjectPropID::TimeScale:
|
||||
if (_playAction)
|
||||
return Value(_playAction->getTimeScale());
|
||||
else
|
||||
return Value(1);
|
||||
default:
|
||||
return GObject::getProp(propId);
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader::setProp(ObjectPropID propId, const cocos2d::Value& value)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
setColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
case ObjectPropID::Playing:
|
||||
setPlaying(value.asBool());
|
||||
break;
|
||||
case ObjectPropID::Frame:
|
||||
setFrame(value.asInt());
|
||||
break;
|
||||
case ObjectPropID::TimeScale:
|
||||
if (_playAction)
|
||||
_playAction->setTimeScale(value.asFloat());
|
||||
break;
|
||||
case ObjectPropID::DeltaTime:
|
||||
if (_playAction)
|
||||
_playAction->advance(value.asFloat());
|
||||
break;
|
||||
default:
|
||||
GObject::setProp(propId, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader::setup_beforeAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GObject::setup_beforeAdd(buffer, beginPos);
|
||||
|
||||
buffer->seek(beginPos, 5);
|
||||
|
||||
_url = buffer->readS();
|
||||
_align = (TextHAlignment)buffer->readByte();
|
||||
_verticalAlign = (TextVAlignment)buffer->readByte();
|
||||
_fill = (LoaderFillType)buffer->readByte();
|
||||
_shrinkOnly = buffer->readBool();
|
||||
_autoSize = buffer->readBool();
|
||||
buffer->readBool(); //_showErrorSign
|
||||
_playing = buffer->readBool();
|
||||
_frame = buffer->readInt();
|
||||
|
||||
if (buffer->readBool())
|
||||
setColor((Color3B)buffer->readColor());
|
||||
int fillMethod = buffer->readByte();
|
||||
if (fillMethod != 0)
|
||||
{
|
||||
_content->setFillMethod((FillMethod)fillMethod);
|
||||
_content->setFillOrigin((FillOrigin)buffer->readByte());
|
||||
_content->setFillClockwise(buffer->readBool());
|
||||
_content->setFillAmount(buffer->readFloat());
|
||||
}
|
||||
|
||||
if (_url.length() > 0)
|
||||
loadContent();
|
||||
}
|
||||
|
||||
GObject* GLoader::hitTest(const Vec2& worldPoint, const Camera* camera)
|
||||
{
|
||||
if (!_touchable || !_displayObject->isVisible() || !_displayObject->getParent())
|
||||
return nullptr;
|
||||
|
||||
if (_content2 != nullptr)
|
||||
{
|
||||
GObject* obj = _content2->hitTest(worldPoint, camera);
|
||||
if (obj != nullptr)
|
||||
return obj;
|
||||
}
|
||||
|
||||
Rect rect;
|
||||
rect.size = _size;
|
||||
//if (isScreenPointInRect(worldPoint, camera, _displayObject->getWorldToNodeTransform(), rect, nullptr))
|
||||
if (rect.containsPoint(_displayObject->convertToNodeSpace(worldPoint)))
|
||||
return this;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,110 @@
|
|||
#ifndef __GLOADER_H__
|
||||
#define __GLOADER_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GObject.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GComponent;
|
||||
class ActionMovieClip;
|
||||
class FUISprite;
|
||||
|
||||
class GLoader : public GObject
|
||||
{
|
||||
public:
|
||||
GLoader();
|
||||
virtual ~GLoader();
|
||||
|
||||
CREATE_FUNC(GLoader);
|
||||
|
||||
const std::string& getURL() const { return _url; }
|
||||
void setURL(const std::string& value);
|
||||
|
||||
virtual const std::string& getIcon() const override { return _url; }
|
||||
virtual void setIcon(const std::string& value) override { setURL(value); }
|
||||
|
||||
cocos2d::TextHAlignment getAlign() const { return _align; }
|
||||
void setAlign(cocos2d::TextHAlignment value);
|
||||
|
||||
cocos2d::TextVAlignment getVerticalAlign() const { return _verticalAlign; }
|
||||
void setVerticalAlign(cocos2d::TextVAlignment value);
|
||||
|
||||
bool getAutoSize() const { return _autoSize; }
|
||||
void setAutoSize(bool value);
|
||||
|
||||
LoaderFillType getFill() const { return _fill; }
|
||||
void setFill(LoaderFillType value);
|
||||
|
||||
bool isShrinkOnly() const { return _shrinkOnly; }
|
||||
void setShrinkOnly(bool value);
|
||||
|
||||
const cocos2d::Size& getContentSize();
|
||||
|
||||
cocos2d::Color3B getColor() const;
|
||||
void setColor(const cocos2d::Color3B& value);
|
||||
|
||||
bool isPlaying() const { return _playing; }
|
||||
void setPlaying(bool value);
|
||||
|
||||
int getFrame() const;
|
||||
void setFrame(int value);
|
||||
|
||||
FillMethod getFillMethod() const;
|
||||
void setFillMethod(FillMethod value);
|
||||
|
||||
FillOrigin getFillOrigin() const;
|
||||
void setFillOrigin(FillOrigin value);
|
||||
|
||||
bool isFillClockwise() const;
|
||||
void setFillClockwise(bool value);
|
||||
|
||||
float getFillAmount() const;
|
||||
void setFillAmount(float value);
|
||||
|
||||
GComponent* getComponent() const { return _content2; }
|
||||
|
||||
virtual cocos2d::Value getProp(ObjectPropID propId) override;
|
||||
virtual void setProp(ObjectPropID propId, const cocos2d::Value& value) override;
|
||||
|
||||
protected:
|
||||
virtual void handleInit() override;
|
||||
virtual void handleSizeChanged() override;
|
||||
virtual void handleGrayedChanged() override;
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual GObject* hitTest(const cocos2d::Vec2 & worldPoint, const cocos2d::Camera * camera) override;
|
||||
|
||||
virtual void loadExternal();
|
||||
virtual void freeExternal(cocos2d::SpriteFrame* spriteFrame);
|
||||
void onExternalLoadSuccess(cocos2d::SpriteFrame* spriteFrame);
|
||||
void onExternalLoadFailed();
|
||||
|
||||
private:
|
||||
void loadContent();
|
||||
void loadFromPackage();
|
||||
void clearContent();
|
||||
void updateLayout();
|
||||
void setErrorState();
|
||||
void clearErrorState();
|
||||
|
||||
std::string _url;
|
||||
cocos2d::TextHAlignment _align;
|
||||
cocos2d::TextVAlignment _verticalAlign;
|
||||
bool _autoSize;
|
||||
LoaderFillType _fill;
|
||||
bool _shrinkOnly;
|
||||
bool _updatingLayout;
|
||||
PackageItem* _contentItem;
|
||||
int _contentStatus;
|
||||
bool _playing;
|
||||
int _frame;
|
||||
|
||||
FUISprite* _content;
|
||||
GComponent* _content2;
|
||||
ActionMovieClip* _playAction;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,470 @@
|
|||
#include "GLoader3D.h"
|
||||
#include "GComponent.h"
|
||||
#include "GMovieClip.h"
|
||||
#include "UIPackage.h"
|
||||
#include "display/FUISprite.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
#include "spine/spine-cocos2dx.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GLoader3D::GLoader3D()
|
||||
: _autoSize(false),
|
||||
_align(TextHAlignment::LEFT),
|
||||
_verticalAlign(TextVAlignment::TOP),
|
||||
_fill(LoaderFillType::NONE),
|
||||
_shrinkOnly(false),
|
||||
_updatingLayout(false),
|
||||
_contentItem(nullptr),
|
||||
_content(nullptr),
|
||||
_container(nullptr),
|
||||
_playing(true),
|
||||
_frame(0),
|
||||
_loop(false),
|
||||
_color(255, 255, 255)
|
||||
{
|
||||
}
|
||||
|
||||
GLoader3D::~GLoader3D()
|
||||
{
|
||||
CC_SAFE_RELEASE(_content);
|
||||
CC_SAFE_RELEASE(_container);
|
||||
}
|
||||
|
||||
void GLoader3D::handleInit()
|
||||
{
|
||||
FUIContainer* c = FUIContainer::create();
|
||||
c->retain();
|
||||
c->gOwner = this;
|
||||
_displayObject = c;
|
||||
|
||||
_container = FUIContainer::create();
|
||||
_container->retain();
|
||||
_container->setAnchorPoint(Vec2(0, 1));
|
||||
_displayObject->addChild(_container);
|
||||
}
|
||||
|
||||
void GLoader3D::setURL(const std::string& value)
|
||||
{
|
||||
if (_url.compare(value) == 0)
|
||||
return;
|
||||
|
||||
_url = value;
|
||||
loadContent();
|
||||
updateGear(7);
|
||||
}
|
||||
|
||||
void GLoader3D::setAlign(cocos2d::TextHAlignment value)
|
||||
{
|
||||
if (_align != value)
|
||||
{
|
||||
_align = value;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader3D::setVerticalAlign(cocos2d::TextVAlignment value)
|
||||
{
|
||||
if (_verticalAlign != value)
|
||||
{
|
||||
_verticalAlign = value;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader3D::setAutoSize(bool value)
|
||||
{
|
||||
if (_autoSize != value)
|
||||
{
|
||||
_autoSize = value;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader3D::setFill(LoaderFillType value)
|
||||
{
|
||||
if (_fill != value)
|
||||
{
|
||||
_fill = value;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader3D::setShrinkOnly(bool value)
|
||||
{
|
||||
if (_shrinkOnly != value)
|
||||
{
|
||||
_shrinkOnly = value;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
cocos2d::Color3B GLoader3D::getColor() const
|
||||
{
|
||||
return _color;
|
||||
}
|
||||
|
||||
void GLoader3D::setColor(const cocos2d::Color3B& value)
|
||||
{
|
||||
_color = value;
|
||||
if (_content != nullptr)
|
||||
_content->setColor(_color);
|
||||
}
|
||||
|
||||
void GLoader3D::setPlaying(bool value)
|
||||
{
|
||||
if (_playing != value)
|
||||
{
|
||||
_playing = value;
|
||||
updateGear(5);
|
||||
}
|
||||
}
|
||||
|
||||
int GLoader3D::getFrame() const
|
||||
{
|
||||
return _frame;
|
||||
}
|
||||
|
||||
void GLoader3D::setFrame(int value)
|
||||
{
|
||||
if (_frame != value)
|
||||
{
|
||||
_frame = value;
|
||||
updateGear(5);
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader3D::setAnimationName(const std::string& value)
|
||||
{
|
||||
_animationName = value;
|
||||
onChange();
|
||||
}
|
||||
|
||||
void GLoader3D::setSkinName(const std::string& value)
|
||||
{
|
||||
_skinName = value;
|
||||
onChange();
|
||||
}
|
||||
|
||||
void GLoader3D::setLoop(bool value)
|
||||
{
|
||||
_loop = value;
|
||||
onChange();
|
||||
}
|
||||
|
||||
void GLoader3D::setContent(cocos2d::Node* value)
|
||||
{
|
||||
setURL(STD_STRING_EMPTY);
|
||||
|
||||
_content = value;
|
||||
if (_content != nullptr)
|
||||
{
|
||||
_content->retain();
|
||||
_container->addChild(value);
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader3D::loadContent()
|
||||
{
|
||||
clearContent();
|
||||
|
||||
if (_url.length() == 0)
|
||||
return;
|
||||
|
||||
if (_url.compare(0, 5, "ui://") == 0)
|
||||
loadFromPackage();
|
||||
else
|
||||
loadExternal();
|
||||
}
|
||||
|
||||
void GLoader3D::loadFromPackage()
|
||||
{
|
||||
_contentItem = UIPackage::getItemByURL(_url);
|
||||
|
||||
if (_contentItem != nullptr)
|
||||
{
|
||||
_contentItem = _contentItem->getBranch();
|
||||
sourceSize.width = _contentItem->width;
|
||||
sourceSize.height = _contentItem->height;
|
||||
_contentItem = _contentItem->getHighResolution();
|
||||
_contentItem->load();
|
||||
|
||||
if (_contentItem->type == PackageItemType::SPINE)
|
||||
{
|
||||
size_t pos = _contentItem->file.find_last_of('.');
|
||||
std::string atlasFile = _contentItem->file.substr(0, pos + 1).append("atlas");
|
||||
if (!ToolSet::isFileExist(atlasFile))
|
||||
atlasFile = _contentItem->file.substr(0, pos + 1).append("atlas.txt");
|
||||
spine::SkeletonAnimation* skeletonAni;
|
||||
if (FileUtils::getInstance()->getFileExtension(_contentItem->file) == ".skel")
|
||||
skeletonAni = spine::SkeletonAnimation::createWithBinaryFile(_contentItem->file, atlasFile);
|
||||
else
|
||||
skeletonAni = spine::SkeletonAnimation::createWithJsonFile(_contentItem->file, atlasFile);
|
||||
skeletonAni->setPosition(_contentItem->skeletonAnchor->x, -_contentItem->skeletonAnchor->y);
|
||||
skeletonAni->retain();
|
||||
|
||||
_content = skeletonAni;
|
||||
_container->addChild(_content);
|
||||
|
||||
onChangeSpine();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_autoSize)
|
||||
setSize(_contentItem->width, _contentItem->height);
|
||||
|
||||
setErrorState();
|
||||
}
|
||||
}
|
||||
else
|
||||
setErrorState();
|
||||
}
|
||||
|
||||
void GLoader3D::onChange()
|
||||
{
|
||||
onChangeSpine();
|
||||
}
|
||||
|
||||
void GLoader3D::onChangeSpine()
|
||||
{
|
||||
spine::SkeletonAnimation* skeletonAni = dynamic_cast<spine::SkeletonAnimation*>(_content);
|
||||
if (skeletonAni == nullptr)
|
||||
return;
|
||||
|
||||
spine::AnimationState* state = skeletonAni->getState();
|
||||
|
||||
spine::Animation* aniToUse = !_animationName.empty() ? skeletonAni->findAnimation(_animationName) : nullptr;
|
||||
if (aniToUse != nullptr)
|
||||
{
|
||||
spine::TrackEntry* entry = state->getCurrent(0);
|
||||
if (entry == nullptr || strcmp(entry->getAnimation()->getName().buffer(), _animationName.c_str()) != 0
|
||||
|| entry->isComplete() && !entry->getLoop())
|
||||
entry = state->setAnimation(0, aniToUse, _loop);
|
||||
else
|
||||
entry->setLoop(_loop);
|
||||
|
||||
if (_playing)
|
||||
entry->setTimeScale(1);
|
||||
else
|
||||
{
|
||||
entry->setTimeScale(0);
|
||||
entry->setTrackTime(MathUtil::lerp(0, entry->getAnimationEnd() - entry->getAnimationStart(), _frame / 100.0f));
|
||||
}
|
||||
}
|
||||
else
|
||||
state->clearTrack(0);
|
||||
|
||||
skeletonAni->setSkin(_skinName);
|
||||
}
|
||||
|
||||
void GLoader3D::loadExternal()
|
||||
{
|
||||
}
|
||||
|
||||
void GLoader3D::freeExternal(cocos2d::SpriteFrame* spriteFrame)
|
||||
{
|
||||
}
|
||||
|
||||
void GLoader3D::onExternalLoadSuccess(cocos2d::SpriteFrame* spriteFrame)
|
||||
{
|
||||
}
|
||||
|
||||
void GLoader3D::onExternalLoadFailed()
|
||||
{
|
||||
setErrorState();
|
||||
}
|
||||
|
||||
void GLoader3D::clearContent()
|
||||
{
|
||||
clearErrorState();
|
||||
_contentItem = nullptr;
|
||||
}
|
||||
|
||||
void GLoader3D::updateLayout()
|
||||
{
|
||||
Size contentSize = sourceSize;
|
||||
|
||||
if (_autoSize)
|
||||
{
|
||||
_updatingLayout = true;
|
||||
if (contentSize.width == 0)
|
||||
contentSize.width = 50;
|
||||
if (contentSize.height == 0)
|
||||
contentSize.height = 30;
|
||||
setSize(contentSize.width, contentSize.height);
|
||||
_updatingLayout = false;
|
||||
|
||||
if (_size.equals(contentSize))
|
||||
{
|
||||
_container->setScale(1, 1);
|
||||
_container->setAnchorPoint(Vec2::ZERO);
|
||||
_container->setPosition(0, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float sx = 1, sy = 1;
|
||||
if (_fill != LoaderFillType::NONE)
|
||||
{
|
||||
sx = _size.width / sourceSize.width;
|
||||
sy = _size.height / sourceSize.height;
|
||||
|
||||
if (sx != 1 || sy != 1)
|
||||
{
|
||||
if (_fill == LoaderFillType::SCALE_MATCH_HEIGHT)
|
||||
sx = sy;
|
||||
else if (_fill == LoaderFillType::SCALE_MATCH_WIDTH)
|
||||
sy = sx;
|
||||
else if (_fill == LoaderFillType::SCALE)
|
||||
{
|
||||
if (sx > sy)
|
||||
sx = sy;
|
||||
else
|
||||
sy = sx;
|
||||
}
|
||||
else if (_fill == LoaderFillType::SCALE_NO_BORDER)
|
||||
{
|
||||
if (sx > sy)
|
||||
sy = sx;
|
||||
else
|
||||
sx = sy;
|
||||
}
|
||||
|
||||
if (_shrinkOnly)
|
||||
{
|
||||
if (sx > 1)
|
||||
sx = 1;
|
||||
if (sy > 1)
|
||||
sy = 1;
|
||||
}
|
||||
contentSize.width = floor(sourceSize.width * sx);
|
||||
contentSize.height = floor(sourceSize.height * sy);
|
||||
}
|
||||
}
|
||||
|
||||
_container->setScale(sx, sy);
|
||||
_container->setAnchorPoint(Vec2::ZERO);
|
||||
|
||||
float nx;
|
||||
float ny;
|
||||
if (_align == TextHAlignment::CENTER)
|
||||
nx = floor((_size.width - contentSize.width) / 2);
|
||||
else if (_align == TextHAlignment::RIGHT)
|
||||
nx = floor(_size.width - contentSize.width);
|
||||
else
|
||||
nx = 0;
|
||||
|
||||
if (_verticalAlign == TextVAlignment::CENTER)
|
||||
ny = floor((_size.height - contentSize.height) / 2);
|
||||
else if (_verticalAlign == TextVAlignment::BOTTOM)
|
||||
ny = 0;
|
||||
else
|
||||
ny = _size.height - contentSize.height;
|
||||
|
||||
_container->setPosition(nx, ny);
|
||||
}
|
||||
|
||||
void GLoader3D::setErrorState()
|
||||
{
|
||||
}
|
||||
|
||||
void GLoader3D::clearErrorState()
|
||||
{
|
||||
}
|
||||
|
||||
void GLoader3D::handleSizeChanged()
|
||||
{
|
||||
GObject::handleSizeChanged();
|
||||
|
||||
if (!_updatingLayout)
|
||||
updateLayout();
|
||||
}
|
||||
|
||||
void GLoader3D::handleGrayedChanged()
|
||||
{
|
||||
GObject::handleGrayedChanged();
|
||||
}
|
||||
|
||||
cocos2d::Value GLoader3D::getProp(ObjectPropID propId)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
return Value(ToolSet::colorToInt(getColor()));
|
||||
case ObjectPropID::Playing:
|
||||
return Value(isPlaying());
|
||||
case ObjectPropID::Frame:
|
||||
return Value(getFrame());
|
||||
case ObjectPropID::TimeScale:
|
||||
return Value(1);
|
||||
default:
|
||||
return GObject::getProp(propId);
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader3D::setProp(ObjectPropID propId, const cocos2d::Value& value)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
setColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
case ObjectPropID::Playing:
|
||||
setPlaying(value.asBool());
|
||||
break;
|
||||
case ObjectPropID::Frame:
|
||||
setFrame(value.asInt());
|
||||
break;
|
||||
case ObjectPropID::TimeScale:
|
||||
break;
|
||||
case ObjectPropID::DeltaTime:
|
||||
break;
|
||||
default:
|
||||
GObject::setProp(propId, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GLoader3D::setup_beforeAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GObject::setup_beforeAdd(buffer, beginPos);
|
||||
|
||||
buffer->seek(beginPos, 5);
|
||||
|
||||
_url = buffer->readS();
|
||||
_align = (TextHAlignment)buffer->readByte();
|
||||
_verticalAlign = (TextVAlignment)buffer->readByte();
|
||||
_fill = (LoaderFillType)buffer->readByte();
|
||||
_shrinkOnly = buffer->readBool();
|
||||
_autoSize = buffer->readBool();
|
||||
_animationName = buffer->readS();
|
||||
_skinName = buffer->readS();
|
||||
_playing = buffer->readBool();
|
||||
_frame = buffer->readInt();
|
||||
_loop = buffer->readBool();
|
||||
|
||||
if (buffer->readBool())
|
||||
setColor((Color3B)buffer->readColor());
|
||||
|
||||
if (_url.length() > 0)
|
||||
loadContent();
|
||||
}
|
||||
|
||||
GObject* GLoader3D::hitTest(const Vec2& worldPoint, const Camera* camera)
|
||||
{
|
||||
if (!_touchable || !_displayObject->isVisible() || !_displayObject->getParent())
|
||||
return nullptr;
|
||||
|
||||
Rect rect;
|
||||
rect.size = _size;
|
||||
//if (isScreenPointInRect(worldPoint, camera, _displayObject->getWorldToNodeTransform(), rect, nullptr))
|
||||
if (rect.containsPoint(_displayObject->convertToNodeSpace(worldPoint)))
|
||||
return this;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,110 @@
|
|||
#ifndef __GLOADER3D_H__
|
||||
#define __GLOADER3D_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GObject.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GComponent;
|
||||
class FUIContainer;
|
||||
|
||||
class GLoader3D : public GObject
|
||||
{
|
||||
public:
|
||||
GLoader3D();
|
||||
virtual ~GLoader3D();
|
||||
|
||||
CREATE_FUNC(GLoader3D);
|
||||
|
||||
const std::string& getURL() const { return _url; }
|
||||
void setURL(const std::string& value);
|
||||
|
||||
virtual const std::string& getIcon() const override { return _url; }
|
||||
virtual void setIcon(const std::string& value) override { setURL(value); }
|
||||
|
||||
cocos2d::TextHAlignment getAlign() const { return _align; }
|
||||
void setAlign(cocos2d::TextHAlignment value);
|
||||
|
||||
cocos2d::TextVAlignment getVerticalAlign() const { return _verticalAlign; }
|
||||
void setVerticalAlign(cocos2d::TextVAlignment value);
|
||||
|
||||
bool getAutoSize() const { return _autoSize; }
|
||||
void setAutoSize(bool value);
|
||||
|
||||
LoaderFillType getFill() const { return _fill; }
|
||||
void setFill(LoaderFillType value);
|
||||
|
||||
bool isShrinkOnly() const { return _shrinkOnly; }
|
||||
void setShrinkOnly(bool value);
|
||||
|
||||
const cocos2d::Node* getContent() { return _content; }
|
||||
void setContent(cocos2d::Node* value);
|
||||
|
||||
cocos2d::Color3B getColor() const;
|
||||
void setColor(const cocos2d::Color3B& value);
|
||||
|
||||
bool isPlaying() const { return _playing; }
|
||||
void setPlaying(bool value);
|
||||
|
||||
int getFrame() const;
|
||||
void setFrame(int value);
|
||||
|
||||
const std::string& getAnimationName() const { return _animationName; }
|
||||
void setAnimationName(const std::string& value);
|
||||
|
||||
const std::string& getSkinName() const { return _skinName; }
|
||||
void setSkinName(const std::string& value);
|
||||
|
||||
bool getLoop() const { return _loop; }
|
||||
void setLoop(bool value);
|
||||
|
||||
virtual cocos2d::Value getProp(ObjectPropID propId) override;
|
||||
virtual void setProp(ObjectPropID propId, const cocos2d::Value& value) override;
|
||||
|
||||
protected:
|
||||
virtual void handleInit() override;
|
||||
virtual void handleSizeChanged() override;
|
||||
virtual void handleGrayedChanged() override;
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual GObject* hitTest(const cocos2d::Vec2 & worldPoint, const cocos2d::Camera * camera) override;
|
||||
|
||||
virtual void loadExternal();
|
||||
virtual void freeExternal(cocos2d::SpriteFrame* spriteFrame);
|
||||
void onExternalLoadSuccess(cocos2d::SpriteFrame* spriteFrame);
|
||||
void onExternalLoadFailed();
|
||||
|
||||
void onChange();
|
||||
void onChangeSpine();
|
||||
|
||||
private:
|
||||
void loadContent();
|
||||
void loadFromPackage();
|
||||
void clearContent();
|
||||
void updateLayout();
|
||||
void setErrorState();
|
||||
void clearErrorState();
|
||||
|
||||
std::string _url;
|
||||
cocos2d::TextHAlignment _align;
|
||||
cocos2d::TextVAlignment _verticalAlign;
|
||||
bool _autoSize;
|
||||
LoaderFillType _fill;
|
||||
bool _shrinkOnly;
|
||||
bool _updatingLayout;
|
||||
PackageItem* _contentItem;
|
||||
bool _playing;
|
||||
int _frame;
|
||||
bool _loop;
|
||||
std::string _animationName;
|
||||
std::string _skinName;
|
||||
cocos2d::Color3B _color;
|
||||
|
||||
FUIContainer* _container;
|
||||
cocos2d::Node* _content;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,483 @@
|
|||
#include "GMovieClip.h"
|
||||
#include "PackageItem.h"
|
||||
#include "display/FUISprite.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GMovieClip::GMovieClip()
|
||||
: _playAction(nullptr),
|
||||
_content(nullptr),
|
||||
_playing(true)
|
||||
{
|
||||
_sizeImplType = 1;
|
||||
_touchDisabled = true;
|
||||
}
|
||||
|
||||
GMovieClip::~GMovieClip()
|
||||
{
|
||||
CC_SAFE_RELEASE(_playAction);
|
||||
}
|
||||
|
||||
void GMovieClip::handleInit()
|
||||
{
|
||||
_content = FUISprite::create();
|
||||
_content->retain();
|
||||
|
||||
_playAction = ActionMovieClip::create(nullptr);
|
||||
_playAction->retain();
|
||||
|
||||
_displayObject = _content;
|
||||
}
|
||||
|
||||
void GMovieClip::setPlaySettings(int start, int end, int times, int endAt, std::function<void()> completeCallback)
|
||||
{
|
||||
_playAction->setPlaySettings(start, end, times, endAt, completeCallback);
|
||||
}
|
||||
|
||||
void GMovieClip::setPlaying(bool value)
|
||||
{
|
||||
if (_playing != value)
|
||||
{
|
||||
_playing = value;
|
||||
if (_playing)
|
||||
_content->runAction(_playAction);
|
||||
else
|
||||
_content->stopAction(_playAction);
|
||||
}
|
||||
}
|
||||
|
||||
int GMovieClip::getFrame() const
|
||||
{
|
||||
return _playAction->getFrame();
|
||||
}
|
||||
void GMovieClip::setFrame(int value)
|
||||
{
|
||||
_playAction->setFrame(value);
|
||||
}
|
||||
|
||||
float GMovieClip::getTimeScale() const
|
||||
{
|
||||
return _playAction->getTimeScale();
|
||||
}
|
||||
void GMovieClip::setTimeScale(float value)
|
||||
{
|
||||
_playAction->setTimeScale(value);
|
||||
}
|
||||
|
||||
void GMovieClip::advance(float time)
|
||||
{
|
||||
_playAction->advance(time);
|
||||
}
|
||||
|
||||
FlipType GMovieClip::getFlip() const
|
||||
{
|
||||
if (_content->isFlippedX() && _content->isFlippedY())
|
||||
return FlipType::BOTH;
|
||||
else if (_content->isFlippedX())
|
||||
return FlipType::HORIZONTAL;
|
||||
else if (_content->isFlippedY())
|
||||
return FlipType::VERTICAL;
|
||||
else
|
||||
return FlipType::NONE;
|
||||
}
|
||||
|
||||
void GMovieClip::setFlip(FlipType value)
|
||||
{
|
||||
_content->setFlippedX(value == FlipType::HORIZONTAL || value == FlipType::BOTH);
|
||||
_content->setFlippedY(value == FlipType::VERTICAL || value == FlipType::BOTH);
|
||||
}
|
||||
|
||||
void GMovieClip::setColor(const cocos2d::Color3B& value)
|
||||
{
|
||||
_content->setColor(value);
|
||||
}
|
||||
|
||||
void GMovieClip::handleGrayedChanged()
|
||||
{
|
||||
GObject::handleGrayedChanged();
|
||||
|
||||
((FUISprite*)_content)->setGrayed(_finalGrayed);
|
||||
}
|
||||
|
||||
cocos2d::Value GMovieClip::getProp(ObjectPropID propId)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
return Value(ToolSet::colorToInt(getColor()));
|
||||
case ObjectPropID::Playing:
|
||||
return Value(isPlaying());
|
||||
case ObjectPropID::Frame:
|
||||
return Value(getFrame());
|
||||
case ObjectPropID::TimeScale:
|
||||
return Value(_playAction->getTimeScale());
|
||||
default:
|
||||
return GObject::getProp(propId);
|
||||
}
|
||||
}
|
||||
|
||||
void GMovieClip::setProp(ObjectPropID propId, const cocos2d::Value& value)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
setColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
case ObjectPropID::Playing:
|
||||
setPlaying(value.asBool());
|
||||
break;
|
||||
case ObjectPropID::Frame:
|
||||
setFrame(value.asInt());
|
||||
break;
|
||||
case ObjectPropID::TimeScale:
|
||||
_playAction->setTimeScale(value.asFloat());
|
||||
break;
|
||||
case ObjectPropID::DeltaTime:
|
||||
_playAction->advance(value.asFloat());
|
||||
break;
|
||||
default:
|
||||
GObject::setProp(propId, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GMovieClip::constructFromResource()
|
||||
{
|
||||
PackageItem* contentItem = _packageItem->getBranch();
|
||||
sourceSize.width = contentItem->width;
|
||||
sourceSize.height = contentItem->height;
|
||||
initSize = sourceSize;
|
||||
|
||||
contentItem = contentItem->getHighResolution();
|
||||
contentItem->load();
|
||||
|
||||
_playAction->setAnimation(contentItem->animation, contentItem->repeatDelay, contentItem->swing);
|
||||
_content->runAction(_playAction);
|
||||
|
||||
setSize(sourceSize.width, sourceSize.height);
|
||||
}
|
||||
|
||||
void GMovieClip::setup_beforeAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GObject::setup_beforeAdd(buffer, beginPos);
|
||||
|
||||
buffer->seek(beginPos, 5);
|
||||
|
||||
if (buffer->readBool())
|
||||
setColor((Color3B)buffer->readColor());
|
||||
setFlip((FlipType)buffer->readByte());
|
||||
setFrame(buffer->readInt());
|
||||
setPlaying(buffer->readBool());
|
||||
}
|
||||
|
||||
ActionMovieClip::ActionMovieClip() : _animation(nullptr),
|
||||
_frame(0),
|
||||
_frameElapsed(0),
|
||||
_repeatedCount(0),
|
||||
_repeatDelay(0),
|
||||
_start(0),
|
||||
_end(0),
|
||||
_times(0),
|
||||
_endAt(0),
|
||||
_status(0),
|
||||
_displayFrame(-1),
|
||||
_swing(false),
|
||||
_reversed(false),
|
||||
_timeScale(1)
|
||||
{
|
||||
}
|
||||
|
||||
ActionMovieClip::~ActionMovieClip()
|
||||
{
|
||||
CC_SAFE_RELEASE(_animation);
|
||||
}
|
||||
|
||||
ActionMovieClip* ActionMovieClip::create(cocos2d::Animation* animation, float repeatDelay, bool swing)
|
||||
{
|
||||
ActionMovieClip* action = new (std::nothrow) ActionMovieClip();
|
||||
if (action)
|
||||
{
|
||||
action->setAnimation(animation, repeatDelay, swing);
|
||||
action->autorelease();
|
||||
return action;
|
||||
}
|
||||
|
||||
delete action;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ActionMovieClip::isDone() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void ActionMovieClip::step(float dt)
|
||||
{
|
||||
if (_animation == nullptr)
|
||||
return;
|
||||
|
||||
auto frames = _animation->getFrames();
|
||||
int frameCount = (int)frames.size();
|
||||
if (frameCount == 0)
|
||||
return;
|
||||
|
||||
if (frameCount == 0 || _status == 3)
|
||||
return;
|
||||
|
||||
if (_timeScale != 1)
|
||||
dt *= _timeScale;
|
||||
|
||||
_frameElapsed += dt;
|
||||
float tt = (frames.at(_frame)->getDelayUnits() + ((_frame == 0 && _repeatedCount > 0) ? _repeatDelay : 0)) * _animation->getDelayPerUnit();
|
||||
if (_frame == 0 && _repeatedCount > 0)
|
||||
tt += _repeatDelay;
|
||||
if (_frameElapsed < tt)
|
||||
return;
|
||||
|
||||
_frameElapsed -= tt;
|
||||
if (_frameElapsed > _animation->getDelayPerUnit())
|
||||
_frameElapsed = _animation->getDelayPerUnit();
|
||||
|
||||
if (_swing)
|
||||
{
|
||||
if (_reversed)
|
||||
{
|
||||
_frame--;
|
||||
if (_frame <= 0)
|
||||
{
|
||||
_frame = 0;
|
||||
_repeatedCount++;
|
||||
_reversed = !_reversed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_frame++;
|
||||
if (_frame > frameCount - 1)
|
||||
{
|
||||
_frame = MAX(0, frameCount - 2);
|
||||
_repeatedCount++;
|
||||
_reversed = !_reversed;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_frame++;
|
||||
if (_frame > frameCount - 1)
|
||||
{
|
||||
_frame = 0;
|
||||
_repeatedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (_status == 1) //new loop
|
||||
{
|
||||
_frame = _start;
|
||||
_frameElapsed = 0;
|
||||
_status = 0;
|
||||
}
|
||||
else if (_status == 2) //ending
|
||||
{
|
||||
_frame = _endAt;
|
||||
_frameElapsed = 0;
|
||||
_status = 3; //ended
|
||||
|
||||
if (_completeCallback)
|
||||
_completeCallback();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_frame == _end)
|
||||
{
|
||||
if (_times > 0)
|
||||
{
|
||||
_times--;
|
||||
if (_times == 0)
|
||||
_status = 2; //ending
|
||||
else
|
||||
_status = 1; //new loop
|
||||
}
|
||||
else if (_start != 0)
|
||||
_status = 1; //new loop
|
||||
}
|
||||
}
|
||||
|
||||
drawFrame();
|
||||
}
|
||||
|
||||
void ActionMovieClip::startWithTarget(Node* target)
|
||||
{
|
||||
Action::startWithTarget(target);
|
||||
|
||||
drawFrame();
|
||||
}
|
||||
|
||||
ActionMovieClip* ActionMovieClip::reverse() const
|
||||
{
|
||||
CC_ASSERT(0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ActionMovieClip* ActionMovieClip::clone() const
|
||||
{
|
||||
return ActionMovieClip::create(_animation->clone(), _repeatDelay, _swing);
|
||||
}
|
||||
|
||||
void ActionMovieClip::setFrame(int value)
|
||||
{
|
||||
if (_animation == nullptr)
|
||||
return;
|
||||
|
||||
auto frames = _animation->getFrames();
|
||||
int frameCount = (int)frames.size();
|
||||
|
||||
if (value >= frameCount)
|
||||
value = frameCount - 1;
|
||||
|
||||
_frame = value;
|
||||
_frameElapsed = 0;
|
||||
_displayFrame = -1;
|
||||
drawFrame();
|
||||
}
|
||||
|
||||
void ActionMovieClip::advance(float time)
|
||||
{
|
||||
if (_animation == nullptr)
|
||||
return;
|
||||
|
||||
auto frames = _animation->getFrames();
|
||||
int frameCount = (int)frames.size();
|
||||
if (frameCount == 0)
|
||||
return;
|
||||
|
||||
int beginFrame = _frame;
|
||||
bool beginReversed = _reversed;
|
||||
float backupTime = time;
|
||||
while (true)
|
||||
{
|
||||
float tt = (frames.at(_frame)->getDelayUnits() + ((_frame == 0 && _repeatedCount > 0) ? _repeatDelay : 0)) * _animation->getDelayPerUnit();
|
||||
if (_frame == 0 && _repeatedCount > 0)
|
||||
tt += _repeatDelay;
|
||||
if (time < tt)
|
||||
{
|
||||
_frameElapsed = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
time -= tt;
|
||||
|
||||
if (_swing)
|
||||
{
|
||||
if (_reversed)
|
||||
{
|
||||
_frame--;
|
||||
if (_frame <= 0)
|
||||
{
|
||||
_frame = 0;
|
||||
_repeatedCount++;
|
||||
_reversed = !_reversed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_frame++;
|
||||
if (_frame > frameCount - 1)
|
||||
{
|
||||
_frame = MAX(0, frameCount - 2);
|
||||
_repeatedCount++;
|
||||
_reversed = !_reversed;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_frame++;
|
||||
if (_frame > frameCount - 1)
|
||||
{
|
||||
_frame = 0;
|
||||
_repeatedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (_frame == beginFrame && _reversed == beginReversed)
|
||||
{
|
||||
float roundTime = backupTime - time;
|
||||
time -= (int)floor(time / roundTime) * roundTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActionMovieClip::setPlaySettings(int start, int end, int times, int endAt, std::function<void()> completeCallback)
|
||||
{
|
||||
auto frames = _animation->getFrames();
|
||||
int frameCount = (int)frames.size();
|
||||
|
||||
_start = start;
|
||||
_end = end;
|
||||
if (_end == -1 || _end > frameCount - 1)
|
||||
_end = frameCount - 1;
|
||||
_times = times;
|
||||
_endAt = endAt;
|
||||
if (_endAt == -1)
|
||||
_endAt = _end;
|
||||
_status = 0;
|
||||
_completeCallback = completeCallback;
|
||||
|
||||
setFrame(start);
|
||||
}
|
||||
|
||||
void ActionMovieClip::setAnimation(cocos2d::Animation* animation, float repeatDelay, bool swing)
|
||||
{
|
||||
if (_animation != animation)
|
||||
{
|
||||
CC_SAFE_RETAIN(animation);
|
||||
CC_SAFE_RELEASE(_animation);
|
||||
_animation = animation;
|
||||
}
|
||||
|
||||
if (_animation == nullptr)
|
||||
return;
|
||||
|
||||
_repeatDelay = repeatDelay;
|
||||
_swing = swing;
|
||||
_completeCallback = nullptr;
|
||||
|
||||
auto frames = _animation->getFrames();
|
||||
int frameCount = (int)frames.size();
|
||||
if (_end == -1 || _end > frameCount - 1)
|
||||
_end = frameCount - 1;
|
||||
if (_endAt == -1 || _endAt > frameCount - 1)
|
||||
_endAt = frameCount - 1;
|
||||
|
||||
if (_frame < 0 || _frame > frameCount - 1)
|
||||
_frame = frameCount - 1;
|
||||
|
||||
_displayFrame = -1;
|
||||
_frameElapsed = 0;
|
||||
_repeatedCount = 0;
|
||||
_reversed = false;
|
||||
}
|
||||
|
||||
void ActionMovieClip::drawFrame()
|
||||
{
|
||||
if (_target == nullptr || _animation == nullptr)
|
||||
return;
|
||||
|
||||
auto frames = _animation->getFrames();
|
||||
int frameCount = (int)frames.size();
|
||||
|
||||
if (_frame == _displayFrame || frameCount == 0)
|
||||
return;
|
||||
|
||||
_displayFrame = _frame;
|
||||
AnimationFrame* frame = frames.at(_frame);
|
||||
//auto blend = static_cast<Sprite*>(_target)->getBlendFunc();
|
||||
static_cast<Sprite*>(_target)->setSpriteFrame(frame->getSpriteFrame());
|
||||
//static_cast<Sprite*>(_target)->setBlendFunc(blend);
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,106 @@
|
|||
#ifndef __GMOVIECLIP_H__
|
||||
#define __GMOVIECLIP_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GObject.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class ActionMovieClip;
|
||||
|
||||
class GMovieClip : public GObject
|
||||
{
|
||||
public:
|
||||
GMovieClip();
|
||||
virtual ~GMovieClip();
|
||||
|
||||
CREATE_FUNC(GMovieClip);
|
||||
|
||||
bool isPlaying() const { return _playing; }
|
||||
void setPlaying(bool value);
|
||||
|
||||
int getFrame() const;
|
||||
void setFrame(int value);
|
||||
|
||||
float getTimeScale() const;
|
||||
void setTimeScale(float value);
|
||||
|
||||
void advance(float time);
|
||||
|
||||
FlipType getFlip() const;
|
||||
void setFlip(FlipType value);
|
||||
|
||||
cocos2d::Color3B getColor() const { return _content->getColor(); }
|
||||
void setColor(const cocos2d::Color3B& value);
|
||||
|
||||
//from start to end(-1 means ending) repeat times(0 means infinite loop) when all is over, stopping at endAt(-1 means same value of end)
|
||||
void setPlaySettings(int start = 0, int end = -1, int times = 0, int endAt = -1, std::function<void()> completeCallback = nullptr);
|
||||
|
||||
virtual void constructFromResource() override;
|
||||
|
||||
virtual cocos2d::Value getProp(ObjectPropID propId) override;
|
||||
virtual void setProp(ObjectPropID propId, const cocos2d::Value& value) override;
|
||||
|
||||
protected:
|
||||
virtual void handleInit() override;
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual void handleGrayedChanged() override;
|
||||
|
||||
private:
|
||||
cocos2d::Sprite* _content;
|
||||
ActionMovieClip* _playAction;
|
||||
bool _playing;
|
||||
};
|
||||
|
||||
class ActionMovieClip : public cocos2d::Action
|
||||
{
|
||||
public:
|
||||
static ActionMovieClip* create(cocos2d::Animation *animation, float repeatDelay = 0, bool swing =false);
|
||||
ActionMovieClip();
|
||||
~ActionMovieClip();
|
||||
|
||||
virtual bool isDone() const override;
|
||||
virtual void step(float dt) override;
|
||||
virtual void startWithTarget(cocos2d::Node *target) override;
|
||||
virtual ActionMovieClip* reverse() const override;
|
||||
virtual ActionMovieClip* clone() const override;
|
||||
|
||||
int getFrame() { return _frame; }
|
||||
void setFrame(int value);
|
||||
|
||||
float getTimeScale() const { return _timeScale; }
|
||||
void setTimeScale(float value) { _timeScale = value; }
|
||||
|
||||
void advance(float time);
|
||||
|
||||
void setPlaySettings(int start, int end, int times, int endAt, std::function<void()> completeCallback = nullptr);
|
||||
void setAnimation(cocos2d::Animation *animation, float repeatDelay = 0, bool swing = false);
|
||||
|
||||
private:
|
||||
void drawFrame();
|
||||
|
||||
cocos2d::Animation* _animation;
|
||||
int _frame;
|
||||
float _frameElapsed;
|
||||
int _repeatedCount;
|
||||
bool _reversed;
|
||||
float _timeScale;
|
||||
|
||||
float _repeatDelay;
|
||||
bool _swing;
|
||||
std::function<void()> _completeCallback;
|
||||
int _displayFrame;
|
||||
|
||||
int _start;
|
||||
int _end;
|
||||
int _times;
|
||||
int _endAt;
|
||||
int _status; //0-none, 1-next loop, 2-ending, 3-ended
|
||||
|
||||
CC_DISALLOW_COPY_AND_ASSIGN(ActionMovieClip);
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,265 @@
|
|||
#ifndef __GOBJECT_H__
|
||||
#define __GOBJECT_H__
|
||||
|
||||
#include "Controller.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "Relations.h"
|
||||
#include "cocos2d.h"
|
||||
#include "event/UIEventDispatcher.h"
|
||||
#include "gears/GearBase.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GComponent;
|
||||
class GGroup;
|
||||
class ByteBuffer;
|
||||
class GRoot;
|
||||
class PackageItem;
|
||||
class GTreeNode;
|
||||
|
||||
class GObject : public UIEventDispatcher
|
||||
{
|
||||
public:
|
||||
static GObject* getDraggingObject() { return _draggingObject; }
|
||||
|
||||
GObject();
|
||||
virtual ~GObject();
|
||||
|
||||
CREATE_FUNC(GObject);
|
||||
|
||||
float getX() const { return _position.x; };
|
||||
void setX(float value);
|
||||
float getY() const { return _position.y; };
|
||||
void setY(float value);
|
||||
const cocos2d::Vec2& getPosition() const { return _position; }
|
||||
void setPosition(float xv, float yv);
|
||||
float getXMin() const;
|
||||
void setXMin(float value);
|
||||
float getYMin() const;
|
||||
void setYMin(float value);
|
||||
|
||||
bool isPixelSnapping() const { return _pixelSnapping; }
|
||||
void setPixelSnapping(bool value);
|
||||
|
||||
float getWidth() const { return _size.width; }
|
||||
void setWidth(float value) { setSize(value, _rawSize.height); }
|
||||
float getHeight() const { return _size.height; }
|
||||
void setHeight(float value) { setSize(_rawSize.width, value); }
|
||||
const cocos2d::Size& getSize() const { return _size; }
|
||||
void setSize(float wv, float hv, bool ignorePivot = false);
|
||||
|
||||
void center(bool restraint = false);
|
||||
void makeFullScreen();
|
||||
|
||||
const cocos2d::Vec2& getPivot() const { return _pivot; }
|
||||
void setPivot(float xv, float yv, bool asAnchor = false);
|
||||
bool isPivotAsAnchor() const { return _pivotAsAnchor; }
|
||||
|
||||
float getScaleX() const { return _scale.x; }
|
||||
void setScaleX(float value) { setScale(value, _scale.y); }
|
||||
float getScaleY() const { return _scale.y; }
|
||||
void setScaleY(float value) { setScale(_scale.x, value); }
|
||||
const cocos2d::Vec2& getScale() const { return _scale; }
|
||||
void setScale(float xv, float yv);
|
||||
|
||||
float getSkewX() const { return _displayObject->getSkewX(); }
|
||||
void setSkewX(float value);
|
||||
|
||||
float getSkewY() const { return _displayObject->getSkewY(); }
|
||||
void setSkewY(float value);
|
||||
|
||||
float getRotation() const { return _rotation; }
|
||||
void setRotation(float value);
|
||||
|
||||
float getAlpha() const { return _alpha; }
|
||||
void setAlpha(float value);
|
||||
|
||||
bool isGrayed() const { return _grayed; }
|
||||
void setGrayed(bool value);
|
||||
|
||||
bool isVisible() const { return _visible; }
|
||||
void setVisible(bool value);
|
||||
|
||||
bool isTouchable() const { return _touchable; }
|
||||
void setTouchable(bool value);
|
||||
|
||||
int getSortingOrder() const { return _sortingOrder; }
|
||||
void setSortingOrder(int value);
|
||||
|
||||
GGroup* getGroup() const { return _group; }
|
||||
void setGroup(GGroup* value);
|
||||
|
||||
virtual const std::string& getText() const;
|
||||
virtual void setText(const std::string& text);
|
||||
|
||||
virtual const std::string& getIcon() const;
|
||||
virtual void setIcon(const std::string& text);
|
||||
|
||||
const std::string& getTooltips() const { return _tooltips; }
|
||||
void setTooltips(const std::string& value);
|
||||
|
||||
void* getData() const { return _data; };
|
||||
void setData(void* value) { _data = value; }
|
||||
const cocos2d::Value& getCustomData() const { return _customData; }
|
||||
void setCustomData(const cocos2d::Value& value) { _customData = value; }
|
||||
|
||||
bool isDraggable() const { return _draggable; }
|
||||
void setDraggable(bool value);
|
||||
cocos2d::Rect* getDragBounds() const { return _dragBounds; }
|
||||
void setDragBounds(const cocos2d::Rect& value);
|
||||
|
||||
void startDrag(int touchId = -1);
|
||||
void stopDrag();
|
||||
|
||||
std::string getResourceURL() const;
|
||||
|
||||
PackageItem* getPackageItem() const { return _packageItem; }
|
||||
|
||||
cocos2d::Vec2 globalToLocal(const cocos2d::Vec2& pt);
|
||||
cocos2d::Rect globalToLocal(const cocos2d::Rect& rect);
|
||||
cocos2d::Vec2 localToGlobal(const cocos2d::Vec2& pt);
|
||||
cocos2d::Rect localToGlobal(const cocos2d::Rect& rect);
|
||||
cocos2d::Rect transformRect(const cocos2d::Rect& rect, GObject* targetSpace);
|
||||
|
||||
Relations* relations() { return _relations; }
|
||||
void addRelation(GObject* target, RelationType relationType, bool usePercent = false);
|
||||
void removeRelation(GObject* target, RelationType relationType);
|
||||
|
||||
GearBase* getGear(int index);
|
||||
bool checkGearController(int index, GController* c);
|
||||
uint32_t addDisplayLock();
|
||||
void releaseDisplayLock(uint32_t token);
|
||||
|
||||
GComponent* getParent() const { return _parent; }
|
||||
GObject* findParent() const;
|
||||
cocos2d::Node* displayObject() const { return _displayObject; }
|
||||
GRoot* getRoot() const;
|
||||
bool onStage() const;
|
||||
void removeFromParent();
|
||||
|
||||
void addClickListener(const EventCallback& callback) { addEventListener(UIEventType::Click, callback); }
|
||||
void addClickListener(const EventCallback& callback, const EventTag& tag) { addEventListener(UIEventType::Click, callback, tag); }
|
||||
void removeClickListener(const EventTag& tag) { removeEventListener(UIEventType::Click, tag); }
|
||||
|
||||
virtual cocos2d::Value getProp(ObjectPropID propId);
|
||||
virtual void setProp(ObjectPropID propId, const cocos2d::Value& value);
|
||||
|
||||
virtual void constructFromResource();
|
||||
virtual GObject* hitTest(const cocos2d::Vec2& worldPoint, const cocos2d::Camera* camera);
|
||||
|
||||
template <typename T>
|
||||
T* as();
|
||||
|
||||
GTreeNode* treeNode() const { return _treeNode; }
|
||||
|
||||
std::string id;
|
||||
std::string name;
|
||||
cocos2d::Size sourceSize;
|
||||
cocos2d::Size initSize;
|
||||
cocos2d::Size minSize;
|
||||
cocos2d::Size maxSize;
|
||||
|
||||
//internal use
|
||||
bool _underConstruct;
|
||||
bool _gearLocked;
|
||||
bool _alignToBL;
|
||||
|
||||
protected:
|
||||
GComponent* _parent;
|
||||
cocos2d::Node* _displayObject;
|
||||
PackageItem* _packageItem;
|
||||
int _sizeImplType;
|
||||
bool _touchDisabled;
|
||||
|
||||
virtual void handleInit();
|
||||
virtual void handleSizeChanged();
|
||||
virtual void handleScaleChanged();
|
||||
virtual void handleGrayedChanged();
|
||||
virtual void handlePositionChanged();
|
||||
virtual void handleControllerChanged(GController* c);
|
||||
virtual void handleAlphaChanged();
|
||||
virtual void handleVisibleChanged();
|
||||
|
||||
virtual void onEnter();
|
||||
virtual void onExit();
|
||||
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos);
|
||||
virtual void setup_afterAdd(ByteBuffer* buffer, int beginPos);
|
||||
|
||||
bool init();
|
||||
|
||||
void updateGear(int index);
|
||||
void checkGearDisplay();
|
||||
|
||||
void setSizeDirectly(float wv, float hv);
|
||||
|
||||
cocos2d::Vec2 _position;
|
||||
cocos2d::Size _size;
|
||||
cocos2d::Size _rawSize;
|
||||
cocos2d::Vec2 _pivot;
|
||||
cocos2d::Vec2 _scale;
|
||||
bool _pivotAsAnchor;
|
||||
float _alpha;
|
||||
float _rotation;
|
||||
bool _visible;
|
||||
bool _touchable;
|
||||
bool _grayed;
|
||||
bool _finalGrayed;
|
||||
|
||||
private:
|
||||
bool internalVisible() const;
|
||||
bool internalVisible2() const;
|
||||
bool internalVisible3() const;
|
||||
void updateGearFromRelations(int index, float dx, float dy);
|
||||
void transformRectPoint(const cocos2d::Vec2& pt, float rect[], GObject* targetSpace);
|
||||
|
||||
void initDrag();
|
||||
void dragBegin(int touchId);
|
||||
void dragEnd();
|
||||
void onTouchBegin(EventContext* context);
|
||||
void onTouchMove(EventContext* context);
|
||||
void onTouchEnd(EventContext* context);
|
||||
void onRollOver(EventContext* context);
|
||||
void onRollOut(EventContext* context);
|
||||
|
||||
bool _internalVisible;
|
||||
bool _handlingController;
|
||||
bool _draggable;
|
||||
int _sortingOrder;
|
||||
bool _focusable;
|
||||
std::string _tooltips;
|
||||
bool _pixelSnapping;
|
||||
GGroup* _group;
|
||||
float _sizePercentInGroup;
|
||||
Relations* _relations;
|
||||
GearBase* _gears[10];
|
||||
void* _data;
|
||||
cocos2d::Value _customData;
|
||||
cocos2d::Vec2 _dragTouchStartPos;
|
||||
cocos2d::Rect* _dragBounds;
|
||||
bool _dragTesting;
|
||||
GTreeNode* _treeNode;
|
||||
|
||||
uint64_t _uid;
|
||||
size_t _weakPtrRef;
|
||||
|
||||
static GObject* _draggingObject;
|
||||
|
||||
friend class GComponent;
|
||||
friend class GGroup;
|
||||
friend class RelationItem;
|
||||
friend class UIObjectFactory;
|
||||
friend class WeakPtr;
|
||||
friend class UIPackage;
|
||||
friend class GTree;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline T* GObject::as()
|
||||
{
|
||||
return dynamic_cast<T*>(this);
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
#include "GObjectPool.h"
|
||||
#include "GObject.h"
|
||||
#include "UIPackage.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GObjectPool::GObjectPool()
|
||||
{
|
||||
}
|
||||
|
||||
GObjectPool::~GObjectPool()
|
||||
{
|
||||
}
|
||||
|
||||
GObject* GObjectPool::getObject(const std::string & url)
|
||||
{
|
||||
std::string url2 = UIPackage::normalizeURL(url);
|
||||
if (url2.length() == 0)
|
||||
return nullptr;
|
||||
|
||||
GObject* ret;
|
||||
Vector<GObject*>& arr = _pool[url2];
|
||||
if (!arr.empty())
|
||||
{
|
||||
ret = arr.back();
|
||||
ret->retain();
|
||||
arr.popBack();
|
||||
ret->autorelease();
|
||||
}
|
||||
else
|
||||
ret = UIPackage::createObjectFromURL(url2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GObjectPool::returnObject(GObject* obj)
|
||||
{
|
||||
_pool[obj->getResourceURL()].pushBack(obj);
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef __GOBJECTPOOL_H__
|
||||
#define __GOBJECTPOOL_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GObject;
|
||||
|
||||
class GObjectPool
|
||||
{
|
||||
public:
|
||||
GObjectPool();
|
||||
~GObjectPool();
|
||||
|
||||
GObject* getObject(const std::string& url);
|
||||
void returnObject(GObject* obj);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, cocos2d::Vector<GObject*>> _pool;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,234 @@
|
|||
#include "GProgressBar.h"
|
||||
#include "GImage.h"
|
||||
#include "GLoader.h"
|
||||
#include "PackageItem.h"
|
||||
#include "tween/GTween.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GProgressBar::GProgressBar()
|
||||
: _min(0),
|
||||
_max(100),
|
||||
_value(0),
|
||||
_titleType(ProgressTitleType::PERCENT),
|
||||
_titleObject(nullptr),
|
||||
_barObjectH(nullptr),
|
||||
_barObjectV(nullptr),
|
||||
_barMaxWidth(0),
|
||||
_barMaxHeight(0),
|
||||
_barMaxWidthDelta(0),
|
||||
_barMaxHeightDelta(0),
|
||||
_barStartX(0),
|
||||
_barStartY(0)
|
||||
{
|
||||
}
|
||||
|
||||
GProgressBar::~GProgressBar()
|
||||
{
|
||||
}
|
||||
|
||||
void GProgressBar::setTitleType(ProgressTitleType value)
|
||||
{
|
||||
if (_titleType != value)
|
||||
{
|
||||
_titleType = value;
|
||||
update(_value);
|
||||
}
|
||||
}
|
||||
|
||||
void GProgressBar::setMin(double value)
|
||||
{
|
||||
if (_min != value)
|
||||
{
|
||||
_min = value;
|
||||
update(_value);
|
||||
}
|
||||
}
|
||||
|
||||
void GProgressBar::setMax(double value)
|
||||
{
|
||||
if (_max != value)
|
||||
{
|
||||
_max = value;
|
||||
update(_value);
|
||||
}
|
||||
}
|
||||
|
||||
void GProgressBar::setValue(double value)
|
||||
{
|
||||
if (_value != value)
|
||||
{
|
||||
GTween::kill(this, TweenPropType::Progress, false);
|
||||
|
||||
_value = value;
|
||||
update(_value);
|
||||
}
|
||||
}
|
||||
|
||||
void GProgressBar::tweenValue(double value, float duration)
|
||||
{
|
||||
double oldValule;
|
||||
|
||||
GTweener* twener = GTween::getTween(this, TweenPropType::Progress);
|
||||
if (twener != nullptr)
|
||||
{
|
||||
oldValule = twener->value.d;
|
||||
twener->kill(false);
|
||||
}
|
||||
else
|
||||
oldValule = _value;
|
||||
|
||||
_value = value;
|
||||
GTween::toDouble(oldValule, _value, duration)
|
||||
->setEase(EaseType::Linear)
|
||||
->setTarget(this, TweenPropType::Progress);
|
||||
}
|
||||
|
||||
void GProgressBar::update(double newValue)
|
||||
{
|
||||
float percent;
|
||||
if (_max == _min)
|
||||
percent = 0;
|
||||
else
|
||||
percent = clampf((newValue - _min) / (_max - _min), 0, 1);
|
||||
|
||||
if (_titleObject != nullptr)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
switch (_titleType)
|
||||
{
|
||||
case ProgressTitleType::PERCENT:
|
||||
oss << floor(percent * 100) << "%";
|
||||
break;
|
||||
|
||||
case ProgressTitleType::VALUE_MAX:
|
||||
oss << floor(newValue) << "/" << floor(_max);
|
||||
break;
|
||||
|
||||
case ProgressTitleType::VALUE:
|
||||
oss << floor(newValue);
|
||||
break;
|
||||
|
||||
case ProgressTitleType::MAX:
|
||||
oss << floor(_max);
|
||||
break;
|
||||
}
|
||||
_titleObject->setText(oss.str());
|
||||
}
|
||||
|
||||
float fullWidth = this->getWidth() - _barMaxWidthDelta;
|
||||
float fullHeight = this->getHeight() - _barMaxHeightDelta;
|
||||
if (!_reverse)
|
||||
{
|
||||
if (_barObjectH != nullptr)
|
||||
{
|
||||
if (!setFillAmount(_barObjectH, percent))
|
||||
_barObjectH->setWidth(round(fullWidth * percent));
|
||||
}
|
||||
if (_barObjectV != nullptr)
|
||||
{
|
||||
if (!setFillAmount(_barObjectV, percent))
|
||||
_barObjectV->setHeight(round(fullHeight * percent));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_barObjectH != nullptr)
|
||||
{
|
||||
if (!setFillAmount(_barObjectH, 1 - percent))
|
||||
{
|
||||
_barObjectH->setWidth(round(fullWidth * percent));
|
||||
_barObjectH->setX(_barStartX + (fullWidth - _barObjectH->getWidth()));
|
||||
}
|
||||
}
|
||||
if (_barObjectV != nullptr)
|
||||
{
|
||||
if (!setFillAmount(_barObjectV, 1 - percent))
|
||||
{
|
||||
_barObjectV->setHeight(round(fullHeight * percent));
|
||||
_barObjectV->setY(_barStartY + (fullHeight - _barObjectV->getHeight()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GProgressBar::setFillAmount(GObject* bar, float amount)
|
||||
{
|
||||
GImage* image = nullptr;
|
||||
GLoader* loader = nullptr;
|
||||
|
||||
if ((image = dynamic_cast<GImage*>(bar)) != nullptr && image->getFillMethod() != FillMethod::None)
|
||||
image->setFillAmount(amount);
|
||||
else if ((loader = dynamic_cast<GLoader*>(bar)) != nullptr && loader->getFillMethod() != FillMethod::None)
|
||||
loader->setFillAmount(amount);
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GProgressBar::handleSizeChanged()
|
||||
{
|
||||
GComponent::handleSizeChanged();
|
||||
|
||||
if (_barObjectH != nullptr)
|
||||
_barMaxWidth = getWidth() - _barMaxWidthDelta;
|
||||
if (_barObjectV != nullptr)
|
||||
_barMaxHeight = getHeight() - _barMaxHeightDelta;
|
||||
|
||||
if (!_underConstruct)
|
||||
update(_value);
|
||||
}
|
||||
|
||||
void GProgressBar::constructExtension(ByteBuffer* buffer)
|
||||
{
|
||||
buffer->seek(0, 6);
|
||||
|
||||
_titleType = (ProgressTitleType)buffer->readByte();
|
||||
_reverse = buffer->readBool();
|
||||
|
||||
_titleObject = getChild("title");
|
||||
_barObjectH = getChild("bar");
|
||||
_barObjectV = getChild("bar_v");
|
||||
|
||||
if (_barObjectH != nullptr)
|
||||
{
|
||||
_barMaxWidth = _barObjectH->getWidth();
|
||||
_barMaxWidthDelta = getWidth() - _barMaxWidth;
|
||||
_barStartX = _barObjectH->getX();
|
||||
}
|
||||
if (_barObjectV != nullptr)
|
||||
{
|
||||
_barMaxHeight = _barObjectV->getHeight();
|
||||
_barMaxHeightDelta = getHeight() - _barMaxHeight;
|
||||
_barStartY = _barObjectV->getY();
|
||||
}
|
||||
}
|
||||
|
||||
void GProgressBar::setup_afterAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GComponent::setup_afterAdd(buffer, beginPos);
|
||||
|
||||
if (!buffer->seek(beginPos, 6))
|
||||
{
|
||||
update(_value);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ObjectType)buffer->readByte() != _packageItem->objectType)
|
||||
{
|
||||
update(_value);
|
||||
return;
|
||||
}
|
||||
|
||||
_value = buffer->readInt();
|
||||
_max = buffer->readInt();
|
||||
if (buffer->version >= 2)
|
||||
_min = buffer->readInt();
|
||||
|
||||
update(_value);
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef __GPROGRESSBAR_H__
|
||||
#define __GPROGRESSBAR_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GComponent.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GProgressBar : public GComponent
|
||||
{
|
||||
public:
|
||||
GProgressBar();
|
||||
virtual ~GProgressBar();
|
||||
|
||||
CREATE_FUNC(GProgressBar);
|
||||
|
||||
ProgressTitleType getTitleType() const { return _titleType; }
|
||||
void setTitleType(ProgressTitleType value);
|
||||
|
||||
double getMin() const { return _min; }
|
||||
void setMin(double value);
|
||||
|
||||
double getMax() const { return _max; }
|
||||
void setMax(double value);
|
||||
|
||||
double getValue() const { return _value; }
|
||||
void setValue(double value);
|
||||
|
||||
void tweenValue(double value, float duration);
|
||||
void update(double newValue);
|
||||
|
||||
protected:
|
||||
virtual void handleSizeChanged() override;
|
||||
virtual void constructExtension(ByteBuffer* buffer) override;
|
||||
virtual void setup_afterAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
|
||||
bool setFillAmount(GObject* bar, float amount);
|
||||
|
||||
private:
|
||||
double _min;
|
||||
double _max;
|
||||
double _value;
|
||||
ProgressTitleType _titleType;
|
||||
bool _reverse;
|
||||
|
||||
GObject* _titleObject;
|
||||
GObject* _barObjectH;
|
||||
GObject* _barObjectV;
|
||||
float _barMaxWidth;
|
||||
float _barMaxHeight;
|
||||
float _barMaxWidthDelta;
|
||||
float _barMaxHeightDelta;
|
||||
float _barStartX;
|
||||
float _barStartY;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,114 @@
|
|||
#include "GRichTextField.h"
|
||||
#include "utils/UBBParser.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GRichTextField::GRichTextField() :
|
||||
_richText(nullptr),
|
||||
_updatingSize(false)
|
||||
{
|
||||
}
|
||||
|
||||
GRichTextField::~GRichTextField()
|
||||
{
|
||||
}
|
||||
|
||||
void GRichTextField::handleInit()
|
||||
{
|
||||
_richText = FUIRichText::create();
|
||||
_richText->retain();
|
||||
_richText->setCascadeOpacityEnabled(true);
|
||||
|
||||
_displayObject = _richText;
|
||||
}
|
||||
|
||||
void GRichTextField::applyTextFormat()
|
||||
{
|
||||
_richText->applyTextFormat();
|
||||
updateGear(4);
|
||||
if (!_underConstruct)
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void GRichTextField::setAutoSize(AutoSizeType value)
|
||||
{
|
||||
_autoSize = value;
|
||||
switch (value)
|
||||
{
|
||||
case AutoSizeType::NONE:
|
||||
_richText->setOverflow(Label::Overflow::CLAMP);
|
||||
break;
|
||||
case AutoSizeType::BOTH:
|
||||
_richText->setOverflow(Label::Overflow::NONE);
|
||||
break;
|
||||
case AutoSizeType::HEIGHT:
|
||||
_richText->setOverflow(Label::Overflow::RESIZE_HEIGHT);
|
||||
break;
|
||||
case AutoSizeType::SHRINK:
|
||||
_richText->setOverflow(Label::Overflow::SHRINK);
|
||||
break;
|
||||
}
|
||||
|
||||
_richText->setDimensions(_size.width, _size.height);
|
||||
if (!_underConstruct)
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void GRichTextField::setSingleLine(bool value)
|
||||
{
|
||||
}
|
||||
|
||||
void GRichTextField::setTextFieldText()
|
||||
{
|
||||
if (_ubbEnabled)
|
||||
{
|
||||
std::string parsedText = UBBParser::getInstance()->parse(_text.c_str());
|
||||
if (_templateVars != nullptr)
|
||||
parsedText = parseTemplate(parsedText.c_str());
|
||||
_richText->setText(parsedText);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_templateVars != nullptr)
|
||||
_richText->setText(parseTemplate(_text.c_str()));
|
||||
else
|
||||
_richText->setText(_text);
|
||||
}
|
||||
}
|
||||
|
||||
void GRichTextField::updateSize()
|
||||
{
|
||||
if (_updatingSize)
|
||||
return;
|
||||
|
||||
_updatingSize = true;
|
||||
|
||||
Size sz = _richText->getContentSize();
|
||||
if (_autoSize == AutoSizeType::BOTH)
|
||||
setSize(sz.width, sz.height);
|
||||
else if (_autoSize == AutoSizeType::HEIGHT)
|
||||
setHeight(sz.height);
|
||||
|
||||
_updatingSize = false;
|
||||
}
|
||||
|
||||
void GRichTextField::handleSizeChanged()
|
||||
{
|
||||
if (_updatingSize)
|
||||
return;
|
||||
|
||||
if (_autoSize != AutoSizeType::BOTH)
|
||||
{
|
||||
_richText->setDimensions(_size.width, _size.height);
|
||||
|
||||
if (_autoSize == AutoSizeType::HEIGHT)
|
||||
{
|
||||
if (!_text.empty())
|
||||
setSizeDirectly(_size.width, _richText->getContentSize().height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef __GRICHTEXTFIELD_H__
|
||||
#define __GRICHTEXTFIELD_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GTextField.h"
|
||||
#include "display/FUIRichText.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GRichTextField : public GTextField
|
||||
{
|
||||
public:
|
||||
GRichTextField();
|
||||
virtual ~GRichTextField();
|
||||
|
||||
CREATE_FUNC(GRichTextField);
|
||||
|
||||
virtual void setAutoSize(AutoSizeType value) override;
|
||||
|
||||
virtual bool isSingleLine() const override { return false; }
|
||||
virtual void setSingleLine(bool value) override;
|
||||
|
||||
virtual TextFormat* getTextFormat() const override { return _richText->getTextFormat(); }
|
||||
virtual void applyTextFormat() override;
|
||||
|
||||
protected:
|
||||
virtual void handleInit() override;
|
||||
virtual void handleSizeChanged() override;
|
||||
|
||||
virtual void setTextFieldText() override;
|
||||
virtual void updateSize() override;
|
||||
|
||||
private:
|
||||
FUIRichText* _richText;
|
||||
bool _updatingSize;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,569 @@
|
|||
#include "GRoot.h"
|
||||
#include "AudioEngine.h"
|
||||
#include "UIConfig.h"
|
||||
#include "UIPackage.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
#if COCOS2D_VERSION < 0x00040000
|
||||
using namespace cocos2d::experimental;
|
||||
#endif
|
||||
|
||||
GRoot* GRoot::_inst = nullptr;
|
||||
bool GRoot::_soundEnabled = true;
|
||||
float GRoot::_soundVolumeScale = 1.0f;
|
||||
int GRoot::contentScaleLevel = 0;
|
||||
|
||||
GRoot* GRoot::create(Scene* scene, int zOrder)
|
||||
{
|
||||
GRoot* pRet = new (std::nothrow) GRoot();
|
||||
if (pRet && pRet->initWithScene(scene, zOrder))
|
||||
{
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete pRet;
|
||||
pRet = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
GRoot::GRoot() : _windowSizeListener(nullptr),
|
||||
_inputProcessor(nullptr),
|
||||
_modalLayer(nullptr),
|
||||
_modalWaitPane(nullptr),
|
||||
_tooltipWin(nullptr),
|
||||
_defaultTooltipWin(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
GRoot::~GRoot()
|
||||
{
|
||||
delete _inputProcessor;
|
||||
CC_SAFE_RELEASE(_modalWaitPane);
|
||||
CC_SAFE_RELEASE(_defaultTooltipWin);
|
||||
CC_SAFE_RELEASE(_modalLayer);
|
||||
CALL_LATER_CANCEL(GRoot, doShowTooltipsWin);
|
||||
|
||||
if (_windowSizeListener)
|
||||
Director::getInstance()->getEventDispatcher()->removeEventListener(_windowSizeListener);
|
||||
}
|
||||
|
||||
void GRoot::showWindow(Window* win)
|
||||
{
|
||||
addChild(win);
|
||||
adjustModalLayer();
|
||||
}
|
||||
|
||||
void GRoot::hideWindow(Window* win)
|
||||
{
|
||||
win->hide();
|
||||
}
|
||||
|
||||
void GRoot::hideWindowImmediately(Window* win)
|
||||
{
|
||||
if (win->getParent() == this)
|
||||
removeChild(win);
|
||||
|
||||
adjustModalLayer();
|
||||
}
|
||||
|
||||
void GRoot::bringToFront(Window* win)
|
||||
{
|
||||
int cnt = numChildren();
|
||||
int i;
|
||||
if (_modalLayer->getParent() != nullptr && !win->isModal())
|
||||
i = getChildIndex(_modalLayer) - 1;
|
||||
else
|
||||
i = cnt - 1;
|
||||
|
||||
for (; i >= 0; i--)
|
||||
{
|
||||
GObject* g = getChildAt(i);
|
||||
if (g == win)
|
||||
return;
|
||||
if (dynamic_cast<Window*>(g))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= 0)
|
||||
setChildIndex(win, i);
|
||||
}
|
||||
|
||||
void GRoot::closeAllExceptModals()
|
||||
{
|
||||
Vector<GObject*> map(_children);
|
||||
|
||||
for (const auto& child : map)
|
||||
{
|
||||
if (dynamic_cast<Window*>(child) && !((Window*)child)->isModal())
|
||||
hideWindowImmediately((Window*)child);
|
||||
}
|
||||
}
|
||||
|
||||
void GRoot::closeAllWindows()
|
||||
{
|
||||
Vector<GObject*> map(_children);
|
||||
|
||||
for (const auto& child : map)
|
||||
{
|
||||
if (dynamic_cast<Window*>(child))
|
||||
hideWindowImmediately((Window*)child);
|
||||
}
|
||||
}
|
||||
|
||||
Window* GRoot::getTopWindow()
|
||||
{
|
||||
int cnt = numChildren();
|
||||
for (int i = cnt - 1; i >= 0; i--)
|
||||
{
|
||||
GObject* child = getChildAt(i);
|
||||
if (dynamic_cast<Window*>(child))
|
||||
{
|
||||
return (Window*)child;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GGraph* GRoot::getModalLayer()
|
||||
{
|
||||
if (_modalLayer == nullptr)
|
||||
createModalLayer();
|
||||
|
||||
return _modalLayer;
|
||||
}
|
||||
|
||||
void GRoot::createModalLayer()
|
||||
{
|
||||
_modalLayer = GGraph::create();
|
||||
_modalLayer->retain();
|
||||
_modalLayer->drawRect(getWidth(), getHeight(), 0, Color4F::WHITE, UIConfig::modalLayerColor);
|
||||
_modalLayer->addRelation(this, RelationType::Size);
|
||||
}
|
||||
|
||||
void GRoot::adjustModalLayer()
|
||||
{
|
||||
if (_modalLayer == nullptr)
|
||||
createModalLayer();
|
||||
|
||||
int cnt = numChildren();
|
||||
|
||||
if (_modalWaitPane != nullptr && _modalWaitPane->getParent() != nullptr)
|
||||
setChildIndex(_modalWaitPane, cnt - 1);
|
||||
|
||||
for (int i = cnt - 1; i >= 0; i--)
|
||||
{
|
||||
GObject* child = getChildAt(i);
|
||||
if (dynamic_cast<Window*>(child) && ((Window*)child)->isModal())
|
||||
{
|
||||
if (_modalLayer->getParent() == nullptr)
|
||||
addChildAt(_modalLayer, i);
|
||||
else
|
||||
setChildIndexBefore(_modalLayer, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_modalLayer->getParent() != nullptr)
|
||||
removeChild(_modalLayer);
|
||||
}
|
||||
|
||||
bool GRoot::hasModalWindow()
|
||||
{
|
||||
return _modalLayer != nullptr && _modalLayer->getParent() != nullptr;
|
||||
}
|
||||
|
||||
void GRoot::showModalWait()
|
||||
{
|
||||
getModalWaitingPane();
|
||||
if (_modalWaitPane)
|
||||
addChild(_modalWaitPane);
|
||||
}
|
||||
|
||||
void GRoot::closeModalWait()
|
||||
{
|
||||
if (_modalWaitPane != nullptr && _modalWaitPane->getParent() != nullptr)
|
||||
removeChild(_modalWaitPane);
|
||||
}
|
||||
|
||||
GObject* GRoot::getModalWaitingPane()
|
||||
{
|
||||
if (!UIConfig::globalModalWaiting.empty())
|
||||
{
|
||||
if (_modalWaitPane == nullptr)
|
||||
{
|
||||
_modalWaitPane = UIPackage::createObjectFromURL(UIConfig::globalModalWaiting);
|
||||
_modalWaitPane->setSortingOrder(INT_MAX);
|
||||
_modalWaitPane->retain();
|
||||
}
|
||||
|
||||
_modalWaitPane->setSize(getWidth(), getHeight());
|
||||
_modalWaitPane->addRelation(this, RelationType::Size);
|
||||
|
||||
return _modalWaitPane;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool GRoot::isModalWaiting()
|
||||
{
|
||||
return (_modalWaitPane != nullptr) && _modalWaitPane->onStage();
|
||||
}
|
||||
|
||||
cocos2d::Vec2 GRoot::getTouchPosition(int touchId)
|
||||
{
|
||||
return _inputProcessor->getTouchPosition(touchId);
|
||||
}
|
||||
|
||||
GObject* GRoot::getTouchTarget()
|
||||
{
|
||||
return _inputProcessor->getRecentInput()->getTarget();
|
||||
}
|
||||
|
||||
cocos2d::Vec2 GRoot::worldToRoot(const cocos2d::Vec2 &pt)
|
||||
{
|
||||
cocos2d::Vec2 pos = _displayObject->convertToNodeSpace(pt);
|
||||
pos.y = getHeight() - pos.y;
|
||||
return pos;
|
||||
}
|
||||
|
||||
cocos2d::Vec2 GRoot::rootToWorld(const cocos2d::Vec2 &pt)
|
||||
{
|
||||
cocos2d::Vec2 pos = pt;
|
||||
pos.y = getHeight() - pos.y;
|
||||
pos = _displayObject->convertToWorldSpace(pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
void GRoot::showPopup(GObject* popup)
|
||||
{
|
||||
showPopup(popup, nullptr, PopupDirection::AUTO);
|
||||
}
|
||||
|
||||
void GRoot::showPopup(GObject* popup, GObject* target, PopupDirection dir)
|
||||
{
|
||||
if (!_popupStack.empty())
|
||||
hidePopup(popup);
|
||||
|
||||
_popupStack.push_back(WeakPtr(popup));
|
||||
|
||||
if (target != nullptr)
|
||||
{
|
||||
GObject* p = target;
|
||||
while (p != nullptr)
|
||||
{
|
||||
if (p->getParent() == this)
|
||||
{
|
||||
if (popup->getSortingOrder() < p->getSortingOrder())
|
||||
{
|
||||
popup->setSortingOrder(p->getSortingOrder());
|
||||
}
|
||||
break;
|
||||
}
|
||||
p = p->getParent();
|
||||
}
|
||||
}
|
||||
|
||||
addChild(popup);
|
||||
adjustModalLayer();
|
||||
|
||||
if (dynamic_cast<Window*>(popup) && target == nullptr && dir == PopupDirection::AUTO)
|
||||
return;
|
||||
|
||||
Vec2 pos = getPoupPosition(popup, target, dir);
|
||||
popup->setPosition(pos.x, pos.y);
|
||||
}
|
||||
|
||||
void GRoot::togglePopup(GObject* popup)
|
||||
{
|
||||
togglePopup(popup, nullptr, PopupDirection::AUTO);
|
||||
}
|
||||
|
||||
void GRoot::togglePopup(GObject* popup, GObject* target, PopupDirection dir)
|
||||
{
|
||||
if (std::find(_justClosedPopups.cbegin(), _justClosedPopups.cend(), popup) != _justClosedPopups.cend())
|
||||
return;
|
||||
|
||||
showPopup(popup, target, dir);
|
||||
}
|
||||
|
||||
void GRoot::hidePopup()
|
||||
{
|
||||
hidePopup(nullptr);
|
||||
}
|
||||
|
||||
void GRoot::hidePopup(GObject* popup)
|
||||
{
|
||||
if (popup != nullptr)
|
||||
{
|
||||
auto it = std::find(_popupStack.cbegin(), _popupStack.cend(), popup);
|
||||
if (it != _popupStack.cend())
|
||||
{
|
||||
int k = (int)(it - _popupStack.cbegin());
|
||||
for (int i = (int)_popupStack.size() - 1; i >= k; i--)
|
||||
{
|
||||
closePopup(_popupStack.back().ptr());
|
||||
_popupStack.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& it : _popupStack)
|
||||
closePopup(it.ptr());
|
||||
_popupStack.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void GRoot::closePopup(GObject* target)
|
||||
{
|
||||
if (target && target->getParent() != nullptr)
|
||||
{
|
||||
if (dynamic_cast<Window*>(target))
|
||||
((Window*)target)->hide();
|
||||
else
|
||||
removeChild(target);
|
||||
}
|
||||
}
|
||||
|
||||
void GRoot::checkPopups()
|
||||
{
|
||||
_justClosedPopups.clear();
|
||||
if (!_popupStack.empty())
|
||||
{
|
||||
GObject* mc = _inputProcessor->getRecentInput()->getTarget();
|
||||
bool handled = false;
|
||||
while (mc != this && mc != nullptr)
|
||||
{
|
||||
auto it = std::find(_popupStack.cbegin(), _popupStack.cend(), mc);
|
||||
if (it != _popupStack.cend())
|
||||
{
|
||||
int k = (int)(it - _popupStack.cbegin());
|
||||
for (int i = (int)_popupStack.size() - 1; i > k; i--)
|
||||
{
|
||||
closePopup(_popupStack.back().ptr());
|
||||
_popupStack.pop_back();
|
||||
}
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
mc = mc->findParent();
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
for (int i = (int)_popupStack.size() - 1; i >= 0; i--)
|
||||
{
|
||||
GObject* popup = _popupStack[i].ptr();
|
||||
if (popup)
|
||||
{
|
||||
_justClosedPopups.push_back(WeakPtr(popup));
|
||||
closePopup(popup);
|
||||
}
|
||||
}
|
||||
_popupStack.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GRoot::hasAnyPopup()
|
||||
{
|
||||
return !_popupStack.empty();
|
||||
}
|
||||
|
||||
cocos2d::Vec2 GRoot::getPoupPosition(GObject* popup, GObject* target, PopupDirection dir)
|
||||
{
|
||||
Vec2 pos;
|
||||
Vec2 size;
|
||||
if (target != nullptr)
|
||||
{
|
||||
pos = target->localToGlobal(Vec2::ZERO);
|
||||
pos = this->globalToLocal(pos);
|
||||
size = target->localToGlobal(target->getSize());
|
||||
size = this->globalToLocal(size);
|
||||
size -= pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = globalToLocal(_inputProcessor->getRecentInput()->getPosition());
|
||||
}
|
||||
float xx, yy;
|
||||
xx = pos.x;
|
||||
if (xx + popup->getWidth() > getWidth())
|
||||
xx = xx + size.x - popup->getWidth();
|
||||
yy = pos.y + size.y;
|
||||
if ((dir == PopupDirection::AUTO && yy + popup->getHeight() > getHeight()) || dir == PopupDirection::UP)
|
||||
{
|
||||
yy = pos.y - popup->getHeight() - 1;
|
||||
if (yy < 0)
|
||||
{
|
||||
yy = 0;
|
||||
xx += size.x / 2;
|
||||
}
|
||||
}
|
||||
|
||||
return Vec2(round(xx), round(yy));
|
||||
}
|
||||
|
||||
void GRoot::showTooltips(const std::string& msg)
|
||||
{
|
||||
if (_defaultTooltipWin == nullptr)
|
||||
{
|
||||
const std::string& resourceURL = UIConfig::tooltipsWin;
|
||||
if (resourceURL.empty())
|
||||
{
|
||||
CCLOGWARN("FairyGUI: UIConfig.tooltipsWin not defined");
|
||||
return;
|
||||
}
|
||||
|
||||
_defaultTooltipWin = UIPackage::createObjectFromURL(resourceURL);
|
||||
_defaultTooltipWin->setTouchable(false);
|
||||
_defaultTooltipWin->retain();
|
||||
}
|
||||
|
||||
_defaultTooltipWin->setText(msg);
|
||||
showTooltipsWin(_defaultTooltipWin);
|
||||
}
|
||||
|
||||
void GRoot::showTooltipsWin(GObject* tooltipWin)
|
||||
{
|
||||
hideTooltips();
|
||||
|
||||
_tooltipWin = tooltipWin;
|
||||
CALL_LATER(GRoot, doShowTooltipsWin, 0.1f);
|
||||
}
|
||||
|
||||
void GRoot::doShowTooltipsWin()
|
||||
{
|
||||
if (_tooltipWin == nullptr)
|
||||
return;
|
||||
|
||||
Vec2 pt = _inputProcessor->getRecentInput()->getPosition();
|
||||
float xx = pt.x + 10;
|
||||
float yy = pt.y + 20;
|
||||
|
||||
pt = globalToLocal(Vec2(xx, yy));
|
||||
xx = pt.x;
|
||||
yy = pt.y;
|
||||
|
||||
if (xx + _tooltipWin->getWidth() > getWidth())
|
||||
xx = xx - _tooltipWin->getWidth();
|
||||
if (yy + _tooltipWin->getHeight() > getHeight())
|
||||
{
|
||||
yy = yy - _tooltipWin->getHeight() - 1;
|
||||
if (yy < 0)
|
||||
yy = 0;
|
||||
}
|
||||
|
||||
_tooltipWin->setPosition(round(xx), round(yy));
|
||||
addChild(_tooltipWin);
|
||||
}
|
||||
|
||||
void GRoot::hideTooltips()
|
||||
{
|
||||
if (_tooltipWin != nullptr)
|
||||
{
|
||||
if (_tooltipWin->getParent() != nullptr)
|
||||
removeChild(_tooltipWin);
|
||||
_tooltipWin = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GRoot::playSound(const std::string& url, float volumnScale)
|
||||
{
|
||||
if (!_soundEnabled)
|
||||
return;
|
||||
|
||||
PackageItem* pi = UIPackage::getItemByURL(url);
|
||||
if (pi)
|
||||
AudioEngine::play2d(pi->file, false, _soundVolumeScale * volumnScale);
|
||||
}
|
||||
|
||||
void GRoot::setSoundEnabled(bool value)
|
||||
{
|
||||
_soundEnabled = value;
|
||||
}
|
||||
|
||||
void GRoot::setSoundVolumeScale(float value)
|
||||
{
|
||||
_soundVolumeScale = value;
|
||||
}
|
||||
|
||||
void GRoot::onTouchEvent(int eventType)
|
||||
{
|
||||
if (eventType == UIEventType::TouchBegin)
|
||||
{
|
||||
if (_tooltipWin != nullptr)
|
||||
hideTooltips();
|
||||
|
||||
checkPopups();
|
||||
}
|
||||
}
|
||||
|
||||
void GRoot::handlePositionChanged()
|
||||
{
|
||||
_displayObject->setPosition(0, _size.height);
|
||||
}
|
||||
|
||||
void GRoot::onEnter()
|
||||
{
|
||||
GComponent::onEnter();
|
||||
_inst = this;
|
||||
}
|
||||
|
||||
void GRoot::onExit()
|
||||
{
|
||||
GComponent::onExit();
|
||||
if (_inst == this)
|
||||
_inst = nullptr;
|
||||
}
|
||||
|
||||
bool GRoot::initWithScene(cocos2d::Scene* scene, int zOrder)
|
||||
{
|
||||
if (!GComponent::init())
|
||||
return false;
|
||||
|
||||
if (_inst == nullptr)
|
||||
_inst = this;
|
||||
|
||||
_inputProcessor = new InputProcessor(this);
|
||||
_inputProcessor->setCaptureCallback(CC_CALLBACK_1(GRoot::onTouchEvent, this));
|
||||
|
||||
#ifdef CC_PLATFORM_PC
|
||||
_windowSizeListener = Director::getInstance()->getEventDispatcher()->addCustomEventListener(GLViewImpl::EVENT_WINDOW_RESIZED, CC_CALLBACK_0(GRoot::onWindowSizeChanged, this));
|
||||
#endif
|
||||
onWindowSizeChanged();
|
||||
|
||||
scene->addChild(_displayObject, zOrder);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GRoot::onWindowSizeChanged()
|
||||
{
|
||||
const cocos2d::Size& rs = Director::getInstance()->getOpenGLView()->getDesignResolutionSize();
|
||||
setSize(rs.width, rs.height);
|
||||
|
||||
updateContentScaleLevel();
|
||||
}
|
||||
|
||||
void GRoot::updateContentScaleLevel()
|
||||
{
|
||||
float ss = Director::getInstance()->getContentScaleFactor();
|
||||
if (ss >= 3.5f)
|
||||
contentScaleLevel = 3; //x4
|
||||
else if (ss >= 2.5f)
|
||||
contentScaleLevel = 2; //x3
|
||||
else if (ss >= 1.5f)
|
||||
contentScaleLevel = 1; //x2
|
||||
else
|
||||
contentScaleLevel = 0;
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,102 @@
|
|||
#ifndef __GROOT_H__
|
||||
#define __GROOT_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GComponent.h"
|
||||
#include "GGraph.h"
|
||||
#include "Window.h"
|
||||
#include "cocos2d.h"
|
||||
#include "event/InputProcessor.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class WeakPtr;
|
||||
|
||||
class GRoot : public GComponent
|
||||
{
|
||||
public:
|
||||
GRoot();
|
||||
virtual ~GRoot();
|
||||
|
||||
static GRoot* create(cocos2d::Scene* scene, int zOrder = 1000);
|
||||
static GRoot* getInstance() { return _inst; }
|
||||
|
||||
void showWindow(Window* win);
|
||||
void hideWindow(Window* win);
|
||||
void hideWindowImmediately(Window* win);
|
||||
void bringToFront(Window* win);
|
||||
void showModalWait();
|
||||
void closeModalWait();
|
||||
void closeAllExceptModals();
|
||||
void closeAllWindows();
|
||||
Window* getTopWindow();
|
||||
|
||||
GObject* getModalWaitingPane();
|
||||
GGraph* getModalLayer();
|
||||
bool hasModalWindow();
|
||||
bool isModalWaiting();
|
||||
|
||||
InputProcessor* getInputProcessor() const { return _inputProcessor; }
|
||||
cocos2d::Vec2 getTouchPosition(int touchId);
|
||||
GObject* getTouchTarget();
|
||||
|
||||
cocos2d::Vec2 worldToRoot(const cocos2d::Vec2 &pt);
|
||||
cocos2d::Vec2 rootToWorld(const cocos2d::Vec2 &pt);
|
||||
|
||||
void showPopup(GObject* popup);
|
||||
void showPopup(GObject* popup, GObject* target, PopupDirection dir);
|
||||
void togglePopup(GObject* popup);
|
||||
void togglePopup(GObject* popup, GObject* target, PopupDirection dir);
|
||||
void hidePopup();
|
||||
void hidePopup(GObject* popup);
|
||||
bool hasAnyPopup();
|
||||
cocos2d::Vec2 getPoupPosition(GObject* popup, GObject* target, PopupDirection dir);
|
||||
|
||||
void showTooltips(const std::string& msg);
|
||||
void showTooltipsWin(GObject* tooltipWin);
|
||||
void hideTooltips();
|
||||
|
||||
void playSound(const std::string& url, float volumeScale = 1);
|
||||
bool isSoundEnabled() const { return _soundEnabled; }
|
||||
void setSoundEnabled(bool value);
|
||||
float getSoundVolumeScale() const { return _soundVolumeScale; }
|
||||
void setSoundVolumeScale(float value);
|
||||
|
||||
static int contentScaleLevel;
|
||||
|
||||
protected:
|
||||
virtual void handlePositionChanged() override;
|
||||
virtual void onEnter() override;
|
||||
virtual void onExit() override;
|
||||
|
||||
private:
|
||||
bool initWithScene(cocos2d::Scene* scene, int zOrder);
|
||||
void onWindowSizeChanged();
|
||||
void createModalLayer();
|
||||
void adjustModalLayer();
|
||||
void closePopup(GObject* target);
|
||||
void checkPopups();
|
||||
void onTouchEvent(int eventType);
|
||||
void updateContentScaleLevel();
|
||||
|
||||
CALL_LATER_FUNC(GRoot, doShowTooltipsWin);
|
||||
|
||||
cocos2d::EventListener* _windowSizeListener;
|
||||
InputProcessor* _inputProcessor;
|
||||
|
||||
GGraph* _modalLayer;
|
||||
GObject* _modalWaitPane;
|
||||
std::vector<WeakPtr> _popupStack;
|
||||
std::vector<WeakPtr> _justClosedPopups;
|
||||
GObject* _tooltipWin;
|
||||
GObject* _defaultTooltipWin;
|
||||
|
||||
static bool _soundEnabled;
|
||||
static float _soundVolumeScale;
|
||||
|
||||
static GRoot* _inst;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,179 @@
|
|||
#include "GScrollBar.h"
|
||||
#include "PackageItem.h"
|
||||
#include "ScrollPane.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GScrollBar::GScrollBar()
|
||||
: _grip(nullptr),
|
||||
_arrowButton1(nullptr),
|
||||
_arrowButton2(nullptr),
|
||||
_bar(nullptr),
|
||||
_target(nullptr),
|
||||
_vertical(false),
|
||||
_scrollPerc(0),
|
||||
_fixedGripSize(false),
|
||||
_gripDragging(false)
|
||||
{
|
||||
}
|
||||
|
||||
GScrollBar::~GScrollBar()
|
||||
{
|
||||
}
|
||||
|
||||
void GScrollBar::setScrollPane(ScrollPane* target, bool vertical)
|
||||
{
|
||||
_target = target;
|
||||
_vertical = vertical;
|
||||
}
|
||||
|
||||
void GScrollBar::setDisplayPerc(float value)
|
||||
{
|
||||
if (_vertical)
|
||||
{
|
||||
if (!_fixedGripSize)
|
||||
_grip->setHeight(floor(value * _bar->getHeight()));
|
||||
_grip->setY(round(_bar->getY() + (_bar->getHeight() - _grip->getHeight()) * _scrollPerc));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_fixedGripSize)
|
||||
_grip->setWidth(floor(value * _bar->getWidth()));
|
||||
_grip->setX(round(_bar->getX() + (_bar->getWidth() - _grip->getWidth()) * _scrollPerc));
|
||||
}
|
||||
|
||||
_grip->setVisible(value != 0 && value != 1);
|
||||
}
|
||||
|
||||
void GScrollBar::setScrollPerc(float value)
|
||||
{
|
||||
_scrollPerc = value;
|
||||
if (_vertical)
|
||||
_grip->setY(round(_bar->getY() + (_bar->getHeight() - _grip->getHeight()) * _scrollPerc));
|
||||
else
|
||||
_grip->setX(round(_bar->getX() + (_bar->getWidth() - _grip->getWidth()) * _scrollPerc));
|
||||
}
|
||||
|
||||
float GScrollBar::getMinSize()
|
||||
{
|
||||
if (_vertical)
|
||||
return (_arrowButton1 != nullptr ? _arrowButton1->getHeight() : 0) + (_arrowButton2 != nullptr ? _arrowButton2->getHeight() : 0);
|
||||
else
|
||||
return (_arrowButton1 != nullptr ? _arrowButton1->getWidth() : 0) + (_arrowButton2 != nullptr ? _arrowButton2->getWidth() : 0);
|
||||
}
|
||||
|
||||
void GScrollBar::constructExtension(ByteBuffer* buffer)
|
||||
{
|
||||
buffer->seek(0, 6);
|
||||
|
||||
_fixedGripSize = buffer->readBool();
|
||||
|
||||
_grip = getChild("grip");
|
||||
CCASSERT(_grip != nullptr, "FairyGUI: should define grip");
|
||||
_bar = getChild("bar");
|
||||
CCASSERT(_bar != nullptr, "FairyGUI: should define bar");
|
||||
|
||||
_arrowButton1 = getChild("arrow1");
|
||||
_arrowButton2 = getChild("arrow2");
|
||||
|
||||
_grip->addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GScrollBar::onGripTouchBegin, this));
|
||||
_grip->addEventListener(UIEventType::TouchMove, CC_CALLBACK_1(GScrollBar::onGripTouchMove, this));
|
||||
_grip->addEventListener(UIEventType::TouchEnd, CC_CALLBACK_1(GScrollBar::onGripTouchEnd, this));
|
||||
|
||||
this->addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GScrollBar::onTouchBegin, this));
|
||||
|
||||
if (_arrowButton1 != nullptr)
|
||||
_arrowButton1->addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GScrollBar::onArrowButton1Click, this));
|
||||
if (_arrowButton2 != nullptr)
|
||||
_arrowButton2->addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GScrollBar::onArrowButton2Click, this));
|
||||
}
|
||||
|
||||
void GScrollBar::onTouchBegin(EventContext* context)
|
||||
{
|
||||
context->stopPropagation();
|
||||
|
||||
InputEvent* evt = context->getInput();
|
||||
Vec2 pt = _grip->globalToLocal(evt->getPosition());
|
||||
if (_vertical)
|
||||
{
|
||||
if (pt.y < 0)
|
||||
_target->scrollUp(4, false);
|
||||
else
|
||||
_target->scrollDown(4, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pt.x < 0)
|
||||
_target->scrollLeft(4, false);
|
||||
else
|
||||
_target->scrollRight(4, false);
|
||||
}
|
||||
}
|
||||
|
||||
void GScrollBar::onGripTouchBegin(EventContext* context)
|
||||
{
|
||||
if (_bar == nullptr)
|
||||
return;
|
||||
|
||||
context->stopPropagation();
|
||||
context->captureTouch();
|
||||
|
||||
_gripDragging = true;
|
||||
_target->updateScrollBarVisible();
|
||||
|
||||
_dragOffset = globalToLocal(context->getInput()->getPosition()) - _grip->getPosition();
|
||||
}
|
||||
|
||||
void GScrollBar::onGripTouchMove(EventContext* context)
|
||||
{
|
||||
Vec2 pt = globalToLocal(context->getInput()->getPosition());
|
||||
|
||||
if (_vertical)
|
||||
{
|
||||
float curY = pt.y - _dragOffset.y;
|
||||
float diff = _bar->getHeight() - _grip->getHeight();
|
||||
if (diff == 0)
|
||||
_target->setPercY(0);
|
||||
else
|
||||
_target->setPercY((curY - _bar->getY()) / diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
float curX = pt.x - _dragOffset.x;
|
||||
float diff = _bar->getWidth() - _grip->getWidth();
|
||||
if (diff == 0)
|
||||
_target->setPercX(0);
|
||||
else
|
||||
_target->setPercX((curX - _bar->getX()) / diff);
|
||||
}
|
||||
}
|
||||
|
||||
void GScrollBar::onGripTouchEnd(EventContext* context)
|
||||
{
|
||||
_gripDragging = false;
|
||||
_target->updateScrollBarVisible();
|
||||
}
|
||||
|
||||
void GScrollBar::onArrowButton1Click(EventContext* context)
|
||||
{
|
||||
context->stopPropagation();
|
||||
|
||||
if (_vertical)
|
||||
_target->scrollUp();
|
||||
else
|
||||
_target->scrollLeft();
|
||||
}
|
||||
|
||||
void GScrollBar::onArrowButton2Click(EventContext* context)
|
||||
{
|
||||
context->stopPropagation();
|
||||
|
||||
if (_vertical)
|
||||
_target->scrollDown();
|
||||
else
|
||||
_target->scrollRight();
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef __GSCROLLBAR_H__
|
||||
#define __GSCROLLBAR_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GComponent.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GScrollBar : public GComponent
|
||||
{
|
||||
public:
|
||||
GScrollBar();
|
||||
virtual ~GScrollBar();
|
||||
|
||||
CREATE_FUNC(GScrollBar);
|
||||
|
||||
void setScrollPane(ScrollPane* target, bool vertical);
|
||||
void setDisplayPerc(float value);
|
||||
void setScrollPerc(float value);
|
||||
float getMinSize();
|
||||
|
||||
bool _gripDragging;
|
||||
|
||||
protected:
|
||||
virtual void constructExtension(ByteBuffer* buffer) override;
|
||||
|
||||
private:
|
||||
void onTouchBegin(EventContext* context);
|
||||
void onGripTouchBegin(EventContext* context);
|
||||
void onGripTouchMove(EventContext* context);
|
||||
void onGripTouchEnd(EventContext* context);
|
||||
void onArrowButton1Click(EventContext* context);
|
||||
void onArrowButton2Click(EventContext* context);
|
||||
|
||||
GObject* _grip;
|
||||
GObject* _arrowButton1;
|
||||
GObject* _arrowButton2;
|
||||
GObject* _bar;
|
||||
ScrollPane* _target;
|
||||
|
||||
bool _vertical;
|
||||
float _scrollPerc;
|
||||
bool _fixedGripSize;
|
||||
|
||||
cocos2d::Vec2 _dragOffset;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,290 @@
|
|||
#include "GSlider.h"
|
||||
#include "PackageItem.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GSlider::GSlider()
|
||||
: changeOnClick(false),
|
||||
canDrag(false),
|
||||
_min(0),
|
||||
_max(100),
|
||||
_value(0),
|
||||
_titleType(ProgressTitleType::PERCENT),
|
||||
_titleObject(nullptr),
|
||||
_barObjectH(nullptr),
|
||||
_barObjectV(nullptr),
|
||||
_barMaxWidth(0),
|
||||
_barMaxHeight(0),
|
||||
_barMaxWidthDelta(0),
|
||||
_barMaxHeightDelta(0),
|
||||
_gripObject(nullptr),
|
||||
_clickPercent(0),
|
||||
_barStartX(0),
|
||||
_barStartY(0),
|
||||
_wholeNumbers(false)
|
||||
{
|
||||
}
|
||||
|
||||
GSlider::~GSlider()
|
||||
{
|
||||
}
|
||||
|
||||
void GSlider::setTitleType(ProgressTitleType value)
|
||||
{
|
||||
if (_titleType != value)
|
||||
{
|
||||
_titleType = value;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void GSlider::setMin(double value)
|
||||
{
|
||||
if (_min != value)
|
||||
{
|
||||
_min = value;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void GSlider::setMax(double value)
|
||||
{
|
||||
if (_max != value)
|
||||
{
|
||||
_max = value;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void GSlider::setValue(double value)
|
||||
{
|
||||
if (_value != value)
|
||||
{
|
||||
_value = value;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void GSlider::setWholeNumbers(bool value)
|
||||
{
|
||||
if (_wholeNumbers != value)
|
||||
{
|
||||
_wholeNumbers = value;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void GSlider::update()
|
||||
{
|
||||
float percent = MIN(_value / _max, 1);
|
||||
updateWithPercent(percent, false);
|
||||
}
|
||||
|
||||
void GSlider::updateWithPercent(float percent, bool manual)
|
||||
{
|
||||
percent = clampf(percent, 0, 1);
|
||||
if (manual)
|
||||
{
|
||||
double newValue = _min + (_max - _min) * percent;
|
||||
if (newValue < _min)
|
||||
newValue = _min;
|
||||
if (newValue > _max)
|
||||
newValue = _max;
|
||||
if (_wholeNumbers)
|
||||
{
|
||||
newValue = round(newValue);
|
||||
percent = clampf((newValue - _min) / (_max - _min), 0, 1);
|
||||
}
|
||||
|
||||
if (newValue != _value)
|
||||
{
|
||||
_value = newValue;
|
||||
if (dispatchEvent(UIEventType::Changed))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_titleObject != nullptr)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
switch (_titleType)
|
||||
{
|
||||
case ProgressTitleType::PERCENT:
|
||||
oss << floor(percent * 100) << "%";
|
||||
break;
|
||||
|
||||
case ProgressTitleType::VALUE_MAX:
|
||||
oss << floor(_value) << "/" << floor(_max);
|
||||
break;
|
||||
|
||||
case ProgressTitleType::VALUE:
|
||||
oss << _value;
|
||||
break;
|
||||
|
||||
case ProgressTitleType::MAX:
|
||||
oss << _max;
|
||||
break;
|
||||
}
|
||||
_titleObject->setText(oss.str());
|
||||
}
|
||||
|
||||
float fullWidth = this->getWidth() - _barMaxWidthDelta;
|
||||
float fullHeight = this->getHeight() - _barMaxHeightDelta;
|
||||
if (!_reverse)
|
||||
{
|
||||
if (_barObjectH != nullptr)
|
||||
_barObjectH->setWidth(round(fullWidth * percent));
|
||||
if (_barObjectV != nullptr)
|
||||
_barObjectV->setHeight(round(fullHeight * percent));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_barObjectH != nullptr)
|
||||
{
|
||||
_barObjectH->setWidth(round(fullWidth * percent));
|
||||
_barObjectH->setX(_barStartX + (fullWidth - _barObjectH->getWidth()));
|
||||
}
|
||||
if (_barObjectV != nullptr)
|
||||
{
|
||||
_barObjectV->setHeight(round(fullHeight * percent));
|
||||
_barObjectV->setY(_barStartY + (fullHeight - _barObjectV->getHeight()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GSlider::handleSizeChanged()
|
||||
{
|
||||
GComponent::handleSizeChanged();
|
||||
|
||||
if (_barObjectH != nullptr)
|
||||
_barMaxWidth = getWidth() - _barMaxWidthDelta;
|
||||
if (_barObjectV != nullptr)
|
||||
_barMaxHeight = getHeight() - _barMaxHeightDelta;
|
||||
|
||||
if (!_underConstruct)
|
||||
update();
|
||||
}
|
||||
|
||||
void GSlider::constructExtension(ByteBuffer* buffer)
|
||||
{
|
||||
_titleType = (ProgressTitleType)buffer->readByte();
|
||||
_reverse = buffer->readBool();
|
||||
if (buffer->version >= 2)
|
||||
{
|
||||
_wholeNumbers = buffer->readBool();
|
||||
changeOnClick = buffer->readBool();
|
||||
}
|
||||
|
||||
_titleObject = getChild("title");
|
||||
_barObjectH = getChild("bar");
|
||||
_barObjectV = getChild("bar_v");
|
||||
_gripObject = getChild("grip");
|
||||
|
||||
if (_barObjectH != nullptr)
|
||||
{
|
||||
_barMaxWidth = _barObjectH->getWidth();
|
||||
_barMaxWidthDelta = getWidth() - _barMaxWidth;
|
||||
_barStartX = _barObjectH->getX();
|
||||
}
|
||||
if (_barObjectV != nullptr)
|
||||
{
|
||||
_barMaxHeight = _barObjectV->getHeight();
|
||||
_barMaxHeightDelta = getHeight() - _barMaxHeight;
|
||||
_barStartY = _barObjectV->getY();
|
||||
}
|
||||
|
||||
if (_gripObject != nullptr)
|
||||
{
|
||||
_gripObject->addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GSlider::onGripTouchBegin, this));
|
||||
_gripObject->addEventListener(UIEventType::TouchMove, CC_CALLBACK_1(GSlider::onGripTouchMove, this));
|
||||
}
|
||||
|
||||
addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GSlider::onTouchBegin, this));
|
||||
}
|
||||
|
||||
void GSlider::setup_afterAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GComponent::setup_afterAdd(buffer, beginPos);
|
||||
|
||||
if (!buffer->seek(beginPos, 6))
|
||||
{
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ObjectType)buffer->readByte() != _packageItem->objectType)
|
||||
{
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
_value = buffer->readInt();
|
||||
_max = buffer->readInt();
|
||||
if (buffer->version >= 2)
|
||||
_min = buffer->readInt();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void GSlider::onTouchBegin(EventContext* context)
|
||||
{
|
||||
if (!changeOnClick)
|
||||
return;
|
||||
|
||||
InputEvent* evt = context->getInput();
|
||||
if (evt->getButton() != EventMouse::MouseButton::BUTTON_LEFT)
|
||||
return;
|
||||
|
||||
Vec2 pt = _gripObject->globalToLocal(evt->getPosition());
|
||||
float percent = clampf((_value - _min) / (_max - _min), 0, 1);
|
||||
float delta = 0;
|
||||
if (_barObjectH != nullptr)
|
||||
delta = pt.x / _barMaxWidth;
|
||||
if (_barObjectV != nullptr)
|
||||
delta = pt.y / _barMaxHeight;
|
||||
if (_reverse)
|
||||
percent -= delta;
|
||||
else
|
||||
percent += delta;
|
||||
updateWithPercent(percent, true);
|
||||
}
|
||||
|
||||
void GSlider::onGripTouchBegin(EventContext* context)
|
||||
{
|
||||
if (context->getInput()->getButton() != EventMouse::MouseButton::BUTTON_LEFT)
|
||||
return;
|
||||
|
||||
canDrag = true;
|
||||
context->stopPropagation();
|
||||
context->captureTouch();
|
||||
|
||||
_clickPos = globalToLocal(context->getInput()->getPosition());
|
||||
_clickPercent = clampf((_value - _min) / (_max - _min), 0, 1);
|
||||
}
|
||||
|
||||
void GSlider::onGripTouchMove(EventContext* context)
|
||||
{
|
||||
if (!canDrag)
|
||||
return;
|
||||
|
||||
Vec2 pt = globalToLocal(context->getInput()->getPosition());
|
||||
|
||||
float deltaX = pt.x - _clickPos.x;
|
||||
float deltaY = pt.y - _clickPos.y;
|
||||
if (_reverse)
|
||||
{
|
||||
deltaX = -deltaX;
|
||||
deltaY = -deltaY;
|
||||
}
|
||||
|
||||
float percent;
|
||||
if (_barObjectH != nullptr)
|
||||
percent = _clickPercent + deltaX / _barMaxWidth;
|
||||
else
|
||||
percent = _clickPercent + deltaY / _barMaxHeight;
|
||||
updateWithPercent(percent, true);
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef __GSLIDER_H__
|
||||
#define __GSLIDER_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GComponent.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GSlider : public GComponent
|
||||
{
|
||||
public:
|
||||
GSlider();
|
||||
virtual ~GSlider();
|
||||
|
||||
CREATE_FUNC(GSlider);
|
||||
|
||||
ProgressTitleType getTitleType() const { return _titleType; }
|
||||
void setTitleType(ProgressTitleType value);
|
||||
|
||||
double getMin() const { return _min; }
|
||||
void setMin(double value);
|
||||
|
||||
double getMax() const { return _max; }
|
||||
void setMax(double value);
|
||||
|
||||
double getValue() const { return _value; }
|
||||
void setValue(double value);
|
||||
|
||||
bool getWholeNumbers() const { return _wholeNumbers; }
|
||||
void setWholeNumbers(bool value);
|
||||
|
||||
bool changeOnClick;
|
||||
bool canDrag;
|
||||
|
||||
protected:
|
||||
virtual void handleSizeChanged() override;
|
||||
virtual void constructExtension(ByteBuffer* buffer) override;
|
||||
virtual void setup_afterAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
|
||||
void update();
|
||||
void updateWithPercent(float percent, bool manual);
|
||||
|
||||
private:
|
||||
void onTouchBegin(EventContext* context);
|
||||
void onGripTouchBegin(EventContext* context);
|
||||
void onGripTouchMove(EventContext* context);
|
||||
|
||||
double _min;
|
||||
double _max;
|
||||
double _value;
|
||||
ProgressTitleType _titleType;
|
||||
bool _reverse;
|
||||
bool _wholeNumbers;
|
||||
|
||||
GObject* _titleObject;
|
||||
GObject* _barObjectH;
|
||||
GObject* _barObjectV;
|
||||
float _barMaxWidth;
|
||||
float _barMaxHeight;
|
||||
float _barMaxWidthDelta;
|
||||
float _barMaxHeightDelta;
|
||||
GObject* _gripObject;
|
||||
cocos2d::Vec2 _clickPos;
|
||||
float _clickPercent;
|
||||
float _barStartX;
|
||||
float _barStartY;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,377 @@
|
|||
#include "GTextField.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GTextField::GTextField()
|
||||
: _templateVars(nullptr),
|
||||
_ubbEnabled(false),
|
||||
_autoSize(AutoSizeType::BOTH)
|
||||
{
|
||||
}
|
||||
|
||||
GTextField::~GTextField()
|
||||
{
|
||||
CC_SAFE_DELETE(_templateVars);
|
||||
}
|
||||
|
||||
void GTextField::setText(const std::string& value)
|
||||
{
|
||||
_text = value;
|
||||
setTextFieldText();
|
||||
updateGear(6);
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void GTextField::setUBBEnabled(bool value)
|
||||
{
|
||||
if (_ubbEnabled != value)
|
||||
{
|
||||
_ubbEnabled = value;
|
||||
setTextFieldText();
|
||||
updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
void GTextField::setColor(const cocos2d::Color3B& value)
|
||||
{
|
||||
TextFormat* tf = getTextFormat();
|
||||
if (tf->color != value)
|
||||
{
|
||||
tf->color = value;
|
||||
applyTextFormat();
|
||||
}
|
||||
}
|
||||
|
||||
void GTextField::setFontSize(float value)
|
||||
{
|
||||
TextFormat* tf = getTextFormat();
|
||||
if (tf->fontSize != value)
|
||||
{
|
||||
tf->fontSize = value;
|
||||
applyTextFormat();
|
||||
}
|
||||
}
|
||||
|
||||
void GTextField::setOutlineColor(const cocos2d::Color3B& value)
|
||||
{
|
||||
TextFormat* tf = getTextFormat();
|
||||
if (tf->outlineColor != value)
|
||||
{
|
||||
tf->outlineColor = value;
|
||||
applyTextFormat();
|
||||
}
|
||||
}
|
||||
|
||||
void GTextField::setTemplateVars(cocos2d::ValueMap* value)
|
||||
{
|
||||
if (_templateVars == nullptr && value == nullptr)
|
||||
return;
|
||||
|
||||
if (value == nullptr)
|
||||
CC_SAFE_DELETE(_templateVars);
|
||||
else
|
||||
{
|
||||
if (_templateVars == nullptr)
|
||||
_templateVars = new cocos2d::ValueMap();
|
||||
*_templateVars = *value;
|
||||
}
|
||||
|
||||
flushVars();
|
||||
}
|
||||
|
||||
GTextField* GTextField::setVar(const std::string& name, const cocos2d::Value& value)
|
||||
{
|
||||
if (_templateVars == nullptr)
|
||||
_templateVars = new cocos2d::ValueMap();
|
||||
|
||||
(*_templateVars)[name] = value;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void GTextField::flushVars()
|
||||
{
|
||||
setTextFieldText();
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void GTextField::updateSize()
|
||||
{
|
||||
}
|
||||
|
||||
cocos2d::Value GTextField::getProp(ObjectPropID propId)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
return Value(ToolSet::colorToInt(getColor()));
|
||||
case ObjectPropID::OutlineColor:
|
||||
return Value(ToolSet::colorToInt(getOutlineColor()));
|
||||
case ObjectPropID::FontSize:
|
||||
return Value(getFontSize());
|
||||
default:
|
||||
return GObject::getProp(propId);
|
||||
}
|
||||
}
|
||||
|
||||
void GTextField::setProp(ObjectPropID propId, const cocos2d::Value& value)
|
||||
{
|
||||
switch (propId)
|
||||
{
|
||||
case ObjectPropID::Color:
|
||||
setColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
case ObjectPropID::OutlineColor:
|
||||
setOutlineColor(ToolSet::intToColor(value.asUnsignedInt()));
|
||||
break;
|
||||
case ObjectPropID::FontSize:
|
||||
setFontSize(value.asInt());
|
||||
break;
|
||||
default:
|
||||
GObject::setProp(propId, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GTextField::setup_beforeAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GObject::setup_beforeAdd(buffer, beginPos);
|
||||
|
||||
buffer->seek(beginPos, 5);
|
||||
|
||||
TextFormat* tf = getTextFormat();
|
||||
|
||||
tf->face = buffer->readS();
|
||||
tf->fontSize = buffer->readShort();
|
||||
tf->color = (Color3B)buffer->readColor();
|
||||
tf->align = (TextHAlignment)buffer->readByte();
|
||||
tf->verticalAlign = (TextVAlignment)buffer->readByte();
|
||||
tf->lineSpacing = buffer->readShort();
|
||||
tf->letterSpacing = buffer->readShort();
|
||||
_ubbEnabled = buffer->readBool();
|
||||
setAutoSize((AutoSizeType)buffer->readByte());
|
||||
tf->underline = buffer->readBool();
|
||||
tf->italics = buffer->readBool();
|
||||
tf->bold = buffer->readBool();
|
||||
if (buffer->readBool())
|
||||
setSingleLine(true);
|
||||
if (buffer->readBool())
|
||||
{
|
||||
tf->outlineColor = (Color3B)buffer->readColor();
|
||||
tf->outlineSize = buffer->readFloat();
|
||||
tf->enableEffect(TextFormat::OUTLINE);
|
||||
}
|
||||
|
||||
if (buffer->readBool())
|
||||
{
|
||||
tf->shadowColor = (Color3B)buffer->readColor();
|
||||
float f1 = buffer->readFloat();
|
||||
float f2 = buffer->readFloat();
|
||||
tf->shadowOffset = Vec2(f1, -f2);
|
||||
tf->enableEffect(TextFormat::SHADOW);
|
||||
}
|
||||
|
||||
if (buffer->readBool())
|
||||
_templateVars = new cocos2d::ValueMap();
|
||||
}
|
||||
|
||||
void GTextField::setup_afterAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GObject::setup_afterAdd(buffer, beginPos);
|
||||
|
||||
applyTextFormat();
|
||||
|
||||
buffer->seek(beginPos, 6);
|
||||
|
||||
const std::string& str = buffer->readS();
|
||||
if (!str.empty())
|
||||
setText(str);
|
||||
}
|
||||
|
||||
std::string GTextField::parseTemplate(const char* text)
|
||||
{
|
||||
const char* pString = text;
|
||||
|
||||
ssize_t pos;
|
||||
ssize_t pos2;
|
||||
std::string tag, attr;
|
||||
std::string repl;
|
||||
std::string out;
|
||||
|
||||
while (*pString != '\0')
|
||||
{
|
||||
const char* p = strchr(pString, '{');
|
||||
if (!p)
|
||||
{
|
||||
out.append(pString);
|
||||
break;
|
||||
}
|
||||
|
||||
pos = p - pString;
|
||||
if (pos > 0 && *(p - 1) == '\\')
|
||||
{
|
||||
out.append(pString, pos - 1);
|
||||
out.append("{");
|
||||
pString += pos + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
out.append(pString, pos);
|
||||
pString += pos;
|
||||
|
||||
p = strchr(pString, '}');
|
||||
if (!p)
|
||||
{
|
||||
out.append(pString);
|
||||
break;
|
||||
}
|
||||
|
||||
pos = p - pString;
|
||||
if (pos == 1)
|
||||
{
|
||||
out.append(pString, 0, 2);
|
||||
pString += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
tag.assign(pString + 1, pos - 1);
|
||||
|
||||
attr.clear();
|
||||
repl.clear();
|
||||
pos2 = tag.find('=');
|
||||
if (pos2 != -1)
|
||||
{
|
||||
auto it = _templateVars->find(tag.substr(0, pos2));
|
||||
if (it != _templateVars->end())
|
||||
out.append(it->second.asString());
|
||||
else
|
||||
out.append(tag.substr(pos2 + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = _templateVars->find(tag);
|
||||
if (it != _templateVars->end())
|
||||
out.append(it->second.asString());
|
||||
}
|
||||
pString += pos + 1;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
|
||||
GBasicTextField::GBasicTextField() : _label(nullptr),
|
||||
_updatingSize(false)
|
||||
{
|
||||
_touchDisabled = true;
|
||||
}
|
||||
|
||||
GBasicTextField::~GBasicTextField()
|
||||
{
|
||||
}
|
||||
|
||||
void GBasicTextField::handleInit()
|
||||
{
|
||||
_label = FUILabel::create();
|
||||
_label->retain();
|
||||
|
||||
_displayObject = _label;
|
||||
}
|
||||
|
||||
void GBasicTextField::applyTextFormat()
|
||||
{
|
||||
_label->applyTextFormat();
|
||||
updateGear(4);
|
||||
if (!_underConstruct)
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void GBasicTextField::setAutoSize(AutoSizeType value)
|
||||
{
|
||||
_autoSize = value;
|
||||
switch (value)
|
||||
{
|
||||
case AutoSizeType::NONE:
|
||||
_label->setOverflow(Label::Overflow::CLAMP);
|
||||
break;
|
||||
case AutoSizeType::BOTH:
|
||||
_label->setOverflow(Label::Overflow::NONE);
|
||||
break;
|
||||
case AutoSizeType::HEIGHT:
|
||||
_label->setOverflow(Label::Overflow::RESIZE_HEIGHT);
|
||||
break;
|
||||
case AutoSizeType::SHRINK:
|
||||
_label->setOverflow(Label::Overflow::SHRINK);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_autoSize == AutoSizeType::BOTH)
|
||||
_label->setDimensions(0, 0);
|
||||
else if (_autoSize == AutoSizeType::HEIGHT)
|
||||
_label->setDimensions(_size.width, 0);
|
||||
else
|
||||
_label->setDimensions(_size.width, _size.height);
|
||||
|
||||
if (!_underConstruct)
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void GBasicTextField::setSingleLine(bool value)
|
||||
{
|
||||
_label->enableWrap(!value);
|
||||
if (!_underConstruct)
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void GBasicTextField::setTextFieldText()
|
||||
{
|
||||
if (_templateVars != nullptr)
|
||||
_label->setText(parseTemplate(_text.c_str()));
|
||||
else
|
||||
_label->setText(_text);
|
||||
}
|
||||
|
||||
void GBasicTextField::updateSize()
|
||||
{
|
||||
if (_updatingSize)
|
||||
return;
|
||||
|
||||
_updatingSize = true;
|
||||
|
||||
Size sz = _label->getContentSize();
|
||||
if (_autoSize == AutoSizeType::BOTH)
|
||||
setSize(sz.width, sz.height);
|
||||
else if (_autoSize == AutoSizeType::HEIGHT)
|
||||
setHeight(sz.height);
|
||||
|
||||
_updatingSize = false;
|
||||
}
|
||||
|
||||
void GBasicTextField::handleSizeChanged()
|
||||
{
|
||||
if (_updatingSize)
|
||||
return;
|
||||
|
||||
if (_autoSize != AutoSizeType::BOTH)
|
||||
{
|
||||
_label->setDimensions(_size.width, _size.height);
|
||||
|
||||
if (_autoSize == AutoSizeType::HEIGHT)
|
||||
{
|
||||
if (!_text.empty())
|
||||
setSizeDirectly(_size.width, _label->getContentSize().height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GBasicTextField::handleGrayedChanged()
|
||||
{
|
||||
GObject::handleGrayedChanged();
|
||||
|
||||
_label->setGrayed(_finalGrayed);
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,98 @@
|
|||
#ifndef __GTEXTFIELD_H__
|
||||
#define __GTEXTFIELD_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GObject.h"
|
||||
#include "display/FUILabel.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GTextField : public GObject
|
||||
{
|
||||
public:
|
||||
GTextField();
|
||||
virtual ~GTextField();
|
||||
|
||||
virtual const std::string& getText() const override { return _text; }
|
||||
void setText(const std::string& value) override;
|
||||
|
||||
bool isUBBEnabled() const { return _ubbEnabled; }
|
||||
virtual void setUBBEnabled(bool value);
|
||||
|
||||
AutoSizeType getAutoSize() const { return _autoSize; }
|
||||
virtual void setAutoSize(AutoSizeType value) {};
|
||||
|
||||
virtual bool isSingleLine() const { return false; }
|
||||
virtual void setSingleLine(bool value) {};
|
||||
|
||||
virtual TextFormat* getTextFormat() const = 0;
|
||||
virtual void applyTextFormat() = 0;
|
||||
|
||||
virtual const cocos2d::Size& getTextSize() { return _displayObject->getContentSize(); }
|
||||
|
||||
cocos2d::Color3B getColor() const { return getTextFormat()->color; }
|
||||
void setColor(const cocos2d::Color3B& value);
|
||||
|
||||
float getFontSize() const { return getTextFormat()->fontSize; }
|
||||
void setFontSize(float value);
|
||||
|
||||
cocos2d::Color3B getOutlineColor() const { return getTextFormat()->outlineColor; }
|
||||
void setOutlineColor(const cocos2d::Color3B& value);
|
||||
|
||||
cocos2d::ValueMap* getTemplateVars() { return _templateVars; }
|
||||
void setTemplateVars(cocos2d::ValueMap* value);
|
||||
|
||||
GTextField* setVar(const std::string& name, const cocos2d::Value& value);
|
||||
void flushVars();
|
||||
|
||||
virtual cocos2d::Value getProp(ObjectPropID propId) override;
|
||||
virtual void setProp(ObjectPropID propId, const cocos2d::Value& value) override;
|
||||
|
||||
protected:
|
||||
virtual void setTextFieldText() = 0;
|
||||
virtual void updateSize();
|
||||
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual void setup_afterAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
|
||||
std::string parseTemplate(const char* text);
|
||||
|
||||
std::string _text;
|
||||
bool _ubbEnabled;
|
||||
AutoSizeType _autoSize;
|
||||
cocos2d::ValueMap* _templateVars;
|
||||
};
|
||||
|
||||
class GBasicTextField : public GTextField
|
||||
{
|
||||
public:
|
||||
GBasicTextField();
|
||||
virtual ~GBasicTextField();
|
||||
|
||||
CREATE_FUNC(GBasicTextField);
|
||||
|
||||
virtual void setAutoSize(AutoSizeType value) override;
|
||||
|
||||
virtual bool isSingleLine() const override { return _label->isWrapEnabled(); }
|
||||
virtual void setSingleLine(bool value) override;
|
||||
|
||||
virtual TextFormat* getTextFormat() const override { return _label->getTextFormat(); }
|
||||
virtual void applyTextFormat() override;
|
||||
|
||||
protected:
|
||||
virtual void handleInit() override;
|
||||
virtual void handleSizeChanged() override;
|
||||
virtual void handleGrayedChanged() override;
|
||||
|
||||
virtual void setTextFieldText() override;
|
||||
virtual void updateSize() override;
|
||||
|
||||
private:
|
||||
FUILabel* _label;
|
||||
bool _updatingSize;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,131 @@
|
|||
#include "GTextInput.h"
|
||||
#include "UIPackage.h"
|
||||
#include "GRoot.h"
|
||||
#include "ui/UIEditBox/UIEditBox.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/UBBParser.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GTextInput::GTextInput()
|
||||
{
|
||||
}
|
||||
|
||||
GTextInput::~GTextInput()
|
||||
{
|
||||
}
|
||||
|
||||
void GTextInput::handleInit()
|
||||
{
|
||||
_input = FUIInput::create();
|
||||
_input->retain();
|
||||
_input->setDelegate(this);
|
||||
|
||||
_displayObject = _input;
|
||||
|
||||
this->addEventListener(UIEventType::TouchEnd, [this](EventContext*) {
|
||||
_input->openKeyboard();
|
||||
});
|
||||
}
|
||||
|
||||
bool GTextInput::isSingleLine() const
|
||||
{
|
||||
return _input->isSingleLine();
|
||||
}
|
||||
|
||||
void GTextInput::setSingleLine(bool value)
|
||||
{
|
||||
_input->setSingleLine(value);
|
||||
}
|
||||
|
||||
void GTextInput::applyTextFormat()
|
||||
{
|
||||
_input->applyTextFormat();
|
||||
}
|
||||
|
||||
void GTextInput::setPrompt(const std::string & value)
|
||||
{
|
||||
if (value.empty())
|
||||
_input->setPlaceHolder(value.c_str());
|
||||
else
|
||||
{
|
||||
UBBParser* parser = UBBParser::getInstance();
|
||||
_input->setPlaceHolder(parser->parse(value.c_str(), true).c_str());
|
||||
if (!parser->lastColor.empty())
|
||||
_input->setPlaceholderFontColor(ToolSet::hexToColor(parser->lastColor.c_str()));
|
||||
if (!parser->lastFontSize.empty())
|
||||
_input->setPlaceholderFontSize(Value(parser->lastFontSize).asInt());
|
||||
}
|
||||
}
|
||||
|
||||
void GTextInput::setPassword(bool value)
|
||||
{
|
||||
_input->setPassword(value);
|
||||
}
|
||||
|
||||
void GTextInput::setKeyboardType(int value)
|
||||
{
|
||||
_input->setKeyboardType(value);
|
||||
}
|
||||
|
||||
void GTextInput::setMaxLength(int value)
|
||||
{
|
||||
_input->setMaxLength(value);
|
||||
}
|
||||
|
||||
void GTextInput::setRestrict(const std::string & value)
|
||||
{
|
||||
}
|
||||
|
||||
void GTextInput::handleSizeChanged()
|
||||
{
|
||||
_input->setContentSize(_size);
|
||||
}
|
||||
|
||||
void GTextInput::setup_beforeAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GTextField::setup_beforeAdd(buffer, beginPos);
|
||||
|
||||
buffer->seek(beginPos, 4);
|
||||
|
||||
const std::string* str;
|
||||
if ((str = buffer->readSP()))
|
||||
setPrompt(*str);
|
||||
|
||||
if ((str = buffer->readSP()))
|
||||
setRestrict(*str);
|
||||
|
||||
int iv = buffer->readInt();
|
||||
if (iv != 0)
|
||||
setMaxLength(iv);
|
||||
iv = buffer->readInt();
|
||||
if (iv != 0)
|
||||
setKeyboardType(iv);
|
||||
if (buffer->readBool())
|
||||
setPassword(true);
|
||||
}
|
||||
|
||||
void GTextInput::setTextFieldText()
|
||||
{
|
||||
if (_templateVars != nullptr)
|
||||
_input->setText(parseTemplate(_text.c_str()));
|
||||
else
|
||||
_input->setText(_text);
|
||||
}
|
||||
|
||||
void GTextInput::editBoxReturn(cocos2d::ui::EditBox * editBox)
|
||||
{
|
||||
//found that this will trigger even when focus is lost
|
||||
//if (isSingleLine())
|
||||
// dispatchEvent(UIEventType::Submit);
|
||||
}
|
||||
|
||||
void GTextInput::editBoxTextChanged(cocos2d::ui::EditBox* editBox, const std::string& text)
|
||||
{
|
||||
_text.clear();
|
||||
_text.append(_input->getText());
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef __GTEXTINPUT_H__
|
||||
#define __GTEXTINPUT_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GTextField.h"
|
||||
#include "display/FUIInput.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GTextInput : public GTextField, cocos2d::ui::EditBoxDelegate
|
||||
{
|
||||
public:
|
||||
GTextInput();
|
||||
virtual ~GTextInput();
|
||||
|
||||
CREATE_FUNC(GTextInput);
|
||||
|
||||
virtual bool isSingleLine() const override;
|
||||
virtual void setSingleLine(bool value) override;
|
||||
|
||||
virtual TextFormat* getTextFormat() const override { return _input->getTextFormat(); }
|
||||
virtual void applyTextFormat() override;
|
||||
|
||||
void setPrompt(const std::string& value);
|
||||
void setPassword(bool value);
|
||||
void setKeyboardType(int value);
|
||||
void setMaxLength(int value);
|
||||
void setRestrict(const std::string& value);
|
||||
|
||||
protected:
|
||||
virtual void handleInit() override;
|
||||
virtual void handleSizeChanged() override;
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
|
||||
virtual void setTextFieldText() override;
|
||||
|
||||
virtual void editBoxReturn(cocos2d::ui::EditBox* editBox) override;
|
||||
virtual void editBoxTextChanged(cocos2d::ui::EditBox* editBox, const std::string& text) override;
|
||||
|
||||
private:
|
||||
FUIInput* _input;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,412 @@
|
|||
#include "GTree.h"
|
||||
#include "GButton.h"
|
||||
#include "GList.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GTree::GTree()
|
||||
: _rootNode(nullptr),
|
||||
_indent(30),
|
||||
_clickToExpand(0),
|
||||
_expandedStatusInEvt(false)
|
||||
{
|
||||
}
|
||||
|
||||
GTree::~GTree()
|
||||
{
|
||||
CC_SAFE_RELEASE(_rootNode);
|
||||
}
|
||||
|
||||
void GTree::handleInit()
|
||||
{
|
||||
GList::handleInit();
|
||||
|
||||
_rootNode = GTreeNode::create(true);
|
||||
_rootNode->setTree(this);
|
||||
_rootNode->setExpaned(true);
|
||||
_rootNode->retain();
|
||||
}
|
||||
|
||||
GTreeNode* GTree::getSelectedNode() const
|
||||
{
|
||||
int i = getSelectedIndex();
|
||||
if (i != -1)
|
||||
return getChildAt(i)->_treeNode;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GTree::getSelectedNodes(std::vector<GTreeNode*>& result) const
|
||||
{
|
||||
std::vector<int> ids;
|
||||
getSelection(ids);
|
||||
for (auto& it : ids)
|
||||
{
|
||||
GTreeNode* node = getChildAt(it)->_treeNode;
|
||||
result.push_back(node);
|
||||
}
|
||||
}
|
||||
|
||||
void GTree::selectNode(GTreeNode* node, bool scrollItToView)
|
||||
{
|
||||
GTreeNode* parentNode = node->_parent;
|
||||
while (parentNode != nullptr && parentNode != _rootNode)
|
||||
{
|
||||
parentNode->setExpaned(true);
|
||||
parentNode = parentNode->_parent;
|
||||
}
|
||||
if (node->_cell != nullptr)
|
||||
addSelection(getChildIndex(node->_cell), scrollItToView);
|
||||
}
|
||||
|
||||
void GTree::unselectNode(GTreeNode* node)
|
||||
{
|
||||
if (node->_cell != nullptr)
|
||||
removeSelection(getChildIndex(node->_cell));
|
||||
}
|
||||
|
||||
void GTree::expandAll(GTreeNode* folderNode)
|
||||
{
|
||||
folderNode->setExpaned(true);
|
||||
for (auto& it : folderNode->_children)
|
||||
{
|
||||
if (it->isFolder())
|
||||
expandAll(it);
|
||||
}
|
||||
}
|
||||
|
||||
void GTree::collapseAll(GTreeNode* folderNode)
|
||||
{
|
||||
if (folderNode != _rootNode)
|
||||
folderNode->setExpaned(false);
|
||||
for (auto& it : folderNode->_children)
|
||||
{
|
||||
if (it->isFolder())
|
||||
collapseAll(it);
|
||||
}
|
||||
}
|
||||
|
||||
void GTree::createCell(GTreeNode* node)
|
||||
{
|
||||
const std::string& url = node->_resURL.empty() ? getDefaultItem() : node->_resURL;
|
||||
GComponent* child = getItemPool()->getObject(url)->as<GComponent>();
|
||||
CCASSERT(child, "Unable to create tree cell");
|
||||
child->_treeNode = node;
|
||||
node->setCell(child);
|
||||
|
||||
GObject* indentObj = node->_cell->getChild("indent");
|
||||
if (indentObj != nullptr)
|
||||
indentObj->setWidth((node->_level - 1) * _indent);
|
||||
|
||||
GController* cc;
|
||||
|
||||
cc = child->getController("expanded");
|
||||
if (cc != nullptr)
|
||||
{
|
||||
cc->addEventListener(UIEventType::Changed, CC_CALLBACK_1(GTree::onExpandedStateChanged, this));
|
||||
cc->setSelectedIndex(node->isExpanded() ? 1 : 0);
|
||||
}
|
||||
|
||||
cc = child->getController("leaf");
|
||||
if (cc != nullptr)
|
||||
cc->setSelectedIndex(node->isFolder() ? 0 : 1);
|
||||
|
||||
if (node->isFolder())
|
||||
child->addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(GTree::onCellTouchBegin, this));
|
||||
|
||||
if (treeNodeRender != nullptr)
|
||||
treeNodeRender(node, child);
|
||||
}
|
||||
|
||||
void GTree::afterInserted(GTreeNode* node)
|
||||
{
|
||||
if (node->_cell == nullptr)
|
||||
createCell(node);
|
||||
|
||||
int index = getInsertIndexForNode(node);
|
||||
addChildAt(node->_cell, index);
|
||||
if (treeNodeRender != nullptr)
|
||||
treeNodeRender(node, node->_cell);
|
||||
|
||||
if (node->isFolder() && node->isExpanded())
|
||||
checkChildren(node, index);
|
||||
}
|
||||
|
||||
int GTree::getInsertIndexForNode(GTreeNode* node)
|
||||
{
|
||||
GTreeNode* prevNode = node->getPrevSibling();
|
||||
if (prevNode == nullptr)
|
||||
prevNode = node->getParent();
|
||||
int insertIndex;
|
||||
if (prevNode->_cell != nullptr)
|
||||
insertIndex = getChildIndex(prevNode->_cell) + 1;
|
||||
else
|
||||
insertIndex = 0;
|
||||
int myLevel = node->_level;
|
||||
int cnt = numChildren();
|
||||
for (int i = insertIndex; i < cnt; i++)
|
||||
{
|
||||
GTreeNode* testNode = getChildAt(i)->_treeNode;
|
||||
if (testNode->_level <= myLevel)
|
||||
break;
|
||||
|
||||
insertIndex++;
|
||||
}
|
||||
|
||||
return insertIndex;
|
||||
}
|
||||
|
||||
void GTree::afterRemoved(GTreeNode* node)
|
||||
{
|
||||
removeNode(node);
|
||||
}
|
||||
|
||||
void GTree::afterExpanded(GTreeNode* node)
|
||||
{
|
||||
if (node == _rootNode)
|
||||
{
|
||||
checkChildren(_rootNode, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNodeWillExpand != nullptr)
|
||||
treeNodeWillExpand(node, true);
|
||||
|
||||
if (node->_cell == nullptr)
|
||||
return;
|
||||
|
||||
if (treeNodeRender != nullptr)
|
||||
treeNodeRender(node, node->_cell);
|
||||
|
||||
GController* cc = node->_cell->getController("expanded");
|
||||
if (cc != nullptr)
|
||||
cc->setSelectedIndex(1);
|
||||
|
||||
if (node->_cell->getParent() != nullptr)
|
||||
checkChildren(node, getChildIndex(node->_cell));
|
||||
}
|
||||
|
||||
void GTree::afterCollapsed(GTreeNode* node)
|
||||
{
|
||||
if (node == _rootNode)
|
||||
{
|
||||
checkChildren(_rootNode, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNodeWillExpand != nullptr)
|
||||
treeNodeWillExpand(node, false);
|
||||
|
||||
if (node->_cell == nullptr)
|
||||
return;
|
||||
|
||||
if (treeNodeRender != nullptr)
|
||||
treeNodeRender(node, node->_cell);
|
||||
|
||||
GController* cc = node->_cell->getController("expanded");
|
||||
if (cc != nullptr)
|
||||
cc->setSelectedIndex(0);
|
||||
|
||||
if (node->_cell->getParent() != nullptr)
|
||||
hideFolderNode(node);
|
||||
}
|
||||
|
||||
void GTree::afterMoved(GTreeNode* node)
|
||||
{
|
||||
int startIndex = getChildIndex(node->_cell);
|
||||
int endIndex;
|
||||
if (node->isFolder())
|
||||
endIndex = getFolderEndIndex(startIndex, node->_level);
|
||||
else
|
||||
endIndex = startIndex + 1;
|
||||
int insertIndex = getInsertIndexForNode(node);
|
||||
int cnt = endIndex - startIndex;
|
||||
|
||||
if (insertIndex < startIndex)
|
||||
{
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* obj = getChildAt(startIndex + i);
|
||||
setChildIndex(obj, insertIndex + i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GObject* obj = getChildAt(startIndex);
|
||||
setChildIndex(obj, insertIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int GTree::getFolderEndIndex(int startIndex, int level)
|
||||
{
|
||||
int cnt = numChildren();
|
||||
for (int i = startIndex + 1; i < cnt; i++)
|
||||
{
|
||||
GTreeNode* node = getChildAt(i)->_treeNode;
|
||||
if (node->_level <= level)
|
||||
return i;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int GTree::checkChildren(GTreeNode* folderNode, int index)
|
||||
{
|
||||
int cnt = folderNode->numChildren();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
index++;
|
||||
GTreeNode* node = folderNode->getChildAt(i);
|
||||
if (node->_cell == nullptr)
|
||||
createCell(node);
|
||||
|
||||
if (node->_cell->getParent() == nullptr)
|
||||
addChildAt(node->_cell, index);
|
||||
|
||||
if (node->isFolder() && node->isExpanded())
|
||||
index = checkChildren(node, index);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void GTree::hideFolderNode(GTreeNode* folderNode)
|
||||
{
|
||||
int cnt = folderNode->numChildren();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GTreeNode* node = folderNode->getChildAt(i);
|
||||
if (node->_cell != nullptr && node->_cell->getParent() != nullptr)
|
||||
removeChild(node->_cell);
|
||||
|
||||
if (node->isFolder() && node->isExpanded())
|
||||
hideFolderNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
void GTree::removeNode(GTreeNode* node)
|
||||
{
|
||||
if (node->_cell != nullptr)
|
||||
{
|
||||
if (node->_cell->getParent() != nullptr)
|
||||
removeChild(node->_cell);
|
||||
getItemPool()->returnObject(node->_cell);
|
||||
node->_cell->_treeNode = nullptr;
|
||||
node->_cell = nullptr;
|
||||
}
|
||||
|
||||
if (node->isFolder())
|
||||
{
|
||||
int cnt = node->numChildren();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
GTreeNode* node2 = node->getChildAt(i);
|
||||
removeNode(node2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GTree::onCellTouchBegin(EventContext* context)
|
||||
{
|
||||
GTreeNode* node = ((GObject*)context->getSender())->_treeNode;
|
||||
_expandedStatusInEvt = node->isExpanded();
|
||||
}
|
||||
|
||||
void GTree::onExpandedStateChanged(EventContext* context)
|
||||
{
|
||||
GController* cc = (GController*)context->getSender();
|
||||
GTreeNode* node = cc->getParent()->_treeNode;
|
||||
node->setExpaned(cc->getSelectedIndex() == 1);
|
||||
}
|
||||
|
||||
void GTree::dispatchItemEvent(GObject* item, EventContext* context)
|
||||
{
|
||||
if (_clickToExpand != 0)
|
||||
{
|
||||
GTreeNode* node = item->_treeNode;
|
||||
if (node != nullptr && _expandedStatusInEvt == node->isExpanded())
|
||||
{
|
||||
if (_clickToExpand == 2)
|
||||
{
|
||||
if (context->getInput()->isDoubleClick())
|
||||
node->setExpaned(!node->isExpanded());
|
||||
}
|
||||
else
|
||||
node->setExpaned(!node->isExpanded());
|
||||
}
|
||||
}
|
||||
|
||||
GList::dispatchItemEvent(item, context);
|
||||
}
|
||||
|
||||
void GTree::setup_beforeAdd(ByteBuffer* buffer, int beginPos)
|
||||
{
|
||||
GList::setup_beforeAdd(buffer, beginPos);
|
||||
|
||||
buffer->seek(beginPos, 9);
|
||||
|
||||
_indent = buffer->readInt();
|
||||
_clickToExpand = buffer->readByte();
|
||||
}
|
||||
|
||||
void GTree::readItems(ByteBuffer* buffer)
|
||||
{
|
||||
int nextPos;
|
||||
std::string str;
|
||||
bool isFolder;
|
||||
GTreeNode* lastNode = nullptr;
|
||||
int level;
|
||||
int prevLevel = 0;
|
||||
|
||||
int cnt = buffer->readShort();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
nextPos = buffer->readShort();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
str = buffer->readS();
|
||||
if (!str.empty())
|
||||
{
|
||||
str = getDefaultItem();
|
||||
if (str.empty())
|
||||
{
|
||||
buffer->setPos(nextPos);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
isFolder = buffer->readBool();
|
||||
level = buffer->readByte();
|
||||
|
||||
GTreeNode* node = GTreeNode::create(isFolder, str);
|
||||
node->setExpaned(true);
|
||||
if (i == 0)
|
||||
_rootNode->addChild(node);
|
||||
else
|
||||
{
|
||||
if (level > prevLevel)
|
||||
lastNode->addChild(node);
|
||||
else if (level < prevLevel)
|
||||
{
|
||||
for (int j = level; j <= prevLevel; j++)
|
||||
lastNode = lastNode->getParent();
|
||||
lastNode->addChild(node);
|
||||
}
|
||||
else
|
||||
lastNode->getParent()->addChild(node);
|
||||
}
|
||||
lastNode = node;
|
||||
prevLevel = level;
|
||||
|
||||
setupItem(buffer, node->_cell);
|
||||
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,73 @@
|
|||
#ifndef __GTREE_H__
|
||||
#define __GTREE_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GList.h"
|
||||
#include "GTreeNode.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GList;
|
||||
class GComponent;
|
||||
|
||||
class GTree : public GList
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(GTreeNode* node, GComponent* obj)> TreeNodeRenderFunction;
|
||||
typedef std::function<void(GTreeNode* node, bool expand)> TreeNodeWillExpandFunction;
|
||||
|
||||
GTree();
|
||||
virtual ~GTree();
|
||||
|
||||
CREATE_FUNC(GTree);
|
||||
|
||||
int getIndent() const { return _indent; }
|
||||
void setIndent(int value) { _indent = value; }
|
||||
int getClickToExpand() const { return _clickToExpand; }
|
||||
void setClickToExpand(int value) { _clickToExpand = value; }
|
||||
|
||||
GTreeNode* getRootNode() const { return _rootNode; }
|
||||
GTreeNode* getSelectedNode() const;
|
||||
void getSelectedNodes(std::vector<GTreeNode*>& result) const;
|
||||
void selectNode(GTreeNode* node, bool scrollItToView = false);
|
||||
void unselectNode(GTreeNode* node);
|
||||
void expandAll(GTreeNode* folderNode);
|
||||
void collapseAll(GTreeNode* folderNode);
|
||||
|
||||
TreeNodeRenderFunction treeNodeRender;
|
||||
TreeNodeWillExpandFunction treeNodeWillExpand;
|
||||
|
||||
protected:
|
||||
virtual void handleInit() override;
|
||||
virtual void setup_beforeAdd(ByteBuffer* buffer, int beginPos) override;
|
||||
virtual void readItems(ByteBuffer* buffer) override;
|
||||
virtual void dispatchItemEvent(GObject* item, EventContext* context) override;
|
||||
|
||||
private:
|
||||
void createCell(GTreeNode* node);
|
||||
void afterInserted(GTreeNode* node);
|
||||
int getInsertIndexForNode(GTreeNode* node);
|
||||
void afterRemoved(GTreeNode* node);
|
||||
void afterExpanded(GTreeNode* node);
|
||||
void afterCollapsed(GTreeNode* node);
|
||||
void afterMoved(GTreeNode* node);
|
||||
int checkChildren(GTreeNode* folderNode, int index);
|
||||
void hideFolderNode(GTreeNode* folderNode);
|
||||
void removeNode(GTreeNode* node);
|
||||
int getFolderEndIndex(int startIndex, int level);
|
||||
|
||||
void onCellTouchBegin(EventContext* context);
|
||||
void onExpandedStateChanged(EventContext* context);
|
||||
|
||||
int _indent;
|
||||
GTreeNode* _rootNode;
|
||||
int _clickToExpand;
|
||||
bool _expandedStatusInEvt;
|
||||
|
||||
friend class GTreeNode;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,310 @@
|
|||
#include "GTreeNode.h"
|
||||
#include "GComponent.h"
|
||||
#include "GTree.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
GTreeNode* GTreeNode::create(bool isFolder, const std::string& resURL)
|
||||
{
|
||||
GTreeNode* pRet = new (std::nothrow) GTreeNode();
|
||||
|
||||
if (pRet != nullptr && pRet->init(isFolder, resURL))
|
||||
{
|
||||
pRet->autorelease();
|
||||
}
|
||||
else
|
||||
{
|
||||
CC_SAFE_DELETE(pRet);
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
|
||||
GTreeNode::GTreeNode()
|
||||
: _tree(nullptr),
|
||||
_parent(nullptr),
|
||||
_cell(nullptr),
|
||||
_level(0),
|
||||
_expanded(false),
|
||||
_isFolder(false)
|
||||
{
|
||||
}
|
||||
|
||||
GTreeNode::~GTreeNode()
|
||||
{
|
||||
for (auto& it : _children)
|
||||
it->_parent = nullptr;
|
||||
|
||||
_children.clear();
|
||||
|
||||
if (_parent)
|
||||
_parent->removeChild(this);
|
||||
|
||||
CC_SAFE_RELEASE(_cell);
|
||||
}
|
||||
|
||||
bool GTreeNode::init(bool isFolder, const std::string& resURL)
|
||||
{
|
||||
_isFolder = isFolder;
|
||||
_resURL = resURL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GTreeNode::setExpaned(bool value)
|
||||
{
|
||||
if (!_isFolder)
|
||||
return;
|
||||
|
||||
if (_expanded != value)
|
||||
{
|
||||
_expanded = value;
|
||||
if (_tree != nullptr)
|
||||
{
|
||||
if (_expanded)
|
||||
_tree->afterExpanded(this);
|
||||
else
|
||||
_tree->afterCollapsed(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& GTreeNode::getText() const
|
||||
{
|
||||
if (_cell != nullptr)
|
||||
return _cell->getText();
|
||||
else
|
||||
return STD_STRING_EMPTY;
|
||||
}
|
||||
|
||||
void GTreeNode::setText(const std::string& value)
|
||||
{
|
||||
if (_cell != nullptr)
|
||||
return _cell->setText(value);
|
||||
}
|
||||
|
||||
const std::string& GTreeNode::getIcon() const
|
||||
{
|
||||
if (_cell != nullptr)
|
||||
return _cell->getIcon();
|
||||
else
|
||||
return STD_STRING_EMPTY;
|
||||
}
|
||||
|
||||
void GTreeNode::setIcon(const std::string& value)
|
||||
{
|
||||
if (_cell != nullptr)
|
||||
return _cell->setIcon(value);
|
||||
}
|
||||
|
||||
GTreeNode* GTreeNode::addChild(GTreeNode* child)
|
||||
{
|
||||
addChildAt(child, (int)_children.size());
|
||||
return child;
|
||||
}
|
||||
|
||||
GTreeNode* GTreeNode::addChildAt(GTreeNode* child, int index)
|
||||
{
|
||||
CCASSERT(child != nullptr, "Argument must be non-nil");
|
||||
|
||||
if (child->_parent == this)
|
||||
{
|
||||
setChildIndex(child, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
child->retain();
|
||||
if (child->_parent != nullptr)
|
||||
child->_parent->removeChild(child);
|
||||
child->_parent = this;
|
||||
|
||||
int cnt = (int)_children.size();
|
||||
if (index == cnt)
|
||||
_children.pushBack(child);
|
||||
else
|
||||
_children.insert(index, child);
|
||||
child->release();
|
||||
|
||||
child->_level = _level + 1;
|
||||
child->setTree(_tree);
|
||||
if ((_tree != nullptr && this == _tree->getRootNode()) || (_cell != nullptr && _cell->getParent() != nullptr && _expanded))
|
||||
_tree->afterInserted(child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
void GTreeNode::removeChild(GTreeNode* child)
|
||||
{
|
||||
CCASSERT(child != nullptr, "Argument must be non-nil");
|
||||
|
||||
int childIndex = (int)_children.getIndex(child);
|
||||
if (childIndex != -1)
|
||||
removeChildAt(childIndex);
|
||||
}
|
||||
|
||||
void GTreeNode::removeChildAt(int index)
|
||||
{
|
||||
CCASSERT(index >= 0 && index < _children.size(), "Invalid child index");
|
||||
|
||||
GTreeNode* child = _children.at(index);
|
||||
child->_parent = nullptr;
|
||||
|
||||
if (_tree != nullptr)
|
||||
{
|
||||
child->setTree(nullptr);
|
||||
_tree->afterRemoved(child);
|
||||
}
|
||||
|
||||
_children.erase(index);
|
||||
}
|
||||
|
||||
void GTreeNode::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);
|
||||
}
|
||||
|
||||
GTreeNode* GTreeNode::getChildAt(int index) const
|
||||
{
|
||||
CCASSERT(index >= 0 && index < _children.size(), "Invalid child index");
|
||||
|
||||
return _children.at(index);
|
||||
}
|
||||
|
||||
GTreeNode* GTreeNode::getPrevSibling() const
|
||||
{
|
||||
if (_parent == nullptr)
|
||||
return nullptr;
|
||||
|
||||
ssize_t i = _parent->_children.getIndex((GTreeNode*)this);
|
||||
if (i <= 0)
|
||||
return nullptr;
|
||||
|
||||
return _parent->_children.at(i - 1);
|
||||
}
|
||||
|
||||
GTreeNode* GTreeNode::getNextSibling() const
|
||||
{
|
||||
if (_parent == nullptr)
|
||||
return nullptr;
|
||||
|
||||
ssize_t i = _parent->_children.getIndex((GTreeNode*)this);
|
||||
if (i < 0 || i >= _parent->_children.size() - 1)
|
||||
return nullptr;
|
||||
|
||||
return _parent->_children.at(i + 1);
|
||||
}
|
||||
|
||||
int GTreeNode::getChildIndex(const GTreeNode* child) const
|
||||
{
|
||||
CCASSERT(child != nullptr, "Argument must be non-nil");
|
||||
|
||||
return (int)_children.getIndex((GTreeNode*)child);
|
||||
}
|
||||
|
||||
void GTreeNode::setChildIndex(GTreeNode* 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");
|
||||
|
||||
moveChild(child, oldIndex, index);
|
||||
}
|
||||
|
||||
int GTreeNode::setChildIndexBefore(GTreeNode* 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 (oldIndex < index)
|
||||
return moveChild(child, oldIndex, index - 1);
|
||||
else
|
||||
return moveChild(child, oldIndex, index);
|
||||
}
|
||||
|
||||
int GTreeNode::moveChild(GTreeNode* 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 ((_tree != nullptr && this == _tree->getRootNode()) || (_cell != nullptr && _cell->getParent() != nullptr && _expanded))
|
||||
_tree->afterMoved(child);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void GTreeNode::swapChildren(GTreeNode* child1, GTreeNode* 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 GTreeNode::swapChildrenAt(int index1, int index2)
|
||||
{
|
||||
GTreeNode* child1 = _children.at(index1);
|
||||
GTreeNode* child2 = _children.at(index2);
|
||||
|
||||
setChildIndex(child1, index2);
|
||||
setChildIndex(child2, index1);
|
||||
}
|
||||
|
||||
int GTreeNode::numChildren() const
|
||||
{
|
||||
return (int)_children.size();
|
||||
}
|
||||
|
||||
void GTreeNode::setTree(GTree* value)
|
||||
{
|
||||
_tree = value;
|
||||
if (_tree != nullptr && _tree->treeNodeWillExpand != nullptr && _expanded)
|
||||
_tree->treeNodeWillExpand(this, true);
|
||||
|
||||
if (_isFolder)
|
||||
{
|
||||
for (auto& child : _children)
|
||||
{
|
||||
child->_level = _level + 1;
|
||||
child->setTree(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GTreeNode::setCell(GComponent* value)
|
||||
{
|
||||
if (_cell != value)
|
||||
{
|
||||
CC_SAFE_RELEASE(_cell);
|
||||
_cell = value;
|
||||
CC_SAFE_RETAIN(_cell);
|
||||
if (_cell)
|
||||
_cell->setData(this);
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef __GTREENODE_H__
|
||||
#define __GTREENODE_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GTree;
|
||||
class GComponent;
|
||||
|
||||
class GTreeNode : public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
static GTreeNode* create(bool isFolder = false, const std::string& resURL = cocos2d::STD_STRING_EMPTY);
|
||||
|
||||
GTreeNode();
|
||||
virtual ~GTreeNode();
|
||||
|
||||
GTreeNode* getParent() const { return _parent; }
|
||||
GTree* getTree() const { return _tree; }
|
||||
GComponent* getCell() const { return _cell; }
|
||||
const cocos2d::Value& getData() const { return _data; }
|
||||
void setData(const cocos2d::Value& value) { _data = value; }
|
||||
bool isExpanded() const { return _expanded; }
|
||||
void setExpaned(bool value);
|
||||
bool isFolder() const { return _isFolder; }
|
||||
const std::string& getText() const;
|
||||
void setText(const std::string& value);
|
||||
const std::string& getIcon() const;
|
||||
void setIcon(const std::string& value);
|
||||
|
||||
GTreeNode* addChild(GTreeNode* child);
|
||||
GTreeNode* addChildAt(GTreeNode* child, int index);
|
||||
|
||||
void removeChild(GTreeNode* child);
|
||||
void removeChildAt(int index);
|
||||
void removeChildren() { removeChildren(0, -1); }
|
||||
void removeChildren(int beginIndex, int endIndex);
|
||||
|
||||
GTreeNode* getChildAt(int index) const;
|
||||
GTreeNode* getPrevSibling() const;
|
||||
GTreeNode* getNextSibling() const;
|
||||
|
||||
int getChildIndex(const GTreeNode* child) const;
|
||||
void setChildIndex(GTreeNode* child, int index);
|
||||
int setChildIndexBefore(GTreeNode* child, int index);
|
||||
void swapChildren(GTreeNode* child1, GTreeNode* child2);
|
||||
void swapChildrenAt(int index1, int index2);
|
||||
|
||||
int numChildren() const;
|
||||
|
||||
private:
|
||||
bool init(bool isFolder, const std::string& resURL);
|
||||
int moveChild(GTreeNode* child, int oldIndex, int index);
|
||||
void setTree(GTree* value);
|
||||
void setCell(GComponent* value);
|
||||
|
||||
GTree* _tree;
|
||||
GTreeNode* _parent;
|
||||
GComponent* _cell;
|
||||
int _level;
|
||||
bool _expanded;
|
||||
bool _isFolder;
|
||||
cocos2d::Value _data;
|
||||
cocos2d::Vector<GTreeNode*> _children;
|
||||
std::string _resURL;
|
||||
|
||||
friend class GTree;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
#include "Margin.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
const Margin Margin::ZERO = Margin(0, 0, 0, 0);
|
||||
|
||||
Margin::Margin(void) : left(0), top(0), right(0), bottom(0)
|
||||
{
|
||||
}
|
||||
|
||||
Margin::Margin(float l, float t, float r, float b) : left(l), top(t), right(r), bottom(b)
|
||||
{
|
||||
}
|
||||
|
||||
Margin::Margin(const Margin& other) : left(other.left), top(other.top), right(other.right), bottom(other.bottom)
|
||||
{
|
||||
}
|
||||
|
||||
Margin& Margin::operator= (const Margin& other)
|
||||
{
|
||||
setMargin(other.left, other.top, other.right, other.bottom);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Margin::setMargin(float l, float t, float r, float b)
|
||||
{
|
||||
left = l;
|
||||
top = t;
|
||||
right = r;
|
||||
bottom = b;
|
||||
}
|
||||
|
||||
bool Margin::equals(const Margin &target) const
|
||||
{
|
||||
return (left == target.left && top == target.top && right == target.right && bottom == target.bottom);
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,78 @@
|
|||
#ifndef __MARGIN_H__
|
||||
#define __MARGIN_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
//copy from cocos2d::ui::Margin
|
||||
class Margin
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Left margin.
|
||||
*/
|
||||
float left;
|
||||
/**
|
||||
* Top margin.
|
||||
*/
|
||||
float top;
|
||||
/**
|
||||
* Right margin.
|
||||
*/
|
||||
float right;
|
||||
/**
|
||||
* Bottom margin.
|
||||
*/
|
||||
float bottom;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
Margin();
|
||||
|
||||
/**
|
||||
* Construct a Margin instance with left, top, right and bottom margins.
|
||||
*@param l Left margin in float.
|
||||
*@param t Top margin in float.
|
||||
*@param r Right margin in float.
|
||||
*@param b Bottom margin in float.
|
||||
*/
|
||||
Margin(float l, float t, float r, float b);
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
Margin(const Margin& other);
|
||||
|
||||
/**
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
Margin& operator= (const Margin& other);
|
||||
|
||||
/**
|
||||
* Change margin with left, top, right and bottom margin.
|
||||
*@param l Left margin in float.
|
||||
*@param t Top margin in float.
|
||||
*@param r Right margin in float.
|
||||
*@param b Bottom margin in float.
|
||||
*/
|
||||
void setMargin(float l, float t, float r, float b);
|
||||
|
||||
/**
|
||||
* Test equality of two margins.
|
||||
*@param target A Margin instance.
|
||||
*@return True if two margins are equal, false otherwise.
|
||||
*/
|
||||
bool equals(const Margin& target) const;
|
||||
|
||||
/**
|
||||
* A margin constant with all margins equal zero.
|
||||
*/
|
||||
static const Margin ZERO;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,75 @@
|
|||
#include "PackageItem.h"
|
||||
#include "GRoot.h"
|
||||
#include "UIPackage.h"
|
||||
#include "display/BitmapFont.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
PackageItem::PackageItem() : owner(nullptr),
|
||||
objectType(ObjectType::COMPONENT),
|
||||
width(0),
|
||||
height(0),
|
||||
rawData(nullptr),
|
||||
texture(nullptr),
|
||||
spriteFrame(nullptr),
|
||||
scale9Grid(nullptr),
|
||||
scaleByTile(false),
|
||||
tileGridIndice(0),
|
||||
animation(nullptr),
|
||||
repeatDelay(0),
|
||||
swing(false),
|
||||
extensionCreator(nullptr),
|
||||
translated(false),
|
||||
bitmapFont(nullptr),
|
||||
branches(nullptr),
|
||||
highResolution(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
PackageItem::~PackageItem()
|
||||
{
|
||||
CC_SAFE_DELETE(scale9Grid);
|
||||
|
||||
CC_SAFE_DELETE(rawData);
|
||||
if (bitmapFont) //bitmapfont will be released by fontatlas
|
||||
bitmapFont->releaseAtlas();
|
||||
bitmapFont = nullptr;
|
||||
CC_SAFE_RELEASE(animation);
|
||||
CC_SAFE_RELEASE(texture);
|
||||
CC_SAFE_RELEASE(spriteFrame);
|
||||
|
||||
CC_SAFE_DELETE(branches);
|
||||
CC_SAFE_DELETE(highResolution);
|
||||
}
|
||||
|
||||
void PackageItem::load()
|
||||
{
|
||||
owner->getItemAsset(this);
|
||||
}
|
||||
|
||||
PackageItem* PackageItem::getBranch()
|
||||
{
|
||||
if (branches != nullptr && owner->_branchIndex != -1)
|
||||
{
|
||||
std::string itemId = (*branches)[owner->_branchIndex];
|
||||
if (!itemId.empty())
|
||||
return owner->getItem(itemId);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
PackageItem* PackageItem::getHighResolution()
|
||||
{
|
||||
if (highResolution != nullptr && GRoot::contentScaleLevel > 0)
|
||||
{
|
||||
std::string itemId = (*highResolution)[GRoot::contentScaleLevel - 1];
|
||||
if (!itemId.empty())
|
||||
return owner->getItem(itemId);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef __PACKAGEITEM_H__
|
||||
#define __PACKAGEITEM_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class UIPackage;
|
||||
class UIObjectFactory;
|
||||
class GComponent;
|
||||
class BitmapFont;
|
||||
class PixelHitTestData;
|
||||
class ByteBuffer;
|
||||
|
||||
class PackageItem : public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
PackageItem();
|
||||
virtual ~PackageItem();
|
||||
|
||||
void load();
|
||||
PackageItem* getBranch();
|
||||
PackageItem* getHighResolution();
|
||||
|
||||
public:
|
||||
UIPackage* owner;
|
||||
|
||||
PackageItemType type;
|
||||
ObjectType objectType;
|
||||
std::string id;
|
||||
std::string name;
|
||||
int width;
|
||||
int height;
|
||||
std::string file;
|
||||
ByteBuffer* rawData;
|
||||
std::vector<std::string>* branches;
|
||||
std::vector<std::string>* highResolution;
|
||||
|
||||
//atlas
|
||||
cocos2d::Texture2D* texture;
|
||||
|
||||
//image
|
||||
cocos2d::Rect* scale9Grid;
|
||||
bool scaleByTile;
|
||||
int tileGridIndice;
|
||||
cocos2d::SpriteFrame* spriteFrame;
|
||||
PixelHitTestData* pixelHitTestData;
|
||||
|
||||
//movieclip
|
||||
cocos2d::Animation* animation;
|
||||
float delayPerUnit;
|
||||
float repeatDelay;
|
||||
bool swing;
|
||||
|
||||
//component
|
||||
std::function<GComponent*()> extensionCreator;
|
||||
bool translated;
|
||||
|
||||
//font
|
||||
BitmapFont* bitmapFont;
|
||||
|
||||
//skeleton
|
||||
cocos2d::Vec2* skeletonAnchor;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,239 @@
|
|||
#include "PopupMenu.h"
|
||||
#include "GRoot.h"
|
||||
#include "UIPackage.h"
|
||||
#include "GList.h"
|
||||
#include "GButton.h"
|
||||
#include "UIConfig.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
PopupMenu* PopupMenu::create(const std::string & resourceURL)
|
||||
{
|
||||
PopupMenu *pRet = new(std::nothrow) PopupMenu();
|
||||
if (pRet && pRet->init(resourceURL))
|
||||
{
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete pRet;
|
||||
pRet = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PopupMenu::PopupMenu() :
|
||||
_contentPane(nullptr),
|
||||
_list(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
PopupMenu::~PopupMenu()
|
||||
{
|
||||
CC_SAFE_RELEASE(_contentPane);
|
||||
}
|
||||
|
||||
bool PopupMenu::init(const std::string & resourceURL)
|
||||
{
|
||||
std::string url = resourceURL;
|
||||
if (url.empty())
|
||||
{
|
||||
url = UIConfig::popupMenu;
|
||||
if (url.empty())
|
||||
{
|
||||
CCLOGWARN("FairyGUI: UIConfig.popupMenu not defined");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_contentPane = UIPackage::createObjectFromURL(url)->as<GComponent>();
|
||||
_contentPane->retain();
|
||||
_contentPane->addEventListener(UIEventType::Enter, CC_CALLBACK_1(PopupMenu::onEnter, this));
|
||||
|
||||
_list = _contentPane->getChild("list")->as<GList>();
|
||||
_list->removeChildrenToPool();
|
||||
|
||||
_list->addRelation(_contentPane, RelationType::Width);
|
||||
_list->removeRelation(_contentPane, RelationType::Height);
|
||||
_contentPane->addRelation(_list, RelationType::Height);
|
||||
|
||||
_list->addEventListener(UIEventType::ClickItem, CC_CALLBACK_1(PopupMenu::onClickItem, this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GButton * PopupMenu::addItem(const std::string & caption, EventCallback callback)
|
||||
{
|
||||
GButton* item = _list->addItemFromPool()->as<GButton>();
|
||||
item->setTitle(caption);
|
||||
item->setGrayed(false);
|
||||
GController* c = item->getController("checked");
|
||||
if (c != nullptr)
|
||||
c->setSelectedIndex(0);
|
||||
item->removeEventListener(UIEventType::ClickMenu);
|
||||
if (callback)
|
||||
item->addEventListener(UIEventType::ClickMenu, callback);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
GButton * PopupMenu::addItemAt(const std::string & caption, int index, EventCallback callback)
|
||||
{
|
||||
GButton* item = _list->getFromPool(_list->getDefaultItem())->as<GButton>();
|
||||
_list->addChildAt(item, index);
|
||||
|
||||
item->setTitle(caption);
|
||||
item->setGrayed(false);
|
||||
GController* c = item->getController("checked");
|
||||
if (c != nullptr)
|
||||
c->setSelectedIndex(0);
|
||||
item->removeEventListener(UIEventType::ClickMenu);
|
||||
if (callback)
|
||||
item->addEventListener(UIEventType::ClickMenu, callback);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void PopupMenu::addSeperator()
|
||||
{
|
||||
if (UIConfig::popupMenu_seperator.empty())
|
||||
{
|
||||
CCLOGWARN("FairyGUI: UIConfig.popupMenu_seperator not defined");
|
||||
return;
|
||||
}
|
||||
|
||||
_list->addItemFromPool(UIConfig::popupMenu_seperator);
|
||||
}
|
||||
|
||||
const std::string & PopupMenu::getItemName(int index) const
|
||||
{
|
||||
GButton* item = _list->getChildAt(index)->as<GButton>();
|
||||
return item->name;
|
||||
}
|
||||
|
||||
void PopupMenu::setItemText(const std::string & name, const std::string & caption)
|
||||
{
|
||||
GButton* item = _list->getChild(name)->as<GButton>();
|
||||
item->setTitle(caption);
|
||||
}
|
||||
|
||||
void PopupMenu::setItemVisible(const std::string & name, bool visible)
|
||||
{
|
||||
GButton* item = _list->getChild(name)->as<GButton>();
|
||||
if (item->isVisible() != visible)
|
||||
{
|
||||
item->setVisible(visible);
|
||||
_list->setBoundsChangedFlag();
|
||||
}
|
||||
}
|
||||
|
||||
void PopupMenu::setItemGrayed(const std::string & name, bool grayed)
|
||||
{
|
||||
GButton* item = _list->getChild(name)->as<GButton>();
|
||||
item->setGrayed(grayed);
|
||||
}
|
||||
|
||||
void PopupMenu::setItemCheckable(const std::string & name, bool checkable)
|
||||
{
|
||||
GButton* item = _list->getChild(name)->as<GButton>();
|
||||
GController* c = item->getController("checked");
|
||||
if (c != nullptr)
|
||||
{
|
||||
if (checkable)
|
||||
{
|
||||
if (c->getSelectedIndex() == 0)
|
||||
c->setSelectedIndex(1);
|
||||
}
|
||||
else
|
||||
c->setSelectedIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
void PopupMenu::setItemChecked(const std::string & name, bool check)
|
||||
{
|
||||
GButton* item = _list->getChild(name)->as<GButton>();
|
||||
GController* c = item->getController("checked");
|
||||
if (c != nullptr)
|
||||
c->setSelectedIndex(check ? 2 : 1);
|
||||
}
|
||||
|
||||
bool PopupMenu::isItemChecked(const std::string & name) const
|
||||
{
|
||||
GButton* item = _list->getChild(name)->as<GButton>();
|
||||
GController* c = item->getController("checked");
|
||||
if (c != nullptr)
|
||||
return c->getSelectedIndex() == 2;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PopupMenu::removeItem(const std::string & name)
|
||||
{
|
||||
GObject* item = _list->getChild(name);
|
||||
if (item != nullptr)
|
||||
{
|
||||
int index = _list->getChildIndex(item);
|
||||
_list->removeChildToPoolAt(index);
|
||||
item->removeEventListener(UIEventType::ClickMenu);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void PopupMenu::clearItems()
|
||||
{
|
||||
int cnt = _list->numChildren();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
_list->getChildAt(i)->removeEventListener(UIEventType::ClickMenu);
|
||||
_list->removeChildrenToPool();
|
||||
}
|
||||
|
||||
int PopupMenu::getItemCount() const
|
||||
{
|
||||
return _list->numChildren();
|
||||
}
|
||||
|
||||
void PopupMenu::show(GObject * target, PopupDirection dir)
|
||||
{
|
||||
GRoot* r = target != nullptr ? target->getRoot() : UIRoot;
|
||||
r->showPopup(_contentPane, dynamic_cast<GRoot*>(target) ? nullptr : target, dir);
|
||||
}
|
||||
|
||||
void PopupMenu::onClickItem(EventContext * context)
|
||||
{
|
||||
GButton* item = ((GObject*)context->getData())->as<GButton>();
|
||||
if (item == nullptr)
|
||||
return;
|
||||
|
||||
if (item->isGrayed())
|
||||
{
|
||||
_list->setSelectedIndex(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
GController* c = item->getController("checked");
|
||||
if (c != nullptr && c->getSelectedIndex() != 0)
|
||||
{
|
||||
if (c->getSelectedIndex() == 1)
|
||||
c->setSelectedIndex(2);
|
||||
else
|
||||
c->setSelectedIndex(1);
|
||||
}
|
||||
|
||||
GRoot* r = (GRoot*)_contentPane->getParent();
|
||||
r->hidePopup(_contentPane);
|
||||
|
||||
item->dispatchEvent(UIEventType::ClickMenu, context->getData());
|
||||
}
|
||||
|
||||
void PopupMenu::onEnter(EventContext * context)
|
||||
{
|
||||
_list->setSelectedIndex(-1);
|
||||
_list->resizeToFit(INT_MAX, 10);
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef __POPUPMENU_H__
|
||||
#define __POPUPMENU_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
#include "event/UIEventDispatcher.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GObject;
|
||||
class GComponent;
|
||||
class GButton;
|
||||
class GList;
|
||||
|
||||
class PopupMenu : public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
static PopupMenu* create(const std::string& resourceURL);
|
||||
static PopupMenu* create() { return create(""); }
|
||||
|
||||
PopupMenu();
|
||||
virtual ~PopupMenu();
|
||||
|
||||
GButton* addItem(const std::string& caption, EventCallback callback);
|
||||
GButton* addItemAt(const std::string& caption, int index, EventCallback callback);
|
||||
void addSeperator();
|
||||
const std::string& getItemName(int index) const;
|
||||
void setItemText(const std::string& name, const std::string& caption);
|
||||
void setItemVisible(const std::string& name, bool visible);
|
||||
void setItemGrayed(const std::string& name, bool grayed);
|
||||
void setItemCheckable(const std::string& name, bool checkable);
|
||||
void setItemChecked(const std::string& name, bool check);
|
||||
bool isItemChecked(const std::string& name) const;
|
||||
bool removeItem(const std::string& name);
|
||||
void clearItems();
|
||||
int getItemCount() const;
|
||||
GComponent* getContentPane() const { return _contentPane; }
|
||||
GList* getList() const { return _list; }
|
||||
void show() { show(nullptr, PopupDirection::AUTO); }
|
||||
void show(GObject* target, PopupDirection dir);
|
||||
|
||||
protected:
|
||||
bool init(const std::string& resourceURL);
|
||||
|
||||
GComponent* _contentPane;
|
||||
GList* _list;
|
||||
|
||||
private:
|
||||
void onClickItem(EventContext* context);
|
||||
void onEnter(EventContext* context);
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,655 @@
|
|||
#include "RelationItem.h"
|
||||
#include "GComponent.h"
|
||||
#include "GGroup.h"
|
||||
#include "event/UIEventType.h"
|
||||
#include "utils/WeakPtr.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
RelationItem::RelationItem(GObject* owner) : _target(nullptr)
|
||||
{
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
RelationItem::~RelationItem()
|
||||
{
|
||||
releaseRefTarget(_target.ptr());
|
||||
}
|
||||
|
||||
void RelationItem::setTarget(GObject* value)
|
||||
{
|
||||
GObject* old = _target.ptr();
|
||||
if (old != value)
|
||||
{
|
||||
if (old)
|
||||
releaseRefTarget(old);
|
||||
_target = value;
|
||||
if (value)
|
||||
addRefTarget(value);
|
||||
}
|
||||
}
|
||||
|
||||
void RelationItem::add(RelationType relationType, bool usePercent)
|
||||
{
|
||||
if (relationType == RelationType::Size)
|
||||
{
|
||||
add(RelationType::Width, usePercent);
|
||||
add(RelationType::Height, usePercent);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& it : _defs)
|
||||
{
|
||||
if (it.type == relationType)
|
||||
return;
|
||||
}
|
||||
|
||||
internalAdd(relationType, usePercent);
|
||||
}
|
||||
|
||||
void RelationItem::internalAdd(RelationType relationType, bool usePercent)
|
||||
{
|
||||
if (relationType == RelationType::Size)
|
||||
{
|
||||
internalAdd(RelationType::Width, usePercent);
|
||||
internalAdd(RelationType::Height, usePercent);
|
||||
return;
|
||||
}
|
||||
|
||||
RelationDef info;
|
||||
info.percent = usePercent;
|
||||
info.type = relationType;
|
||||
info.axis = (relationType <= RelationType::Right_Right || relationType == RelationType::Width || (relationType >= RelationType::LeftExt_Left && relationType <= RelationType::RightExt_Right)) ? 0 : 1;
|
||||
_defs.push_back(info);
|
||||
|
||||
if (usePercent || relationType == RelationType::Left_Center || relationType == RelationType::Center_Center || relationType == RelationType::Right_Center || relationType == RelationType::Top_Middle || relationType == RelationType::Middle_Middle || relationType == RelationType::Bottom_Middle)
|
||||
_owner->setPixelSnapping(true);
|
||||
}
|
||||
|
||||
void RelationItem::remove(RelationType relationType)
|
||||
{
|
||||
if (relationType == RelationType::Size)
|
||||
{
|
||||
remove(RelationType::Width);
|
||||
remove(RelationType::Height);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto it = _defs.begin(); it != _defs.end(); ++it)
|
||||
{
|
||||
if (it->type == relationType)
|
||||
{
|
||||
_defs.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RelationItem::copyFrom(const RelationItem& source)
|
||||
{
|
||||
setTarget(source._target.ptr());
|
||||
|
||||
_defs.clear();
|
||||
for (auto& it : source._defs)
|
||||
_defs.push_back(it);
|
||||
}
|
||||
|
||||
bool RelationItem::isEmpty() const
|
||||
{
|
||||
return _defs.size() == 0;
|
||||
}
|
||||
|
||||
void RelationItem::applyOnSelfSizeChanged(float dWidth, float dHeight, bool applyPivot)
|
||||
{
|
||||
if (_target == nullptr || _defs.size() == 0)
|
||||
return;
|
||||
|
||||
float ox = _owner->_position.x;
|
||||
float oy = _owner->_position.y;
|
||||
|
||||
for (auto& it : _defs)
|
||||
{
|
||||
switch (it.type)
|
||||
{
|
||||
case RelationType::Center_Center:
|
||||
_owner->setX(_owner->_position.x - (0.5 - (applyPivot ? _owner->_pivot.x : 0)) * dWidth);
|
||||
break;
|
||||
|
||||
case RelationType::Right_Center:
|
||||
case RelationType::Right_Left:
|
||||
case RelationType::Right_Right:
|
||||
_owner->setX(_owner->_position.x - (1 - (applyPivot ? _owner->_pivot.x : 0)) * dWidth);
|
||||
break;
|
||||
|
||||
case RelationType::Middle_Middle:
|
||||
_owner->setY(_owner->_position.y - (0.5 - (applyPivot ? _owner->_pivot.y : 0)) * dHeight);
|
||||
break;
|
||||
|
||||
case RelationType::Bottom_Middle:
|
||||
case RelationType::Bottom_Top:
|
||||
case RelationType::Bottom_Bottom:
|
||||
_owner->setY(_owner->_position.y - (1 - (applyPivot ? _owner->_pivot.y : 0)) * dHeight);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ox != _owner->_position.x || oy != _owner->_position.y)
|
||||
{
|
||||
ox = _owner->_position.x - ox;
|
||||
oy = _owner->_position.y - oy;
|
||||
|
||||
_owner->updateGearFromRelations(1, ox, oy);
|
||||
|
||||
if (_owner->_parent != nullptr)
|
||||
{
|
||||
const Vector<Transition*>& arr = _owner->_parent->getTransitions();
|
||||
for (auto& it : arr)
|
||||
it->updateFromRelations(_owner->id, ox, oy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RelationItem::applyOnXYChanged(GObject* target, const RelationDef& info, float dx, float dy)
|
||||
{
|
||||
float tmp;
|
||||
|
||||
switch (info.type)
|
||||
{
|
||||
case RelationType::Left_Left:
|
||||
case RelationType::Left_Center:
|
||||
case RelationType::Left_Right:
|
||||
case RelationType::Center_Center:
|
||||
case RelationType::Right_Left:
|
||||
case RelationType::Right_Center:
|
||||
case RelationType::Right_Right:
|
||||
_owner->setX(_owner->_position.x + dx);
|
||||
break;
|
||||
|
||||
case RelationType::Top_Top:
|
||||
case RelationType::Top_Middle:
|
||||
case RelationType::Top_Bottom:
|
||||
case RelationType::Middle_Middle:
|
||||
case RelationType::Bottom_Top:
|
||||
case RelationType::Bottom_Middle:
|
||||
case RelationType::Bottom_Bottom:
|
||||
_owner->setY(_owner->_position.y + dy);
|
||||
break;
|
||||
|
||||
case RelationType::Width:
|
||||
case RelationType::Height:
|
||||
break;
|
||||
|
||||
case RelationType::LeftExt_Left:
|
||||
case RelationType::LeftExt_Right:
|
||||
if (_owner != target->getParent())
|
||||
{
|
||||
tmp = _owner->getXMin();
|
||||
_owner->setWidth(_owner->_rawSize.width - dx);
|
||||
_owner->setXMin(tmp + dx);
|
||||
}
|
||||
else
|
||||
_owner->setWidth(_owner->_rawSize.width - dx);
|
||||
break;
|
||||
|
||||
case RelationType::RightExt_Left:
|
||||
case RelationType::RightExt_Right:
|
||||
if (_owner != target->getParent())
|
||||
{
|
||||
tmp = _owner->getXMin();
|
||||
_owner->setWidth(_owner->_rawSize.width + dx);
|
||||
_owner->setXMin(tmp);
|
||||
}
|
||||
else
|
||||
_owner->setWidth(_owner->_rawSize.width + dx);
|
||||
break;
|
||||
|
||||
case RelationType::TopExt_Top:
|
||||
case RelationType::TopExt_Bottom:
|
||||
if (_owner != target->getParent())
|
||||
{
|
||||
tmp = _owner->getYMin();
|
||||
_owner->setHeight(_owner->_rawSize.height - dy);
|
||||
_owner->setYMin(tmp + dy);
|
||||
}
|
||||
else
|
||||
_owner->setHeight(_owner->_rawSize.height - dy);
|
||||
break;
|
||||
|
||||
case RelationType::BottomExt_Top:
|
||||
case RelationType::BottomExt_Bottom:
|
||||
if (_owner != target->getParent())
|
||||
{
|
||||
tmp = _owner->getYMin();
|
||||
_owner->setHeight(_owner->_rawSize.height + dy);
|
||||
_owner->setYMin(tmp);
|
||||
}
|
||||
else
|
||||
_owner->setHeight(_owner->_rawSize.height + dy);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RelationItem::applyOnSizeChanged(GObject* target, const RelationDef& info)
|
||||
{
|
||||
float pos = 0, pivot = 0, delta = 0;
|
||||
if (info.axis == 0)
|
||||
{
|
||||
if (target != _owner->_parent)
|
||||
{
|
||||
pos = target->_position.x;
|
||||
if (target->_pivotAsAnchor)
|
||||
pivot = target->_pivot.x;
|
||||
}
|
||||
|
||||
if (info.percent)
|
||||
{
|
||||
if (_targetData.z != 0)
|
||||
delta = target->_size.width / _targetData.z;
|
||||
}
|
||||
else
|
||||
delta = target->_size.width - _targetData.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target != _owner->_parent)
|
||||
{
|
||||
pos = target->_position.y;
|
||||
if (target->_pivotAsAnchor)
|
||||
pivot = target->_pivot.y;
|
||||
}
|
||||
|
||||
if (info.percent)
|
||||
{
|
||||
if (_targetData.w != 0)
|
||||
delta = target->_size.height / _targetData.w;
|
||||
}
|
||||
else
|
||||
delta = target->_size.height - _targetData.w;
|
||||
}
|
||||
|
||||
float v, tmp;
|
||||
|
||||
switch (info.type)
|
||||
{
|
||||
case RelationType::Left_Left:
|
||||
if (info.percent)
|
||||
_owner->setXMin(pos + (_owner->getXMin() - pos) * delta);
|
||||
else if (pivot != 0)
|
||||
_owner->setX(_owner->_position.x + delta * (-pivot));
|
||||
break;
|
||||
case RelationType::Left_Center:
|
||||
if (info.percent)
|
||||
_owner->setXMin(pos + (_owner->getXMin() - pos) * delta);
|
||||
else
|
||||
_owner->setX(_owner->_position.x + delta * (0.5f - pivot));
|
||||
break;
|
||||
case RelationType::Left_Right:
|
||||
if (info.percent)
|
||||
_owner->setXMin(pos + (_owner->getXMin() - pos) * delta);
|
||||
else
|
||||
_owner->setX(_owner->_position.x + delta * (1 - pivot));
|
||||
break;
|
||||
case RelationType::Center_Center:
|
||||
if (info.percent)
|
||||
_owner->setXMin(pos + (_owner->getXMin() + _owner->_rawSize.width * 0.5f - pos) * delta - _owner->_rawSize.width * 0.5f);
|
||||
else
|
||||
_owner->setX(_owner->_position.x + delta * (0.5f - pivot));
|
||||
break;
|
||||
case RelationType::Right_Left:
|
||||
if (info.percent)
|
||||
_owner->setXMin(pos + (_owner->getXMin() + _owner->_rawSize.width - pos) * delta - _owner->_rawSize.width);
|
||||
else if (pivot != 0)
|
||||
_owner->setX(_owner->_position.x + delta * (-pivot));
|
||||
break;
|
||||
case RelationType::Right_Center:
|
||||
if (info.percent)
|
||||
_owner->setXMin(pos + (_owner->getXMin() + _owner->_rawSize.width - pos) * delta - _owner->_rawSize.width);
|
||||
else
|
||||
_owner->setX(_owner->_position.x + delta * (0.5f - pivot));
|
||||
break;
|
||||
case RelationType::Right_Right:
|
||||
if (info.percent)
|
||||
_owner->setXMin(pos + (_owner->getXMin() + _owner->_rawSize.width - pos) * delta - _owner->_rawSize.width);
|
||||
else
|
||||
_owner->setX(_owner->_position.x + delta * (1 - pivot));
|
||||
break;
|
||||
|
||||
case RelationType::Top_Top:
|
||||
if (info.percent)
|
||||
_owner->setYMin(pos + (_owner->getYMin() - pos) * delta);
|
||||
else if (pivot != 0)
|
||||
_owner->setY(_owner->_position.y + delta * (-pivot));
|
||||
break;
|
||||
case RelationType::Top_Middle:
|
||||
if (info.percent)
|
||||
_owner->setYMin(pos + (_owner->getYMin() - pos) * delta);
|
||||
else
|
||||
_owner->setY(_owner->_position.y + delta * (0.5f - pivot));
|
||||
break;
|
||||
case RelationType::Top_Bottom:
|
||||
if (info.percent)
|
||||
_owner->setYMin(pos + (_owner->getYMin() - pos) * delta);
|
||||
else
|
||||
_owner->setY(_owner->_position.y + delta * (1 - pivot));
|
||||
break;
|
||||
case RelationType::Middle_Middle:
|
||||
if (info.percent)
|
||||
_owner->setYMin(pos + (_owner->getYMin() + _owner->_rawSize.height * 0.5f - pos) * delta - _owner->_rawSize.height * 0.5f);
|
||||
else
|
||||
_owner->setY(_owner->_position.y + delta * (0.5f - pivot));
|
||||
break;
|
||||
case RelationType::Bottom_Top:
|
||||
if (info.percent)
|
||||
_owner->setYMin(pos + (_owner->getYMin() + _owner->_rawSize.height - pos) * delta - _owner->_rawSize.height);
|
||||
else if (pivot != 0)
|
||||
_owner->setY(_owner->_position.y + delta * (-pivot));
|
||||
break;
|
||||
case RelationType::Bottom_Middle:
|
||||
if (info.percent)
|
||||
_owner->setYMin(pos + (_owner->getYMin() + _owner->_rawSize.height - pos) * delta - _owner->_rawSize.height);
|
||||
else
|
||||
_owner->setY(_owner->_position.y + delta * (0.5f - pivot));
|
||||
break;
|
||||
case RelationType::Bottom_Bottom:
|
||||
if (info.percent)
|
||||
_owner->setYMin(pos + (_owner->getYMin() + _owner->_rawSize.height - pos) * delta - _owner->_rawSize.height);
|
||||
else
|
||||
_owner->setY(_owner->_position.y + delta * (1 - pivot));
|
||||
break;
|
||||
|
||||
case RelationType::Width:
|
||||
if (_owner->_underConstruct && _owner == target->_parent)
|
||||
v = _owner->sourceSize.width - target->initSize.width;
|
||||
else
|
||||
v = _owner->_rawSize.width - _targetData.z;
|
||||
if (info.percent)
|
||||
v = v * delta;
|
||||
if (_target == _owner->_parent)
|
||||
{
|
||||
if (_owner->_pivotAsAnchor)
|
||||
{
|
||||
tmp = _owner->getXMin();
|
||||
_owner->setSize(target->_size.width + v, _owner->_rawSize.height, true);
|
||||
_owner->setXMin(tmp);
|
||||
}
|
||||
else
|
||||
_owner->setSize(target->_size.width + v, _owner->_rawSize.height, true);
|
||||
}
|
||||
else
|
||||
_owner->setWidth(target->_size.width + v);
|
||||
break;
|
||||
case RelationType::Height:
|
||||
if (_owner->_underConstruct && _owner == target->_parent)
|
||||
v = _owner->sourceSize.height - target->initSize.height;
|
||||
else
|
||||
v = _owner->_rawSize.height - _targetData.w;
|
||||
if (info.percent)
|
||||
v = v * delta;
|
||||
if (_target == _owner->_parent)
|
||||
{
|
||||
if (_owner->_pivotAsAnchor)
|
||||
{
|
||||
tmp = _owner->getYMin();
|
||||
_owner->setSize(_owner->_rawSize.width, target->_size.height + v, true);
|
||||
_owner->setYMin(tmp);
|
||||
}
|
||||
else
|
||||
_owner->setSize(_owner->_rawSize.width, target->_size.height + v, true);
|
||||
}
|
||||
else
|
||||
_owner->setHeight(target->_size.height + v);
|
||||
break;
|
||||
|
||||
case RelationType::LeftExt_Left:
|
||||
tmp = _owner->getXMin();
|
||||
if (info.percent)
|
||||
v = pos + (tmp - pos) * delta - tmp;
|
||||
else
|
||||
v = delta * (-pivot);
|
||||
_owner->setWidth(_owner->_rawSize.width - v);
|
||||
_owner->setXMin(tmp + v);
|
||||
break;
|
||||
case RelationType::LeftExt_Right:
|
||||
tmp = _owner->getXMin();
|
||||
if (info.percent)
|
||||
v = pos + (tmp - pos) * delta - tmp;
|
||||
else
|
||||
v = delta * (1 - pivot);
|
||||
_owner->setWidth(_owner->_rawSize.width - v);
|
||||
_owner->setXMin(tmp + v);
|
||||
break;
|
||||
case RelationType::RightExt_Left:
|
||||
tmp = _owner->getXMin();
|
||||
if (info.percent)
|
||||
v = pos + (tmp + _owner->_rawSize.width - pos) * delta - (tmp + _owner->_rawSize.width);
|
||||
else
|
||||
v = delta * (-pivot);
|
||||
_owner->setWidth(_owner->_rawSize.width + v);
|
||||
_owner->setXMin(tmp);
|
||||
break;
|
||||
case RelationType::RightExt_Right:
|
||||
tmp = _owner->getXMin();
|
||||
if (info.percent)
|
||||
{
|
||||
if (_owner == target->_parent)
|
||||
{
|
||||
if (_owner->_underConstruct)
|
||||
_owner->setWidth(pos + target->_size.width - target->_size.width * pivot +
|
||||
(_owner->sourceSize.width - pos - target->initSize.width + target->initSize.width * pivot) * delta);
|
||||
else
|
||||
_owner->setWidth(pos + (_owner->_rawSize.width - pos) * delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
v = pos + (tmp + _owner->_rawSize.width - pos) * delta - (tmp + _owner->_rawSize.width);
|
||||
_owner->setWidth(_owner->_rawSize.width + v);
|
||||
_owner->setXMin(tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_owner == target->_parent)
|
||||
{
|
||||
if (_owner->_underConstruct)
|
||||
_owner->setWidth(_owner->sourceSize.width + (target->_size.width - target->initSize.width) * (1 - pivot));
|
||||
else
|
||||
_owner->setWidth(_owner->_rawSize.width + delta * (1 - pivot));
|
||||
}
|
||||
else
|
||||
{
|
||||
v = delta * (1 - pivot);
|
||||
_owner->setWidth(_owner->_rawSize.width + v);
|
||||
_owner->setXMin(tmp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RelationType::TopExt_Top:
|
||||
tmp = _owner->getYMin();
|
||||
if (info.percent)
|
||||
v = pos + (tmp - pos) * delta - tmp;
|
||||
else
|
||||
v = delta * (-pivot);
|
||||
_owner->setHeight(_owner->_rawSize.height - v);
|
||||
_owner->setYMin(tmp + v);
|
||||
break;
|
||||
case RelationType::TopExt_Bottom:
|
||||
tmp = _owner->getYMin();
|
||||
if (info.percent)
|
||||
v = pos + (tmp - pos) * delta - tmp;
|
||||
else
|
||||
v = delta * (1 - pivot);
|
||||
_owner->setHeight(_owner->_rawSize.height - v);
|
||||
_owner->setYMin(tmp + v);
|
||||
break;
|
||||
case RelationType::BottomExt_Top:
|
||||
tmp = _owner->getYMin();
|
||||
if (info.percent)
|
||||
v = pos + (tmp + _owner->_rawSize.height - pos) * delta - (tmp + _owner->_rawSize.height);
|
||||
else
|
||||
v = delta * (-pivot);
|
||||
_owner->setHeight(_owner->_rawSize.height + v);
|
||||
_owner->setYMin(tmp);
|
||||
break;
|
||||
case RelationType::BottomExt_Bottom:
|
||||
tmp = _owner->getYMin();
|
||||
if (info.percent)
|
||||
{
|
||||
if (_owner == target->_parent)
|
||||
{
|
||||
if (_owner->_underConstruct)
|
||||
_owner->setHeight(pos + target->_size.height - target->_size.height * pivot +
|
||||
(_owner->sourceSize.height - pos - target->initSize.height + target->initSize.height * pivot) * delta);
|
||||
else
|
||||
_owner->setHeight(pos + (_owner->_rawSize.height - pos) * delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
v = pos + (tmp + _owner->_rawSize.height - pos) * delta - (tmp + _owner->_rawSize.height);
|
||||
_owner->setHeight(_owner->_rawSize.height + v);
|
||||
_owner->setYMin(tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_owner == target->_parent)
|
||||
{
|
||||
if (_owner->_underConstruct)
|
||||
_owner->setHeight(_owner->sourceSize.height + (target->_size.height - target->initSize.height) * (1 - pivot));
|
||||
else
|
||||
_owner->setHeight(_owner->_rawSize.height + delta * (1 - pivot));
|
||||
}
|
||||
else
|
||||
{
|
||||
v = delta * (1 - pivot);
|
||||
_owner->setHeight(_owner->_rawSize.height + v);
|
||||
_owner->setYMin(tmp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RelationItem::addRefTarget(GObject* target)
|
||||
{
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (target != _owner->_parent)
|
||||
target->addEventListener(UIEventType::PositionChange, CC_CALLBACK_1(RelationItem::onTargetXYChanged, this), EventTag(this));
|
||||
target->addEventListener(UIEventType::SizeChange, CC_CALLBACK_1(RelationItem::onTargetSizeChanged, this), EventTag(this));
|
||||
|
||||
_targetData.x = target->_position.x;
|
||||
_targetData.y = target->_position.y;
|
||||
_targetData.z = target->_size.width;
|
||||
_targetData.w = target->_size.height;
|
||||
}
|
||||
|
||||
void RelationItem::releaseRefTarget(GObject* target)
|
||||
{
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target->removeEventListener(UIEventType::PositionChange, EventTag(this));
|
||||
target->removeEventListener(UIEventType::SizeChange, EventTag(this));
|
||||
}
|
||||
|
||||
void RelationItem::onTargetXYChanged(EventContext* context)
|
||||
{
|
||||
GObject* target = (GObject*)context->getSender();
|
||||
if (_owner->relations()->handling != nullptr || (_owner->_group != nullptr && _owner->_group->_updating != 0))
|
||||
{
|
||||
_targetData.x = target->_position.x;
|
||||
_targetData.y = target->_position.y;
|
||||
return;
|
||||
}
|
||||
|
||||
_owner->relations()->handling = target;
|
||||
|
||||
float ox = _owner->_position.x;
|
||||
float oy = _owner->_position.y;
|
||||
float dx = target->_position.x - _targetData.x;
|
||||
float dy = target->_position.y - _targetData.y;
|
||||
|
||||
for (auto& it : _defs)
|
||||
applyOnXYChanged(target, it, dx, dy);
|
||||
|
||||
_targetData.x = target->_position.x;
|
||||
_targetData.y = target->_position.y;
|
||||
|
||||
if (ox != _owner->_position.x || oy != _owner->_position.y)
|
||||
{
|
||||
ox = _owner->_position.x - ox;
|
||||
oy = _owner->_position.y - oy;
|
||||
|
||||
_owner->updateGearFromRelations(1, ox, oy);
|
||||
|
||||
if (_owner->_parent != nullptr)
|
||||
{
|
||||
const Vector<Transition*>& arr = _owner->_parent->getTransitions();
|
||||
for (auto& it : arr)
|
||||
it->updateFromRelations(_owner->id, ox, oy);
|
||||
}
|
||||
}
|
||||
|
||||
_owner->relations()->handling = nullptr;
|
||||
}
|
||||
|
||||
void RelationItem::onTargetSizeChanged(EventContext* context)
|
||||
{
|
||||
GObject* target = (GObject*)context->getSender();
|
||||
if (_owner->relations()->handling != nullptr || (_owner->_group != nullptr && _owner->_group->_updating != 0))
|
||||
{
|
||||
_targetData.z = target->_size.width;
|
||||
_targetData.w = target->_size.height;
|
||||
return;
|
||||
}
|
||||
|
||||
_owner->relations()->handling = target;
|
||||
|
||||
float ox = _owner->_position.x;
|
||||
float oy = _owner->_position.y;
|
||||
float ow = _owner->_rawSize.width;
|
||||
float oh = _owner->_rawSize.height;
|
||||
|
||||
for (auto& it : _defs)
|
||||
applyOnSizeChanged(target, it);
|
||||
|
||||
_targetData.z = target->_size.width;
|
||||
_targetData.w = target->_size.height;
|
||||
|
||||
if (ox != _owner->_position.x || oy != _owner->_position.y)
|
||||
{
|
||||
ox = _owner->_position.x - ox;
|
||||
oy = _owner->_position.y - oy;
|
||||
|
||||
_owner->updateGearFromRelations(1, ox, oy);
|
||||
|
||||
if (_owner->_parent != nullptr)
|
||||
{
|
||||
const Vector<Transition*>& arr = _owner->_parent->getTransitions();
|
||||
for (auto& it : arr)
|
||||
it->updateFromRelations(_owner->id, ox, oy);
|
||||
}
|
||||
}
|
||||
|
||||
if (ow != _owner->_rawSize.width || oh != _owner->_rawSize.height)
|
||||
{
|
||||
ow = _owner->_rawSize.width - ow;
|
||||
oh = _owner->_rawSize.height - oh;
|
||||
|
||||
_owner->updateGearFromRelations(2, ow, oh);
|
||||
}
|
||||
|
||||
_owner->relations()->handling = nullptr;
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,95 @@
|
|||
#ifndef __RELATIONITEM_H__
|
||||
#define __RELATIONITEM_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "utils/WeakPtr.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GObject;
|
||||
class EventContext;
|
||||
|
||||
enum class RelationType
|
||||
{
|
||||
Left_Left,
|
||||
Left_Center,
|
||||
Left_Right,
|
||||
Center_Center,
|
||||
Right_Left,
|
||||
Right_Center,
|
||||
Right_Right,
|
||||
|
||||
Top_Top,
|
||||
Top_Middle,
|
||||
Top_Bottom,
|
||||
Middle_Middle,
|
||||
Bottom_Top,
|
||||
Bottom_Middle,
|
||||
Bottom_Bottom,
|
||||
|
||||
Width,
|
||||
Height,
|
||||
|
||||
LeftExt_Left,
|
||||
LeftExt_Right,
|
||||
RightExt_Left,
|
||||
RightExt_Right,
|
||||
TopExt_Top,
|
||||
TopExt_Bottom,
|
||||
BottomExt_Top,
|
||||
BottomExt_Bottom,
|
||||
|
||||
Size
|
||||
};
|
||||
|
||||
class RelationDef
|
||||
{
|
||||
public:
|
||||
bool percent;
|
||||
RelationType type;
|
||||
int axis;
|
||||
|
||||
RelationDef() {}
|
||||
|
||||
RelationDef(const RelationDef& source)
|
||||
{
|
||||
this->percent = source.percent;
|
||||
this->type = source.type;
|
||||
this->axis = source.axis;
|
||||
}
|
||||
};
|
||||
|
||||
class RelationItem
|
||||
{
|
||||
public:
|
||||
RelationItem(GObject* owner);
|
||||
~RelationItem();
|
||||
|
||||
GObject* getTarget() { return _target.ptr(); }
|
||||
void setTarget(GObject* value);
|
||||
|
||||
void add(RelationType relationType, bool usePercent);
|
||||
void internalAdd(RelationType relationType, bool usePercent);
|
||||
void remove(RelationType relationType);
|
||||
void copyFrom(const RelationItem& source);
|
||||
bool isEmpty() const;
|
||||
void applyOnSelfSizeChanged(float dWidth, float dHeight, bool applyPivot);
|
||||
|
||||
private:
|
||||
void applyOnXYChanged(GObject* target, const RelationDef& info, float dx, float dy);
|
||||
void applyOnSizeChanged(GObject* target, const RelationDef& info);
|
||||
void addRefTarget(GObject* target);
|
||||
void releaseRefTarget(GObject* target);
|
||||
void onTargetXYChanged(EventContext* context);
|
||||
void onTargetSizeChanged(EventContext* context);
|
||||
|
||||
GObject* _owner;
|
||||
WeakPtr _target;
|
||||
std::vector<RelationDef> _defs;
|
||||
cocos2d::Vec4 _targetData;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,145 @@
|
|||
#include "Relations.h"
|
||||
#include "GComponent.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
Relations::Relations(GObject* owner) :
|
||||
handling(nullptr)
|
||||
{
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
Relations::~Relations()
|
||||
{
|
||||
clearAll();
|
||||
}
|
||||
|
||||
void Relations::add(GObject * target, RelationType relationType)
|
||||
{
|
||||
add(target, relationType, false);
|
||||
}
|
||||
|
||||
void Relations::add(GObject * target, RelationType relationType, bool usePercent)
|
||||
{
|
||||
CCASSERT(target, "target is null");
|
||||
|
||||
for (auto it = _items.begin(); it != _items.end(); ++it)
|
||||
{
|
||||
if ((*it)->getTarget() == target)
|
||||
{
|
||||
(*it)->add(relationType, usePercent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
RelationItem* newItem = new RelationItem(_owner);
|
||||
newItem->setTarget(target);
|
||||
newItem->add(relationType, usePercent);
|
||||
_items.push_back(newItem);
|
||||
}
|
||||
|
||||
void Relations::remove(GObject * target, RelationType relationType)
|
||||
{
|
||||
for (auto it = _items.begin(); it != _items.end(); )
|
||||
{
|
||||
if ((*it)->getTarget() == target)
|
||||
{
|
||||
(*it)->remove(relationType);
|
||||
if ((*it)->isEmpty())
|
||||
{
|
||||
delete (*it);
|
||||
it = _items.erase(it);
|
||||
}
|
||||
else
|
||||
it++;
|
||||
}
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
bool Relations::contains(GObject * target)
|
||||
{
|
||||
for (auto it = _items.begin(); it != _items.end(); ++it)
|
||||
{
|
||||
if ((*it)->getTarget() == target)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Relations::clearFor(GObject * target)
|
||||
{
|
||||
for (auto it = _items.begin(); it != _items.end(); )
|
||||
{
|
||||
if ((*it)->getTarget() == target)
|
||||
{
|
||||
delete (*it);
|
||||
it = _items.erase(it);
|
||||
}
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void Relations::clearAll()
|
||||
{
|
||||
for (auto it = _items.begin(); it != _items.end(); ++it)
|
||||
delete (*it);
|
||||
_items.clear();
|
||||
}
|
||||
|
||||
void Relations::copyFrom(const Relations & source)
|
||||
{
|
||||
clearAll();
|
||||
|
||||
for (auto it = source._items.begin(); it != source._items.end(); ++it)
|
||||
{
|
||||
RelationItem* item = new RelationItem(_owner);
|
||||
item->copyFrom(**it);
|
||||
_items.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
void Relations::onOwnerSizeChanged(float dWidth, float dHeight, bool applyPivot)
|
||||
{
|
||||
for (auto it = _items.begin(); it != _items.end(); ++it)
|
||||
(*it)->applyOnSelfSizeChanged(dWidth, dHeight, applyPivot);
|
||||
}
|
||||
|
||||
bool Relations::isEmpty() const
|
||||
{
|
||||
return _items.size() == 0;
|
||||
}
|
||||
|
||||
void Relations::setup(ByteBuffer * buffer, bool parentToChild)
|
||||
{
|
||||
int cnt = buffer->readByte();
|
||||
GObject* target;
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
int targetIndex = buffer->readShort();
|
||||
if (targetIndex == -1)
|
||||
target = _owner->getParent();
|
||||
else if (parentToChild)
|
||||
target = (dynamic_cast<GComponent*>(_owner))->getChildAt(targetIndex);
|
||||
else
|
||||
target = _owner->getParent()->getChildAt(targetIndex);
|
||||
|
||||
RelationItem* newItem = new RelationItem(_owner);
|
||||
newItem->setTarget(target);
|
||||
_items.push_back(newItem);
|
||||
|
||||
int cnt2 = buffer->readByte();
|
||||
for (int j = 0; j < cnt2; j++)
|
||||
{
|
||||
RelationType rt = (RelationType)buffer->readByte();
|
||||
bool usePercent = buffer->readBool();
|
||||
newItem->internalAdd(rt, usePercent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef __RELATIONS_H__
|
||||
#define __RELATIONS_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "RelationItem.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GObject;
|
||||
class ByteBuffer;
|
||||
|
||||
class Relations
|
||||
{
|
||||
public:
|
||||
Relations(GObject* owner);
|
||||
~Relations();
|
||||
|
||||
void add(GObject* target, RelationType relationType);
|
||||
void add(GObject* target, RelationType relationType, bool usePercent);
|
||||
void remove(GObject* target, RelationType relationType);
|
||||
bool contains(GObject* target);
|
||||
void clearFor(GObject* target);
|
||||
void clearAll();
|
||||
void copyFrom(const Relations& source);
|
||||
void onOwnerSizeChanged(float dWidth, float dHeight, bool applyPivot);
|
||||
bool isEmpty() const;
|
||||
void setup(ByteBuffer* buffer, bool parentToChild);
|
||||
|
||||
GObject* handling;
|
||||
|
||||
private:
|
||||
GObject* _owner;
|
||||
std::vector<RelationItem*> _items;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,219 @@
|
|||
#ifndef __SCROLLPANE_H__
|
||||
#define __SCROLLPANE_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "Margin.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GObject;
|
||||
class GComponent;
|
||||
class GScrollBar;
|
||||
class FUIContainer;
|
||||
class FUIInnerContainer;
|
||||
class GController;
|
||||
class EventContext;
|
||||
class ByteBuffer;
|
||||
class GTweener;
|
||||
|
||||
class ScrollPane : public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
ScrollPane(GComponent* owner);
|
||||
virtual ~ScrollPane();
|
||||
|
||||
void setup(ByteBuffer* buffer);
|
||||
|
||||
GComponent* getOwner() const { return _owner; }
|
||||
GComponent* getHeader() const { return _header; }
|
||||
GComponent* getFooter() const { return _footer; }
|
||||
GScrollBar* getVtScrollBar() const { return _vtScrollBar; }
|
||||
GScrollBar* getHzScrollBar() const { return _hzScrollBar; }
|
||||
|
||||
bool isBouncebackEffect() const { return _bouncebackEffect; }
|
||||
void setBouncebackEffect(bool value) { _bouncebackEffect = value; }
|
||||
|
||||
bool isTouchEffect() const { return _touchEffect; }
|
||||
void setTouchEffect(bool value) { _touchEffect = value; }
|
||||
|
||||
bool isInertiaDisabled() const { return _inertiaDisabled; }
|
||||
void setInertiaDisabled(bool value) { _inertiaDisabled = value; }
|
||||
|
||||
float getScrollStep() const { return _scrollStep; }
|
||||
void setScrollStep(float value);
|
||||
|
||||
bool isSnapToItem() const { return _snapToItem; }
|
||||
void setSnapToItem(bool value) { _snapToItem = value; }
|
||||
|
||||
bool isPageMode() const { return _pageMode; }
|
||||
void setPageMode(bool value) { _pageMode = value; }
|
||||
|
||||
GController* getPageController() const { return _pageController; }
|
||||
void setPageController(GController* value) { _pageController = value; }
|
||||
|
||||
bool isMouseWheelEnabled() const { return _mouseWheelEnabled; }
|
||||
void setMouseWheelEnabled(bool value) { _mouseWheelEnabled = value; }
|
||||
|
||||
float getDecelerationRate() const { return _decelerationRate; }
|
||||
void setDecelerationRate(float value) { _decelerationRate = value; }
|
||||
|
||||
float getPosX() const { return _xPos; }
|
||||
void setPosX(float value, bool ani = false);
|
||||
float getPosY() const { return _yPos; }
|
||||
void setPosY(float value, bool ani = false);
|
||||
|
||||
float getPercX() const;
|
||||
void setPercX(float value, bool ani = false);
|
||||
float getPercY() const;
|
||||
void setPercY(float value, bool ani = false);
|
||||
|
||||
bool isBottomMost() const;
|
||||
bool isRightMost() const;
|
||||
|
||||
void scrollLeft(float ratio = 1, bool ani = false);
|
||||
void scrollRight(float ratio = 1, bool ani = false);
|
||||
void scrollUp(float ratio = 1, bool ani = false);
|
||||
void scrollDown(float ratio = 1, bool ani = false);
|
||||
void scrollTop(bool ani = false);
|
||||
void scrollBottom(bool ani = false);
|
||||
void scrollToView(GObject* obj, bool ani = false, bool setFirst = false);
|
||||
void scrollToView(const cocos2d::Rect& rect, bool ani = false, bool setFirst = false);
|
||||
bool isChildInView(GObject* obj) const;
|
||||
|
||||
int getPageX() const;
|
||||
void setPageX(int value, bool ani = false);
|
||||
int getPageY() const;
|
||||
void setPageY(int value, bool ani = false);
|
||||
|
||||
float getScrollingPosX() const;
|
||||
float getScrollingPosY() const;
|
||||
|
||||
const cocos2d::Size& getContentSize() const { return _contentSize; }
|
||||
const cocos2d::Size& getViewSize() const { return _viewSize; }
|
||||
|
||||
void lockHeader(int size);
|
||||
void lockFooter(int size);
|
||||
|
||||
void cancelDragging();
|
||||
static ScrollPane* getDraggingPane() { return _draggingPane; }
|
||||
|
||||
private:
|
||||
void onOwnerSizeChanged();
|
||||
void adjustMaskContainer();
|
||||
void setContentSize(float wv, float hv);
|
||||
void changeContentSizeOnScrolling(float deltaWidth, float deltaHeight, float deltaPosX, float deltaPosY);
|
||||
void setViewWidth(float value);
|
||||
void setViewHeight(float value);
|
||||
void setSize(float wv, float hv);
|
||||
void handleSizeChanged();
|
||||
|
||||
void handleControllerChanged(GController* c);
|
||||
void updatePageController();
|
||||
|
||||
GObject* hitTest(const cocos2d::Vec2& pt, const cocos2d::Camera* camera);
|
||||
|
||||
void posChanged(bool ani);
|
||||
CALL_LATER_FUNC(ScrollPane, refresh);
|
||||
void refresh2();
|
||||
|
||||
void updateScrollBarPos();
|
||||
void updateScrollBarVisible();
|
||||
void updateScrollBarVisible2(GScrollBar* bar);
|
||||
|
||||
float getLoopPartSize(float division, int axis);
|
||||
bool loopCheckingCurrent();
|
||||
void loopCheckingTarget(cocos2d::Vec2& endPos);
|
||||
void loopCheckingTarget(cocos2d::Vec2& endPos, int axis);
|
||||
void loopCheckingNewPos(float& value, int axis);
|
||||
void alignPosition(cocos2d::Vec2& pos, bool inertialScrolling);
|
||||
float alignByPage(float pos, int axis, bool inertialScrolling);
|
||||
cocos2d::Vec2 updateTargetAndDuration(const cocos2d::Vec2& orignPos);
|
||||
float updateTargetAndDuration(float pos, int axis);
|
||||
void fixDuration(int axis, float oldChange);
|
||||
void startTween(int type);
|
||||
void killTween();
|
||||
void tweenUpdate(float dt);
|
||||
float runTween(int axis, float dt);
|
||||
|
||||
void checkRefreshBar();
|
||||
|
||||
void onTouchBegin(EventContext* context);
|
||||
void onTouchMove(EventContext* context);
|
||||
void onTouchEnd(EventContext* context);
|
||||
void onMouseWheel(EventContext* context);
|
||||
void onRollOver(EventContext* context);
|
||||
void onRollOut(EventContext* context);
|
||||
void onBarTweenComplete(GTweener* tweener);
|
||||
|
||||
ScrollType _scrollType;
|
||||
float _scrollStep;
|
||||
float _mouseWheelStep;
|
||||
Margin _scrollBarMargin;
|
||||
bool _bouncebackEffect;
|
||||
bool _touchEffect;
|
||||
bool _scrollBarDisplayAuto;
|
||||
bool _vScrollNone;
|
||||
bool _hScrollNone;
|
||||
bool _needRefresh;
|
||||
int _refreshBarAxis;
|
||||
bool _displayOnLeft;
|
||||
bool _snapToItem;
|
||||
bool _displayInDemand;
|
||||
bool _mouseWheelEnabled;
|
||||
bool _inertiaDisabled;
|
||||
float _decelerationRate;
|
||||
bool _pageMode;
|
||||
bool _floating;
|
||||
bool _dontClipMargin;
|
||||
|
||||
float _xPos;
|
||||
float _yPos;
|
||||
|
||||
cocos2d::Size _viewSize;
|
||||
cocos2d::Size _contentSize;
|
||||
cocos2d::Size _overlapSize;
|
||||
cocos2d::Size _pageSize;
|
||||
|
||||
cocos2d::Vec2 _containerPos;
|
||||
cocos2d::Vec2 _beginTouchPos;
|
||||
cocos2d::Vec2 _lastTouchPos;
|
||||
cocos2d::Vec2 _lastTouchGlobalPos;
|
||||
cocos2d::Vec2 _velocity;
|
||||
float _velocityScale;
|
||||
clock_t _lastMoveTime;
|
||||
bool _dragged;
|
||||
bool _isHoldAreaDone;
|
||||
int _aniFlag;
|
||||
int _loop;
|
||||
bool _hover;
|
||||
|
||||
int _headerLockedSize;
|
||||
int _footerLockedSize;
|
||||
|
||||
int _tweening;
|
||||
cocos2d::Vec2 _tweenStart;
|
||||
cocos2d::Vec2 _tweenChange;
|
||||
cocos2d::Vec2 _tweenTime;
|
||||
cocos2d::Vec2 _tweenDuration;
|
||||
|
||||
GComponent* _owner;
|
||||
FUIContainer* _maskContainer;
|
||||
FUIInnerContainer* _container;
|
||||
GScrollBar* _hzScrollBar;
|
||||
GScrollBar* _vtScrollBar;
|
||||
GComponent* _header;
|
||||
GComponent* _footer;
|
||||
GController* _pageController;
|
||||
|
||||
static int _gestureFlag;
|
||||
static ScrollPane* _draggingPane;
|
||||
|
||||
friend class GComponent;
|
||||
friend class GList;
|
||||
friend class GScrollBar;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,94 @@
|
|||
#ifndef __TRANSITION_H__
|
||||
#define __TRANSITION_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GObject;
|
||||
class GComponent;
|
||||
class TransitionItem;
|
||||
class GTweener;
|
||||
class ByteBuffer;
|
||||
|
||||
class Transition : public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
typedef std::function<void()> PlayCompleteCallback;
|
||||
typedef std::function<void()> TransitionHook;
|
||||
|
||||
Transition(GComponent* owner);
|
||||
virtual ~Transition();
|
||||
|
||||
GComponent* getOwner() const { return _owner; }
|
||||
bool isPlaying() const { return _playing; }
|
||||
|
||||
void play(PlayCompleteCallback callback = nullptr);
|
||||
void play(int times, float delay, PlayCompleteCallback callback = nullptr);
|
||||
void play(int times, float delay, float startTime, float endTime, PlayCompleteCallback callback = nullptr);
|
||||
void playReverse(PlayCompleteCallback callback = nullptr);
|
||||
void playReverse(int times, float delay, PlayCompleteCallback callback = nullptr);
|
||||
void changePlayTimes(int value);
|
||||
void stop();
|
||||
void stop(bool setToComplete, bool processCallback);
|
||||
void setAutoPlay(bool autoPlay, int times, float delay);
|
||||
void setPaused(bool paused);
|
||||
|
||||
void setValue(const std::string& label, const cocos2d::ValueVector& values);
|
||||
void setHook(const std::string& label, TransitionHook callback);
|
||||
void clearHooks();
|
||||
void setTarget(const std::string& label, GObject* newTarget);
|
||||
void setDuration(const std::string& label, float value);
|
||||
float getLabelTime(const std::string& label) const;
|
||||
float getTimeScale() const { return _timeScale; }
|
||||
void setTimeScale(float value);
|
||||
|
||||
void updateFromRelations(const std::string& targetId, float dx, float dy);
|
||||
void onOwnerAddedToStage();
|
||||
void onOwnerRemovedFromStage();
|
||||
|
||||
void setup(ByteBuffer* buffer);
|
||||
|
||||
std::string name;
|
||||
|
||||
private:
|
||||
void play(int times, float delay, float startTime, float endTime, PlayCompleteCallback onComplete, bool reverse);
|
||||
void stopItem(TransitionItem* item, bool setToComplete);
|
||||
void onDelayedPlay();
|
||||
void internalPlay();
|
||||
void playItem(TransitionItem* item);
|
||||
void skipAnimations();
|
||||
void onDelayedPlayItem(GTweener* tweener);
|
||||
void onTweenStart(GTweener* tweener);
|
||||
void onTweenUpdate(GTweener* tweener);
|
||||
void onTweenComplete(GTweener* tweener);
|
||||
void onPlayTransCompleted(TransitionItem* item);
|
||||
void callHook(TransitionItem* item, bool tweenEnd);
|
||||
void checkAllComplete();
|
||||
void applyValue(TransitionItem* item);
|
||||
void decodeValue(TransitionItem* item, ByteBuffer* buffer, void* value);
|
||||
|
||||
GComponent* _owner;
|
||||
std::vector<TransitionItem*> _items;
|
||||
int _totalTimes;
|
||||
int _totalTasks;
|
||||
bool _playing;
|
||||
bool _paused;
|
||||
float _ownerBaseX;
|
||||
float _ownerBaseY;
|
||||
PlayCompleteCallback _onComplete;
|
||||
int _options;
|
||||
bool _reversed;
|
||||
float _totalDuration;
|
||||
bool _autoPlay;
|
||||
int _autoPlayTimes;
|
||||
float _autoPlayDelay;
|
||||
float _timeScale;
|
||||
float _startTime;
|
||||
float _endTime;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,291 @@
|
|||
#include "TranslationHelper.h"
|
||||
#include "PackageItem.h"
|
||||
#include "UIPackage.h"
|
||||
#if defined(ENGINEX_VERSION)
|
||||
#include "pugixml/pugixml_imp.hpp"
|
||||
#else
|
||||
#include "tinyxml2/tinyxml2.h"
|
||||
#endif
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
USING_NS_CC;
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
using namespace std;
|
||||
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> TranslationHelper::strings;
|
||||
|
||||
void TranslationHelper::loadFromXML(const char* xmlString, size_t nBytes)
|
||||
{
|
||||
strings.clear();
|
||||
|
||||
#if defined(ENGINEX_VERSION)
|
||||
pugi::xml_document doc;
|
||||
if (doc.load_buffer(xmlString, nBytes)) {
|
||||
auto root = doc.document_element();
|
||||
auto ele = doc.child("string");
|
||||
while (ele)
|
||||
{
|
||||
std::string key = ele.attribute("name").value();
|
||||
std::string text = ele.text().as_string();
|
||||
size_t i = key.find("-");
|
||||
if (i == std::string::npos)
|
||||
continue;
|
||||
|
||||
std::string key2 = key.substr(0, i);
|
||||
std::string key3 = key.substr(i + 1);
|
||||
std::unordered_map<std::string, std::string>& col = strings[key2];
|
||||
col[key3] = text;
|
||||
|
||||
ele = ele.next_sibling("string");
|
||||
}
|
||||
}
|
||||
#else
|
||||
tinyxml2::XMLDocument* xml = new tinyxml2::XMLDocument();
|
||||
xml->Parse(xmlString, nBytes);
|
||||
|
||||
tinyxml2::XMLElement* root = xml->RootElement();
|
||||
tinyxml2::XMLElement* ele = root->FirstChildElement("string");
|
||||
while (ele)
|
||||
{
|
||||
std::string key = ele->Attribute("name");
|
||||
std::string text = ele->GetText();
|
||||
size_t i = key.find("-");
|
||||
if (i == std::string::npos)
|
||||
continue;
|
||||
|
||||
std::string key2 = key.substr(0, i);
|
||||
std::string key3 = key.substr(i + 1);
|
||||
std::unordered_map<std::string, std::string>& col = strings[key2];
|
||||
col[key3] = text;
|
||||
|
||||
ele = ele->NextSiblingElement("string");
|
||||
}
|
||||
|
||||
delete xml;
|
||||
#endif
|
||||
}
|
||||
|
||||
void TranslationHelper::translateComponent(PackageItem* item)
|
||||
{
|
||||
if (strings.empty())
|
||||
return;
|
||||
|
||||
auto col = strings.find(item->owner->getId() + item->id);
|
||||
if (col == strings.end())
|
||||
return;
|
||||
|
||||
std::unordered_map<std::string, std::string>& strings = col->second;
|
||||
|
||||
ByteBuffer* buffer = item->rawData;
|
||||
|
||||
buffer->seek(0, 2);
|
||||
|
||||
int childCount = buffer->readShort();
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
int dataLen = buffer->readShort();
|
||||
int curPos = buffer->getPos();
|
||||
|
||||
buffer->seek(curPos, 0);
|
||||
|
||||
ObjectType baseType = (ObjectType)buffer->readByte();
|
||||
ObjectType type = baseType;
|
||||
|
||||
buffer->skip(4);
|
||||
const string& elementId = buffer->readS();
|
||||
|
||||
if (type == ObjectType::COMPONENT)
|
||||
{
|
||||
if (buffer->seek(curPos, 6))
|
||||
type = (ObjectType)buffer->readByte();
|
||||
}
|
||||
|
||||
buffer->seek(curPos, 1);
|
||||
|
||||
auto it = strings.find(elementId + "-tips");
|
||||
if (it != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
|
||||
buffer->seek(curPos, 2);
|
||||
|
||||
int gearCnt = buffer->readShort();
|
||||
for (int j = 0; j < gearCnt; j++)
|
||||
{
|
||||
int nextPos = buffer->readShort();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
if (buffer->readByte() == 6) //gearText
|
||||
{
|
||||
buffer->skip(2); //controller
|
||||
int valueCnt = buffer->readShort();
|
||||
for (int k = 0; k < valueCnt; k++)
|
||||
{
|
||||
const string& page = buffer->readS();
|
||||
if (!page.empty())
|
||||
{
|
||||
if ((it = strings.find(elementId + "-texts_" + Value(k).asString())) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
else
|
||||
buffer->skip(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer->readBool() && (it = strings.find(elementId + "-texts_def")) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
}
|
||||
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
|
||||
if (baseType == ObjectType::COMPONENT && buffer->version >= 2)
|
||||
{
|
||||
buffer->seek(curPos, 4);
|
||||
|
||||
buffer->skip(2); //pageController
|
||||
|
||||
buffer->skip(4 * buffer->readShort());
|
||||
|
||||
int cpCount = buffer->readShort();
|
||||
for (int k = 0; k < cpCount; k++)
|
||||
{
|
||||
std::string target = buffer->readS();
|
||||
int propertyId = buffer->readShort();
|
||||
if (propertyId == 0 && (it = strings.find(elementId + "-cp-" + target)) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
else
|
||||
buffer->skip(2);
|
||||
}
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ObjectType::TEXT:
|
||||
case ObjectType::RICHTEXT:
|
||||
case ObjectType::INPUTTEXT:
|
||||
{
|
||||
if ((it = strings.find(elementId)) != strings.end())
|
||||
{
|
||||
buffer->seek(curPos, 6);
|
||||
buffer->writeS(it->second);
|
||||
}
|
||||
if ((it = strings.find(elementId + "-prompt")) != strings.end())
|
||||
{
|
||||
buffer->seek(curPos, 4);
|
||||
buffer->writeS(it->second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ObjectType::LIST:
|
||||
{
|
||||
buffer->seek(curPos, 8);
|
||||
buffer->skip(2);
|
||||
int itemCount = buffer->readShort();
|
||||
for (int j = 0; j < itemCount; j++)
|
||||
{
|
||||
int nextPos = buffer->readUshort();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
buffer->skip(2); //url
|
||||
if (type == ObjectType::TREE)
|
||||
buffer->skip(2);
|
||||
|
||||
//title
|
||||
if ((it = strings.find(elementId + "-" + Value(j).asString())) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
else
|
||||
buffer->skip(2);
|
||||
|
||||
//selected title
|
||||
if ((it = strings.find(elementId + "-" + Value(j).asString() + "-0")) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
else
|
||||
buffer->skip(2);
|
||||
|
||||
if (buffer->version >= 2)
|
||||
{
|
||||
buffer->skip(6);
|
||||
buffer->skip(buffer->readShort() * 4); //controllers
|
||||
|
||||
int cpCount = buffer->readShort();
|
||||
for (int k = 0; k < cpCount; k++)
|
||||
{
|
||||
std::string target = buffer->readS();
|
||||
int propertyId = buffer->readShort();
|
||||
if (propertyId == 0 && (it = strings.find(elementId + "-" + Value(j).asString() + "-" + target)) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
else
|
||||
buffer->skip(2);
|
||||
}
|
||||
}
|
||||
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ObjectType::LABEL:
|
||||
{
|
||||
if (buffer->seek(curPos, 6) && (ObjectType)buffer->readByte() == type)
|
||||
{
|
||||
if ((it = strings.find(elementId)) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
else
|
||||
buffer->skip(2);
|
||||
|
||||
buffer->skip(2);
|
||||
if (buffer->readBool())
|
||||
buffer->skip(4);
|
||||
buffer->skip(4);
|
||||
if (buffer->readBool() && (it = strings.find(elementId + "-prompt")) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ObjectType::BUTTON:
|
||||
{
|
||||
if (buffer->seek(curPos, 6) && (ObjectType)buffer->readByte() == type)
|
||||
{
|
||||
if ((it = strings.find(elementId)) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
else
|
||||
buffer->skip(2);
|
||||
if ((it = strings.find(elementId + "-0")) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ObjectType::COMBOBOX:
|
||||
{
|
||||
if (buffer->seek(curPos, 6) && (ObjectType)buffer->readByte() == type)
|
||||
{
|
||||
int itemCount = buffer->readShort();
|
||||
for (int j = 0; j < itemCount; j++)
|
||||
{
|
||||
int nextPos = buffer->readShort();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
if ((it = strings.find(elementId + "-" + Value(j).asString())) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
|
||||
if ((it = strings.find(elementId)) != strings.end())
|
||||
buffer->writeS(it->second);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
buffer->setPos(curPos + dataLen);
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef __TRANSLATIONHELPER_H_
|
||||
#define __TRANSLATIONHELPER_H_
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class PackageItem;
|
||||
|
||||
class TranslationHelper
|
||||
{
|
||||
public:
|
||||
static std::unordered_map<std::string, std::unordered_map<std::string, std::string>> strings;
|
||||
|
||||
static void loadFromXML(const char *xmlString, size_t nBytes);
|
||||
static void translateComponent(PackageItem* item);
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,63 @@
|
|||
#include "UIConfig.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
std::string UIConfig::defaultFont = "";
|
||||
std::string UIConfig::buttonSound = "";
|
||||
float UIConfig::buttonSoundVolumeScale = 1;
|
||||
int UIConfig::defaultScrollStep = 25;
|
||||
float UIConfig::defaultScrollDecelerationRate = 0.967f;
|
||||
bool UIConfig::defaultScrollTouchEffect = true;
|
||||
bool UIConfig::defaultScrollBounceEffect = true;
|
||||
ScrollBarDisplayType UIConfig::defaultScrollBarDisplay = ScrollBarDisplayType::DEFAULT;
|
||||
std::string UIConfig::verticalScrollBar = "";
|
||||
std::string UIConfig::horizontalScrollBar = "";
|
||||
int UIConfig::touchDragSensitivity = 10;
|
||||
int UIConfig::clickDragSensitivity = 2;
|
||||
int UIConfig::touchScrollSensitivity = 20;
|
||||
int UIConfig::defaultComboBoxVisibleItemCount = 10;
|
||||
std::string UIConfig::globalModalWaiting = "";
|
||||
std::string UIConfig::tooltipsWin = "";
|
||||
Color4F UIConfig::modalLayerColor = Color4F(0, 0, 0, 0.4f);
|
||||
bool UIConfig::bringWindowToFrontOnClick = true;
|
||||
std::string UIConfig::windowModalWaiting = "";
|
||||
std::string UIConfig::popupMenu = "";
|
||||
std::string UIConfig::popupMenu_seperator = "";
|
||||
|
||||
std::unordered_map<std::string, UIConfig::FontNameItem> UIConfig::_fontNames;
|
||||
|
||||
void UIConfig::registerFont(const std::string& aliasName, const std::string& realName)
|
||||
{
|
||||
FontNameItem fi;
|
||||
fi.name = realName;
|
||||
bool tmp = FileUtils::getInstance()->isPopupNotify();
|
||||
FileUtils::getInstance()->setPopupNotify(false);
|
||||
fi.ttf = FileUtils::getInstance()->isFileExist(realName);
|
||||
FileUtils::getInstance()->setPopupNotify(tmp);
|
||||
_fontNames[aliasName] = fi;
|
||||
}
|
||||
|
||||
const std::string& UIConfig::getRealFontName(const std::string& aliasName, bool* isTTF)
|
||||
{
|
||||
std::unordered_map<std::string, UIConfig::FontNameItem>::const_iterator it;
|
||||
if (aliasName.empty())
|
||||
it = _fontNames.find(UIConfig::defaultFont);
|
||||
else
|
||||
it = _fontNames.find(aliasName);
|
||||
if (it != _fontNames.end())
|
||||
{
|
||||
if(isTTF)
|
||||
*isTTF = it->second.ttf;
|
||||
return it->second.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isTTF)
|
||||
*isTTF = false;
|
||||
return aliasName;
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef __UICONFIG_H__
|
||||
#define __UICONFIG_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class UIConfig
|
||||
{
|
||||
public:
|
||||
static std::string defaultFont;
|
||||
static std::string buttonSound;
|
||||
static float buttonSoundVolumeScale;
|
||||
static int defaultScrollStep;
|
||||
static float defaultScrollDecelerationRate;
|
||||
static bool defaultScrollTouchEffect;
|
||||
static bool defaultScrollBounceEffect;
|
||||
static ScrollBarDisplayType defaultScrollBarDisplay;
|
||||
static std::string verticalScrollBar;
|
||||
static std::string horizontalScrollBar;
|
||||
static int touchDragSensitivity;
|
||||
static int clickDragSensitivity;
|
||||
static int touchScrollSensitivity;
|
||||
static int defaultComboBoxVisibleItemCount;
|
||||
static std::string globalModalWaiting;
|
||||
static cocos2d::Color4F modalLayerColor;
|
||||
static std::string tooltipsWin;
|
||||
static bool bringWindowToFrontOnClick;
|
||||
static std::string windowModalWaiting;
|
||||
static std::string popupMenu;
|
||||
static std::string popupMenu_seperator;
|
||||
|
||||
static void registerFont(const std::string& aliasName, const std::string& realName);
|
||||
static const std::string& getRealFontName(const std::string& aliasName, bool* isTTF = nullptr);
|
||||
|
||||
private:
|
||||
struct FontNameItem
|
||||
{
|
||||
std::string name;
|
||||
bool ttf;
|
||||
};
|
||||
static std::unordered_map<std::string, FontNameItem> _fontNames;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,145 @@
|
|||
#include "UIObjectFactory.h"
|
||||
#include "GButton.h"
|
||||
#include "GComboBox.h"
|
||||
#include "GComponent.h"
|
||||
#include "GGraph.h"
|
||||
#include "GGroup.h"
|
||||
#include "GImage.h"
|
||||
#include "GLabel.h"
|
||||
#include "GList.h"
|
||||
#include "GLoader.h"
|
||||
#include "GMovieClip.h"
|
||||
#include "GProgressBar.h"
|
||||
#include "GRichTextField.h"
|
||||
#include "GScrollBar.h"
|
||||
#include "GSlider.h"
|
||||
#include "GTextField.h"
|
||||
#include "GTextInput.h"
|
||||
#include "GTree.h"
|
||||
#include "GLoader3D.h"
|
||||
#include "UIPackage.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
using namespace std;
|
||||
|
||||
unordered_map<string, UIObjectFactory::GComponentCreator> UIObjectFactory::_packageItemExtensions;
|
||||
UIObjectFactory::GLoaderCreator UIObjectFactory::_loaderCreator;
|
||||
|
||||
void UIObjectFactory::setPackageItemExtension(const string& url, GComponentCreator creator)
|
||||
{
|
||||
if (url.size() == 0)
|
||||
{
|
||||
CCLOG("Invaild url: %s", url.c_str());
|
||||
return;
|
||||
}
|
||||
PackageItem* pi = UIPackage::getItemByURL(url);
|
||||
if (pi)
|
||||
pi->extensionCreator = creator;
|
||||
|
||||
_packageItemExtensions[url] = creator;
|
||||
}
|
||||
|
||||
GObject* UIObjectFactory::newObject(PackageItem* pi)
|
||||
{
|
||||
GObject* obj;
|
||||
if (pi->extensionCreator != nullptr)
|
||||
obj = pi->extensionCreator();
|
||||
else
|
||||
obj = newObject(pi->objectType);
|
||||
if (obj != nullptr)
|
||||
obj->_packageItem = pi;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
GObject* UIObjectFactory::newObject(ObjectType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ObjectType::IMAGE:
|
||||
return GImage::create();
|
||||
|
||||
case ObjectType::MOVIECLIP:
|
||||
return GMovieClip::create();
|
||||
|
||||
case ObjectType::COMPONENT:
|
||||
return GComponent::create();
|
||||
|
||||
case ObjectType::TEXT:
|
||||
return GBasicTextField::create();
|
||||
|
||||
case ObjectType::RICHTEXT:
|
||||
return GRichTextField::create();
|
||||
|
||||
case ObjectType::INPUTTEXT:
|
||||
return GTextInput::create();
|
||||
|
||||
case ObjectType::GROUP:
|
||||
return GGroup::create();
|
||||
|
||||
case ObjectType::LIST:
|
||||
return GList::create();
|
||||
|
||||
case ObjectType::GRAPH:
|
||||
return GGraph::create();
|
||||
|
||||
case ObjectType::LOADER:
|
||||
if (_loaderCreator != nullptr)
|
||||
return _loaderCreator();
|
||||
else
|
||||
return GLoader::create();
|
||||
|
||||
case ObjectType::BUTTON:
|
||||
return GButton::create();
|
||||
|
||||
case ObjectType::LABEL:
|
||||
return GLabel::create();
|
||||
|
||||
case ObjectType::PROGRESSBAR:
|
||||
return GProgressBar::create();
|
||||
|
||||
case ObjectType::SLIDER:
|
||||
return GSlider::create();
|
||||
|
||||
case ObjectType::SCROLLBAR:
|
||||
return GScrollBar::create();
|
||||
|
||||
case ObjectType::COMBOBOX:
|
||||
return GComboBox::create();
|
||||
|
||||
case ObjectType::TREE:
|
||||
return GTree::create();
|
||||
|
||||
case ObjectType::LOADER3D:
|
||||
return GLoader3D::create();
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UIObjectFactory::setLoaderExtension(GLoaderCreator creator)
|
||||
{
|
||||
_loaderCreator = creator;
|
||||
}
|
||||
|
||||
void UIObjectFactory::resolvePackageItemExtension(PackageItem* pi)
|
||||
{
|
||||
auto it = _packageItemExtensions.find(UIPackage::URL_PREFIX + pi->owner->getId() + pi->id);
|
||||
if (it != _packageItemExtensions.end())
|
||||
{
|
||||
pi->extensionCreator = it->second;
|
||||
return;
|
||||
}
|
||||
it = _packageItemExtensions.find(UIPackage::URL_PREFIX + pi->owner->getName() + "/" + pi->name);
|
||||
if (it != _packageItemExtensions.end())
|
||||
{
|
||||
pi->extensionCreator = it->second;
|
||||
return;
|
||||
}
|
||||
pi->extensionCreator = nullptr;
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef __UIOBJECTFACTORY_H__
|
||||
#define __UIOBJECTFACTORY_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GComponent.h"
|
||||
#include "PackageItem.h"
|
||||
#include "GLoader.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class UIObjectFactory
|
||||
{
|
||||
public:
|
||||
typedef std::function<GComponent*()> GComponentCreator;
|
||||
typedef std::function<GLoader*()> GLoaderCreator;
|
||||
|
||||
static void setPackageItemExtension(const std::string& url, GComponentCreator creator);
|
||||
static GObject* newObject(PackageItem* pi);
|
||||
static GObject* newObject(ObjectType type);
|
||||
|
||||
static void setLoaderExtension(GLoaderCreator creator);
|
||||
|
||||
private:
|
||||
static void resolvePackageItemExtension(PackageItem* pi);
|
||||
|
||||
static std::unordered_map<std::string, GComponentCreator> _packageItemExtensions;
|
||||
static GLoaderCreator _loaderCreator;
|
||||
|
||||
friend class UIPackage;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,884 @@
|
|||
#include "UIPackage.h"
|
||||
#include "UIObjectFactory.h"
|
||||
#include "display/BitmapFont.h"
|
||||
#include "event/HitTest.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
using namespace std;
|
||||
|
||||
const string UIPackage::URL_PREFIX = "ui://";
|
||||
int UIPackage::_constructing = 0;
|
||||
std::string UIPackage::_branch;
|
||||
std::unordered_map<std::string, std::string> UIPackage::_vars;
|
||||
|
||||
const unsigned char* emptyTextureData = new unsigned char[16]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
std::unordered_map<std::string, UIPackage*> UIPackage::_packageInstById;
|
||||
std::unordered_map<std::string, UIPackage*> UIPackage::_packageInstByName;
|
||||
std::vector<UIPackage*> UIPackage::_packageList;
|
||||
|
||||
Texture2D* UIPackage::_emptyTexture;
|
||||
|
||||
struct AtlasSprite
|
||||
{
|
||||
PackageItem* atlas;
|
||||
Rect rect;
|
||||
Size originalSize;
|
||||
Vec2 offset;
|
||||
bool rotated;
|
||||
};
|
||||
|
||||
UIPackage::UIPackage()
|
||||
: _branchIndex(-1)
|
||||
{
|
||||
}
|
||||
|
||||
UIPackage::~UIPackage()
|
||||
{
|
||||
for (auto& it : _items)
|
||||
it->release();
|
||||
for (auto& it : _sprites)
|
||||
delete it.second;
|
||||
}
|
||||
|
||||
void UIPackage::setBranch(const std::string& value)
|
||||
{
|
||||
_branch = value;
|
||||
for (auto& it : _packageList)
|
||||
{
|
||||
if (it->_branches.size() > 0)
|
||||
{
|
||||
it->_branchIndex = ToolSet::findInStringArray(it->_branches, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& UIPackage::getVar(const std::string& key)
|
||||
{
|
||||
auto it = _vars.find(key);
|
||||
if (it != _vars.end())
|
||||
return it->second;
|
||||
else
|
||||
return STD_STRING_EMPTY;
|
||||
}
|
||||
|
||||
void UIPackage::setVar(const std::string& key, const std::string& value)
|
||||
{
|
||||
_vars[key] = value;
|
||||
}
|
||||
|
||||
UIPackage* UIPackage::getById(const string& id)
|
||||
{
|
||||
auto it = _packageInstById.find(id);
|
||||
if (it != _packageInstById.end())
|
||||
return it->second;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UIPackage* UIPackage::getByName(const string& name)
|
||||
{
|
||||
auto it = _packageInstByName.find(name);
|
||||
if (it != _packageInstByName.end())
|
||||
return it->second;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UIPackage* UIPackage::addPackage(const string& assetPath)
|
||||
{
|
||||
auto it = _packageInstById.find(assetPath);
|
||||
if (it != _packageInstById.end())
|
||||
return it->second;
|
||||
|
||||
if (_emptyTexture == nullptr)
|
||||
{
|
||||
Image* emptyImage = new Image();
|
||||
emptyImage->initWithRawData(emptyTextureData, 16, 2, 2, 4, false);
|
||||
_emptyTexture = new Texture2D();
|
||||
_emptyTexture->initWithImage(emptyImage);
|
||||
delete emptyImage;
|
||||
}
|
||||
|
||||
Data data;
|
||||
|
||||
if (FileUtils::getInstance()->getContents(assetPath + ".fui", &data) != FileUtils::Status::OK)
|
||||
{
|
||||
CCLOGERROR("FairyGUI: cannot load package from '%s'", assetPath.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ssize_t size;
|
||||
char* p = (char*)data.takeBuffer(&size);
|
||||
ByteBuffer buffer(p, 0, (int)size, true);
|
||||
|
||||
UIPackage* pkg = new UIPackage();
|
||||
pkg->_assetPath = assetPath;
|
||||
if (!pkg->loadPackage(&buffer))
|
||||
{
|
||||
delete pkg;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_packageInstById[pkg->getId()] = pkg;
|
||||
_packageInstByName[pkg->getName()] = pkg;
|
||||
_packageInstById[assetPath] = pkg;
|
||||
_packageList.push_back(pkg);
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
||||
void UIPackage::removePackage(const string& packageIdOrName)
|
||||
{
|
||||
UIPackage* pkg = UIPackage::getByName(packageIdOrName);
|
||||
if (!pkg)
|
||||
pkg = getById(packageIdOrName);
|
||||
|
||||
if (pkg)
|
||||
{
|
||||
auto it = std::find(_packageList.cbegin(), _packageList.cend(), pkg);
|
||||
if (it != _packageList.cend())
|
||||
_packageList.erase(it);
|
||||
|
||||
_packageInstById.erase(pkg->getId());
|
||||
_packageInstById.erase(pkg->_assetPath);
|
||||
_packageInstByName.erase(pkg->getName());
|
||||
|
||||
pkg->release();
|
||||
}
|
||||
else
|
||||
CCLOGERROR("FairyGUI: invalid package name or id: %s", packageIdOrName.c_str());
|
||||
}
|
||||
|
||||
void UIPackage::removeAllPackages()
|
||||
{
|
||||
for (auto& it : _packageList)
|
||||
it->release();
|
||||
|
||||
_packageInstById.clear();
|
||||
_packageInstByName.clear();
|
||||
_packageList.clear();
|
||||
}
|
||||
|
||||
GObject* UIPackage::createObject(const string& pkgName, const string& resName)
|
||||
{
|
||||
UIPackage* pkg = UIPackage::getByName(pkgName);
|
||||
if (pkg)
|
||||
return pkg->createObject(resName);
|
||||
else
|
||||
{
|
||||
CCLOGERROR("FairyGUI: package not found - %s", pkgName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
GObject* UIPackage::createObjectFromURL(const string& url)
|
||||
{
|
||||
PackageItem* pi = UIPackage::getItemByURL(url);
|
||||
if (pi)
|
||||
return pi->owner->createObject(pi);
|
||||
else
|
||||
{
|
||||
CCLOGERROR("FairyGUI: resource not found - %s", url.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
string UIPackage::getItemURL(const string& pkgName, const string& resName)
|
||||
{
|
||||
UIPackage* pkg = UIPackage::getByName(pkgName);
|
||||
if (pkg)
|
||||
{
|
||||
PackageItem* pi = pkg->getItemByName(resName);
|
||||
if (pi)
|
||||
return URL_PREFIX + pkg->getId() + pi->id;
|
||||
}
|
||||
return STD_STRING_EMPTY;
|
||||
}
|
||||
|
||||
PackageItem* UIPackage::getItemByURL(const string& url)
|
||||
{
|
||||
if (url.size() == 0)
|
||||
return nullptr;
|
||||
|
||||
ssize_t pos1 = url.find('/');
|
||||
if (pos1 == -1)
|
||||
return nullptr;
|
||||
|
||||
ssize_t pos2 = url.find('/', pos1 + 2);
|
||||
if (pos2 == -1)
|
||||
{
|
||||
if (url.size() > 13)
|
||||
{
|
||||
string pkgId = url.substr(5, 8);
|
||||
UIPackage* pkg = getById(pkgId);
|
||||
if (pkg != nullptr)
|
||||
{
|
||||
string srcId = url.substr(13);
|
||||
return pkg->getItem(srcId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string pkgName = url.substr(pos1 + 2, pos2 - pos1 - 2);
|
||||
UIPackage* pkg = getByName(pkgName);
|
||||
if (pkg != nullptr)
|
||||
{
|
||||
string srcName = url.substr(pos2 + 1);
|
||||
return pkg->getItemByName(srcName);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
string UIPackage::normalizeURL(const string& url)
|
||||
{
|
||||
if (url.size() == 0)
|
||||
return url;
|
||||
|
||||
ssize_t pos1 = url.find('/');
|
||||
if (pos1 == -1)
|
||||
return url;
|
||||
|
||||
ssize_t pos2 = url.find('/', pos1 + 2);
|
||||
if (pos2 == -1)
|
||||
return url;
|
||||
else
|
||||
{
|
||||
string pkgName = url.substr(pos1 + 2, pos2 - pos1 - 2);
|
||||
string srcName = url.substr(pos2 + 1);
|
||||
return getItemURL(pkgName, srcName);
|
||||
}
|
||||
}
|
||||
|
||||
void* UIPackage::getItemAsset(const std::string& pkgName, const std::string& resName, PackageItemType type)
|
||||
{
|
||||
UIPackage* pkg = UIPackage::getByName(pkgName);
|
||||
if (pkg)
|
||||
{
|
||||
PackageItem* pi = pkg->getItemByName(resName);
|
||||
if (pi)
|
||||
{
|
||||
if (type != PackageItemType::UNKNOWN && pi->type != type)
|
||||
return nullptr;
|
||||
else
|
||||
return pkg->getItemAsset(pi);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* UIPackage::getItemAssetByURL(const std::string& url, PackageItemType type)
|
||||
{
|
||||
PackageItem* pi = UIPackage::getItemByURL(url);
|
||||
if (pi)
|
||||
{
|
||||
if (type != PackageItemType::UNKNOWN && pi->type != type)
|
||||
return nullptr;
|
||||
else
|
||||
return pi->owner->getItemAsset(pi);
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PackageItem* UIPackage::getItem(const string& itemId)
|
||||
{
|
||||
auto it = _itemsById.find(itemId);
|
||||
if (it != _itemsById.end())
|
||||
return it->second;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PackageItem* UIPackage::getItemByName(const string& itemName)
|
||||
{
|
||||
auto it = _itemsByName.find(itemName);
|
||||
if (it != _itemsByName.end())
|
||||
return it->second;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GObject* UIPackage::createObject(const string& resName)
|
||||
{
|
||||
PackageItem* pi = getItemByName(resName);
|
||||
CCASSERT(pi, StringUtils::format("FairyGUI: resource not found - %s in %s",
|
||||
resName.c_str(), _name.c_str())
|
||||
.c_str());
|
||||
|
||||
return createObject(pi);
|
||||
}
|
||||
|
||||
GObject* UIPackage::createObject(PackageItem* item)
|
||||
{
|
||||
GObject* g = UIObjectFactory::newObject(item);
|
||||
if (g == nullptr)
|
||||
return nullptr;
|
||||
|
||||
_constructing++;
|
||||
g->constructFromResource();
|
||||
_constructing--;
|
||||
return g;
|
||||
}
|
||||
|
||||
bool UIPackage::loadPackage(ByteBuffer* buffer)
|
||||
{
|
||||
if (buffer->readUint() != 0x46475549)
|
||||
{
|
||||
CCLOGERROR("FairyGUI: old package format found in '%s'", _assetPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->version = buffer->readInt();
|
||||
bool ver2 = buffer->version >= 2;
|
||||
buffer->readBool(); //compressed
|
||||
_id = buffer->readString();
|
||||
_name = buffer->readString();
|
||||
buffer->skip(20);
|
||||
int indexTablePos = buffer->getPos();
|
||||
int cnt;
|
||||
|
||||
buffer->seek(indexTablePos, 4);
|
||||
|
||||
cnt = buffer->readInt();
|
||||
_stringTable.resize(cnt);
|
||||
for (int i = 0; i < cnt; i++)
|
||||
_stringTable[i] = buffer->readString();
|
||||
buffer->setStringTable(&_stringTable);
|
||||
|
||||
buffer->seek(indexTablePos, 0);
|
||||
cnt = buffer->readShort();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
std::unordered_map<std::string, std::string> info;
|
||||
info["id"] = buffer->readS();
|
||||
info["name"] = buffer->readS();
|
||||
|
||||
_dependencies.push_back(info);
|
||||
}
|
||||
|
||||
bool branchIncluded = false;
|
||||
if (ver2)
|
||||
{
|
||||
cnt = buffer->readShort();
|
||||
if (cnt > 0)
|
||||
{
|
||||
buffer->readSArray(_branches, cnt);
|
||||
if (_branch.size() > 0)
|
||||
_branchIndex = ToolSet::findInStringArray(_branches, _branch);
|
||||
}
|
||||
|
||||
branchIncluded = cnt > 0;
|
||||
}
|
||||
|
||||
buffer->seek(indexTablePos, 1);
|
||||
|
||||
PackageItem* pi;
|
||||
string path = _assetPath;
|
||||
size_t pos = path.find('/');
|
||||
string shortPath = pos == -1 ? STD_STRING_EMPTY : path.substr(0, pos + 1);
|
||||
path += "_";
|
||||
|
||||
cnt = buffer->readShort();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
int nextPos = buffer->readInt();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
pi = new PackageItem();
|
||||
pi->owner = this;
|
||||
pi->type = (PackageItemType)buffer->readByte();
|
||||
pi->id = buffer->readS();
|
||||
pi->name = buffer->readS();
|
||||
buffer->skip(2); //path
|
||||
pi->file = buffer->readS();
|
||||
buffer->readBool(); //exported
|
||||
pi->width = buffer->readInt();
|
||||
pi->height = buffer->readInt();
|
||||
|
||||
switch (pi->type)
|
||||
{
|
||||
case PackageItemType::IMAGE:
|
||||
{
|
||||
pi->objectType = ObjectType::IMAGE;
|
||||
int scaleOption = buffer->readByte();
|
||||
if (scaleOption == 1)
|
||||
{
|
||||
pi->scale9Grid = new Rect();
|
||||
pi->scale9Grid->origin.x = buffer->readInt();
|
||||
pi->scale9Grid->origin.y = buffer->readInt();
|
||||
pi->scale9Grid->size.width = buffer->readInt();
|
||||
pi->scale9Grid->size.height = buffer->readInt();
|
||||
pi->tileGridIndice = buffer->readInt();
|
||||
}
|
||||
else if (scaleOption == 2)
|
||||
pi->scaleByTile = true;
|
||||
|
||||
buffer->readBool(); //smoothing
|
||||
break;
|
||||
}
|
||||
|
||||
case PackageItemType::MOVIECLIP:
|
||||
{
|
||||
buffer->readBool(); //smoothing
|
||||
pi->objectType = ObjectType::MOVIECLIP;
|
||||
pi->rawData = buffer->readBuffer();
|
||||
break;
|
||||
}
|
||||
|
||||
case PackageItemType::FONT:
|
||||
{
|
||||
pi->rawData = buffer->readBuffer();
|
||||
break;
|
||||
}
|
||||
|
||||
case PackageItemType::COMPONENT:
|
||||
{
|
||||
int extension = buffer->readByte();
|
||||
if (extension > 0)
|
||||
pi->objectType = (ObjectType)extension;
|
||||
else
|
||||
pi->objectType = ObjectType::COMPONENT;
|
||||
pi->rawData = buffer->readBuffer();
|
||||
|
||||
UIObjectFactory::resolvePackageItemExtension(pi);
|
||||
break;
|
||||
}
|
||||
|
||||
case PackageItemType::ATLAS:
|
||||
case PackageItemType::SOUND:
|
||||
case PackageItemType::MISC:
|
||||
{
|
||||
pi->file = path + pi->file;
|
||||
break;
|
||||
}
|
||||
|
||||
case PackageItemType::SPINE:
|
||||
case PackageItemType::DRAGONBONES:
|
||||
{
|
||||
pi->file = shortPath + pi->file;
|
||||
pi->skeletonAnchor = new Vec2();
|
||||
pi->skeletonAnchor->x = buffer->readFloat();
|
||||
pi->skeletonAnchor->y = buffer->readFloat();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ver2)
|
||||
{
|
||||
std::string str = buffer->readS(); //branch
|
||||
if (!str.empty())
|
||||
pi->name = str + "/" + pi->name;
|
||||
|
||||
int branchCnt = buffer->readUbyte();
|
||||
if (branchCnt > 0)
|
||||
{
|
||||
if (branchIncluded)
|
||||
{
|
||||
pi->branches = new std::vector<std::string>();
|
||||
buffer->readSArray(*pi->branches, branchCnt);
|
||||
}
|
||||
else
|
||||
_itemsById[buffer->readS()] = pi;
|
||||
}
|
||||
|
||||
int highResCnt = buffer->readUbyte();
|
||||
if (highResCnt > 0)
|
||||
{
|
||||
pi->highResolution = new std::vector<std::string>();
|
||||
buffer->readSArray(*pi->highResolution, highResCnt);
|
||||
}
|
||||
}
|
||||
|
||||
_items.push_back(pi);
|
||||
_itemsById[pi->id] = pi;
|
||||
if (!pi->name.empty())
|
||||
_itemsByName[pi->name] = pi;
|
||||
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
|
||||
buffer->seek(indexTablePos, 2);
|
||||
|
||||
cnt = buffer->readShort();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
int nextPos = buffer->readShort();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
const string& itemId = buffer->readS();
|
||||
pi = _itemsById[buffer->readS()];
|
||||
|
||||
AtlasSprite* sprite = new AtlasSprite();
|
||||
sprite->atlas = pi;
|
||||
sprite->rect.origin.x = buffer->readInt();
|
||||
sprite->rect.origin.y = buffer->readInt();
|
||||
sprite->rect.size.width = buffer->readInt();
|
||||
sprite->rect.size.height = buffer->readInt();
|
||||
sprite->rotated = buffer->readBool();
|
||||
if (ver2 && buffer->readBool())
|
||||
{
|
||||
sprite->offset.x = buffer->readInt();
|
||||
sprite->offset.y = buffer->readInt();
|
||||
sprite->originalSize.width = buffer->readInt();
|
||||
sprite->originalSize.height = buffer->readInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite->offset.setZero();
|
||||
sprite->originalSize.width = sprite->rect.size.width;
|
||||
sprite->originalSize.height = sprite->rect.size.height;
|
||||
}
|
||||
_sprites[itemId] = sprite;
|
||||
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
|
||||
if (buffer->seek(indexTablePos, 3))
|
||||
{
|
||||
cnt = buffer->readShort();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
int nextPos = buffer->readInt();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
auto it = _itemsById.find(buffer->readS());
|
||||
if (it != _itemsById.end())
|
||||
{
|
||||
pi = it->second;
|
||||
if (pi->type == PackageItemType::IMAGE)
|
||||
{
|
||||
pi->pixelHitTestData = new PixelHitTestData();
|
||||
pi->pixelHitTestData->load(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void* UIPackage::getItemAsset(PackageItem* item)
|
||||
{
|
||||
switch (item->type)
|
||||
{
|
||||
case PackageItemType::IMAGE:
|
||||
if (item->spriteFrame == nullptr)
|
||||
loadImage(item);
|
||||
return item->spriteFrame;
|
||||
|
||||
case PackageItemType::ATLAS:
|
||||
if (item->texture == nullptr)
|
||||
loadAtlas(item);
|
||||
return item->texture;
|
||||
|
||||
case PackageItemType::FONT:
|
||||
if (item->bitmapFont == nullptr)
|
||||
loadFont(item);
|
||||
return item->bitmapFont;
|
||||
|
||||
case PackageItemType::MOVIECLIP:
|
||||
if (item->animation == nullptr)
|
||||
loadMovieClip(item);
|
||||
return item->animation;
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UIPackage::loadAtlas(PackageItem* item)
|
||||
{
|
||||
Image* image = new Image();
|
||||
#if COCOS2D_VERSION < 0x00031702
|
||||
Image::setPNGPremultipliedAlphaEnabled(false);
|
||||
#endif
|
||||
if (!image->initWithImageFile(item->file))
|
||||
{
|
||||
item->texture = _emptyTexture;
|
||||
_emptyTexture->retain();
|
||||
delete image;
|
||||
#if COCOS2D_VERSION < 0x00031702
|
||||
Image::setPNGPremultipliedAlphaEnabled(true);
|
||||
#endif
|
||||
CCLOGWARN("FairyGUI: texture '%s' not found in %s", item->file.c_str(), _name.c_str());
|
||||
return;
|
||||
}
|
||||
#if COCOS2D_VERSION < 0x00031702
|
||||
Image::setPNGPremultipliedAlphaEnabled(true);
|
||||
#endif
|
||||
|
||||
Texture2D* tex = new Texture2D();
|
||||
tex->initWithImage(image);
|
||||
item->texture = tex;
|
||||
delete image;
|
||||
|
||||
string alphaFilePath;
|
||||
string ext = FileUtils::getInstance()->getFileExtension(item->file);
|
||||
size_t pos = item->file.find_last_of('.');
|
||||
if (pos != -1)
|
||||
alphaFilePath = item->file.substr(0, pos) + "!a" + ext;
|
||||
else
|
||||
alphaFilePath = item->file + "!a" + ext;
|
||||
|
||||
bool hasAlphaTexture = ToolSet::isFileExist(alphaFilePath);
|
||||
if (hasAlphaTexture)
|
||||
{
|
||||
image = new Image();
|
||||
if (!image->initWithImageFile(alphaFilePath))
|
||||
{
|
||||
delete image;
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(ENGINEX_VERSION)
|
||||
if(image->getFileType() == Image::Format::ETC)
|
||||
tex->updateWithImage(image, Texture2D::getDefaultAlphaPixelFormat(), 1, TextureFormatEXT::ETC1_ALPHA);
|
||||
#else
|
||||
tex = new Texture2D();
|
||||
tex->initWithImage(image);
|
||||
item->texture->setAlphaTexture(tex);
|
||||
tex->release();
|
||||
#endif
|
||||
delete image;
|
||||
}
|
||||
}
|
||||
|
||||
AtlasSprite* UIPackage::getSprite(const std::string& spriteId)
|
||||
{
|
||||
auto it = _sprites.find(spriteId);
|
||||
if (it != _sprites.end())
|
||||
return it->second;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//note: SpriteFrame.ref=1 not autorelease.
|
||||
SpriteFrame* UIPackage::createSpriteTexture(AtlasSprite* sprite)
|
||||
{
|
||||
getItemAsset(sprite->atlas);
|
||||
|
||||
//not using createWithTexture for saving a autorelease call.
|
||||
SpriteFrame* spriteFrame = new SpriteFrame();
|
||||
spriteFrame->initWithTexture(sprite->atlas->texture, sprite->rect, sprite->rotated,
|
||||
Vec2(sprite->offset.x - (sprite->originalSize.width - sprite->rect.size.width) / 2, -(sprite->offset.y - (sprite->originalSize.height - sprite->rect.size.height) / 2)),
|
||||
sprite->originalSize);
|
||||
|
||||
return spriteFrame;
|
||||
}
|
||||
|
||||
void UIPackage::loadImage(PackageItem* item)
|
||||
{
|
||||
AtlasSprite* sprite = getSprite(item->id);
|
||||
if (sprite != nullptr)
|
||||
item->spriteFrame = createSpriteTexture(sprite);
|
||||
else
|
||||
{
|
||||
item->spriteFrame = new (std::nothrow) SpriteFrame();
|
||||
item->spriteFrame->initWithTexture(_emptyTexture, Rect());
|
||||
}
|
||||
if (item->scaleByTile)
|
||||
{
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
Texture2D::TexParams tp(backend::SamplerFilter::LINEAR, backend::SamplerFilter::LINEAR,
|
||||
backend::SamplerAddressMode::REPEAT, backend::SamplerAddressMode::REPEAT);
|
||||
#else
|
||||
Texture2D::TexParams tp = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT };
|
||||
#endif
|
||||
item->spriteFrame->getTexture()->setTexParameters(tp);
|
||||
}
|
||||
}
|
||||
|
||||
void UIPackage::loadMovieClip(PackageItem* item)
|
||||
{
|
||||
item->animation = Animation::create();
|
||||
item->animation->retain();
|
||||
|
||||
ByteBuffer* buffer = item->rawData;
|
||||
|
||||
buffer->seek(0, 0);
|
||||
|
||||
float interval = buffer->readInt() / 1000.0f;
|
||||
item->swing = buffer->readBool();
|
||||
item->repeatDelay = buffer->readInt() / 1000.0f;
|
||||
|
||||
buffer->seek(0, 1);
|
||||
|
||||
int frameCount = buffer->readShort();
|
||||
Vector<AnimationFrame*> frames(frameCount);
|
||||
|
||||
Size mcSizeInPixels = Size(item->width, item->height);
|
||||
Size mcSize = CC_SIZE_PIXELS_TO_POINTS(mcSizeInPixels);
|
||||
|
||||
AtlasSprite* sprite;
|
||||
SpriteFrame* spriteFrame;
|
||||
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
{
|
||||
int nextPos = buffer->readShort();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
Rect rect;
|
||||
rect.origin.x = buffer->readInt();
|
||||
rect.origin.y = buffer->readInt();
|
||||
rect.size.width = buffer->readInt();
|
||||
rect.size.height = buffer->readInt();
|
||||
float addDelay = buffer->readInt() / 1000.0f;
|
||||
const string& spriteId = buffer->readS();
|
||||
|
||||
if (!spriteId.empty() && (sprite = getSprite(spriteId)) != nullptr)
|
||||
{
|
||||
spriteFrame = createSpriteTexture(sprite);
|
||||
spriteFrame->setOriginalSizeInPixels(mcSizeInPixels);
|
||||
spriteFrame->setOriginalSize(mcSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
//dont use createWithTexture
|
||||
spriteFrame = new (std::nothrow) SpriteFrame();
|
||||
spriteFrame->initWithTexture(_emptyTexture, Rect());
|
||||
}
|
||||
|
||||
spriteFrame->setOffset(Vec2(rect.origin.x - (mcSize.width - rect.size.width) / 2, -(rect.origin.y - (mcSize.height - rect.size.height) / 2)));
|
||||
AnimationFrame* frame = AnimationFrame::create(spriteFrame, addDelay / interval + 1, ValueMapNull);
|
||||
frames.pushBack(frame);
|
||||
//tranfer to AnimationFrame
|
||||
spriteFrame->release();
|
||||
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
|
||||
item->animation->initWithAnimationFrames(frames, interval, 1);
|
||||
delete buffer;
|
||||
item->rawData = nullptr;
|
||||
}
|
||||
|
||||
void UIPackage::loadFont(PackageItem* item)
|
||||
{
|
||||
item->bitmapFont = BitmapFont::create();
|
||||
FontAtlas* fontAtlas = new FontAtlas(*item->bitmapFont);
|
||||
item->bitmapFont->_fontAtlas = fontAtlas;
|
||||
|
||||
ByteBuffer* buffer = item->rawData;
|
||||
|
||||
buffer->seek(0, 0);
|
||||
|
||||
bool ttf = buffer->readBool();
|
||||
item->bitmapFont->_canTint = buffer->readBool();
|
||||
item->bitmapFont->_resizable = buffer->readBool();
|
||||
buffer->readBool(); //hasChannel
|
||||
int fontSize = buffer->readInt();
|
||||
int xadvance = buffer->readInt();
|
||||
int lineHeight = buffer->readInt();
|
||||
|
||||
Texture2D* mainTexture = nullptr;
|
||||
AtlasSprite* mainSprite = nullptr;
|
||||
|
||||
if (ttf && (mainSprite = getSprite(item->id)) != nullptr)
|
||||
mainTexture = (Texture2D*)getItemAsset(mainSprite->atlas);
|
||||
|
||||
buffer->seek(0, 1);
|
||||
|
||||
FontLetterDefinition def;
|
||||
int bx = 0, by = 0;
|
||||
int bw = 0, bh = 0;
|
||||
PackageItem* charImg = nullptr;
|
||||
|
||||
int cnt = buffer->readInt();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
int nextPos = buffer->readShort();
|
||||
nextPos += buffer->getPos();
|
||||
|
||||
memset(&def, 0, sizeof(def));
|
||||
|
||||
unsigned short ch = buffer->readUshort();
|
||||
const string& img = buffer->readS();
|
||||
bx = buffer->readInt();
|
||||
by = buffer->readInt();
|
||||
def.offsetX = buffer->readInt();
|
||||
def.offsetY = buffer->readInt();
|
||||
bw = buffer->readInt();
|
||||
bh = buffer->readInt();
|
||||
def.xAdvance = buffer->readInt();
|
||||
buffer->readByte(); //channel
|
||||
|
||||
if (ttf)
|
||||
{
|
||||
Rect tempRect = Rect(bx + mainSprite->rect.origin.x, by + mainSprite->rect.origin.y, bw, bh);
|
||||
tempRect = CC_RECT_PIXELS_TO_POINTS(tempRect);
|
||||
def.U = tempRect.origin.x;
|
||||
def.V = tempRect.origin.y;
|
||||
def.width = tempRect.size.width;
|
||||
def.height = tempRect.size.height;
|
||||
def.validDefinition = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
charImg = getItem(img);
|
||||
if (charImg)
|
||||
{
|
||||
charImg = charImg->getBranch();
|
||||
bw = charImg->width;
|
||||
bh = charImg->height;
|
||||
|
||||
AtlasSprite* sprite = getSprite(img);
|
||||
if (sprite != nullptr)
|
||||
{
|
||||
def.offsetX += sprite->offset.x;
|
||||
def.offsetY += sprite->offset.y;
|
||||
}
|
||||
|
||||
charImg = charImg->getHighResolution();
|
||||
getItemAsset(charImg);
|
||||
|
||||
Rect tempRect = charImg->spriteFrame->getRectInPixels();
|
||||
tempRect = CC_RECT_PIXELS_TO_POINTS(tempRect);
|
||||
def.U = tempRect.origin.x;
|
||||
def.V = tempRect.origin.y;
|
||||
def.width = tempRect.size.width;
|
||||
def.height = tempRect.size.height;
|
||||
if (mainTexture == nullptr)
|
||||
mainTexture = charImg->spriteFrame->getTexture();
|
||||
def.validDefinition = true;
|
||||
|
||||
if (def.xAdvance == 0)
|
||||
{
|
||||
if (xadvance == 0)
|
||||
def.xAdvance = def.offsetX + bw;
|
||||
else
|
||||
def.xAdvance = xadvance;
|
||||
}
|
||||
|
||||
if (fontSize == 0)
|
||||
fontSize = bh;
|
||||
lineHeight = MAX(fontSize, lineHeight);
|
||||
}
|
||||
}
|
||||
|
||||
fontAtlas->addLetterDefinition(ch, def);
|
||||
buffer->setPos(nextPos);
|
||||
}
|
||||
|
||||
if (mainTexture != nullptr)
|
||||
fontAtlas->addTexture(mainTexture, 0);
|
||||
fontAtlas->setLineHeight(lineHeight);
|
||||
item->bitmapFont->_originalFontSize = fontSize;
|
||||
|
||||
delete buffer;
|
||||
item->rawData = nullptr;
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef __UIPACKAGE_H__
|
||||
#define __UIPACKAGE_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "GObject.h"
|
||||
#include "PackageItem.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
struct AtlasSprite;
|
||||
class ByteBuffer;
|
||||
|
||||
class UIPackage : public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
UIPackage();
|
||||
~UIPackage();
|
||||
|
||||
static UIPackage* getById(const std::string& id);
|
||||
static UIPackage* getByName(const std::string& name);
|
||||
static UIPackage* addPackage(const std::string& descFilePath);
|
||||
static void removePackage(const std::string& packageIdOrName);
|
||||
static void removeAllPackages();
|
||||
static GObject* createObject(const std::string& pkgName, const std::string& resName);
|
||||
static GObject* createObjectFromURL(const std::string& url);
|
||||
static std::string getItemURL(const std::string& pkgName, const std::string& resName);
|
||||
static PackageItem* getItemByURL(const std::string& url);
|
||||
static std::string normalizeURL(const std::string& url);
|
||||
static void* getItemAsset(const std::string& pkgName, const std::string& resName, PackageItemType type = PackageItemType::UNKNOWN);
|
||||
static void* getItemAssetByURL(const std::string& url, PackageItemType type = PackageItemType::UNKNOWN);
|
||||
static cocos2d::Texture2D* getEmptyTexture() { return _emptyTexture; }
|
||||
|
||||
const std::string& getId() const { return _id; }
|
||||
const std::string& getName() const { return _name; }
|
||||
|
||||
PackageItem* getItem(const std::string& itemId);
|
||||
PackageItem* getItemByName(const std::string& itemName);
|
||||
void* getItemAsset(PackageItem* item);
|
||||
|
||||
static const std::string& getBranch() { return _branch; }
|
||||
static void setBranch(const std::string& value);
|
||||
static const std::string& getVar(const std::string& key);
|
||||
static void setVar(const std::string& key, const std::string& value);
|
||||
|
||||
static int _constructing;
|
||||
static const std::string URL_PREFIX;
|
||||
|
||||
private:
|
||||
bool loadPackage(ByteBuffer* buffer);
|
||||
void loadAtlas(PackageItem* item);
|
||||
AtlasSprite* getSprite(const std::string& spriteId);
|
||||
cocos2d::SpriteFrame* createSpriteTexture(AtlasSprite* sprite);
|
||||
void loadImage(PackageItem* item);
|
||||
void loadMovieClip(PackageItem* item);
|
||||
void loadFont(PackageItem* item);
|
||||
|
||||
GObject* createObject(const std::string& resName);
|
||||
GObject* createObject(PackageItem* item);
|
||||
|
||||
private:
|
||||
std::string _id;
|
||||
std::string _name;
|
||||
std::string _assetPath;
|
||||
|
||||
std::vector<PackageItem*> _items;
|
||||
std::unordered_map<std::string, PackageItem*> _itemsById;
|
||||
std::unordered_map<std::string, PackageItem*> _itemsByName;
|
||||
std::unordered_map<std::string, AtlasSprite*> _sprites;
|
||||
std::string _customId;
|
||||
std::vector<std::string> _stringTable;
|
||||
std::vector<std::unordered_map<std::string, std::string>> _dependencies;
|
||||
std::vector<std::string> _branches;
|
||||
int _branchIndex;
|
||||
|
||||
static std::unordered_map<std::string, UIPackage*> _packageInstById;
|
||||
static std::unordered_map<std::string, UIPackage*> _packageInstByName;
|
||||
static std::vector<UIPackage*> _packageList;
|
||||
static std::unordered_map<std::string, std::string> _vars;
|
||||
static std::string _branch;
|
||||
|
||||
static cocos2d::Texture2D* _emptyTexture;
|
||||
|
||||
friend class PackageItem;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,296 @@
|
|||
#include "Window.h"
|
||||
#include "GRoot.h"
|
||||
#include "UIPackage.h"
|
||||
#include "UIConfig.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
Window::Window() :
|
||||
_requestingCmd(0),
|
||||
_frame(nullptr),
|
||||
_contentPane(nullptr),
|
||||
_modalWaitPane(nullptr),
|
||||
_closeButton(nullptr),
|
||||
_dragArea(nullptr),
|
||||
_contentArea(nullptr),
|
||||
_modal(false),
|
||||
_inited(false),
|
||||
_loading(false)
|
||||
{
|
||||
_bringToFontOnClick = UIConfig::bringWindowToFrontOnClick;
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
{
|
||||
CC_SAFE_RELEASE(_contentPane);
|
||||
CC_SAFE_RELEASE(_frame);
|
||||
CC_SAFE_RELEASE(_closeButton);
|
||||
CC_SAFE_RELEASE(_dragArea);
|
||||
CC_SAFE_RELEASE(_modalWaitPane);
|
||||
}
|
||||
|
||||
void Window::handleInit()
|
||||
{
|
||||
GComponent::handleInit();
|
||||
|
||||
addEventListener(UIEventType::TouchBegin, CC_CALLBACK_1(Window::onTouchBegin, this));
|
||||
}
|
||||
|
||||
void Window::setContentPane(GComponent* value)
|
||||
{
|
||||
if (_contentPane != value)
|
||||
{
|
||||
if (_contentPane != nullptr)
|
||||
{
|
||||
removeChild(_contentPane);
|
||||
|
||||
CC_SAFE_RELEASE(_frame);
|
||||
_contentPane->release();
|
||||
}
|
||||
_contentPane = value;
|
||||
if (_contentPane != nullptr)
|
||||
{
|
||||
_contentPane->retain();
|
||||
|
||||
addChild(_contentPane);
|
||||
setSize(_contentPane->getWidth(), _contentPane->getHeight());
|
||||
_contentPane->addRelation(this, RelationType::Size);
|
||||
_frame = dynamic_cast<GComponent*>(_contentPane->getChild("frame"));
|
||||
if (_frame != nullptr)
|
||||
{
|
||||
_frame->retain();
|
||||
|
||||
setCloseButton(_frame->getChild("closeButton"));
|
||||
setDragArea(_frame->getChild("dragArea"));
|
||||
setContentArea(_frame->getChild("contentArea"));
|
||||
}
|
||||
}
|
||||
else
|
||||
_frame = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::setCloseButton(GObject * value)
|
||||
{
|
||||
if (_closeButton != nullptr)
|
||||
{
|
||||
_closeButton->removeClickListener(EventTag(this));
|
||||
_closeButton->release();
|
||||
}
|
||||
_closeButton = value;
|
||||
if (_closeButton != nullptr)
|
||||
{
|
||||
_closeButton->retain();
|
||||
_closeButton->addClickListener(CC_CALLBACK_1(Window::closeEventHandler, this), EventTag(this));
|
||||
}
|
||||
}
|
||||
|
||||
void Window::setDragArea(GObject * value)
|
||||
{
|
||||
if (_dragArea != value)
|
||||
{
|
||||
if (_dragArea != nullptr)
|
||||
{
|
||||
_dragArea->setDraggable(false);
|
||||
_dragArea->removeEventListener(UIEventType::DragStart, EventTag(this));
|
||||
_dragArea->release();
|
||||
}
|
||||
|
||||
_dragArea = value;
|
||||
if (_dragArea != nullptr)
|
||||
{
|
||||
_dragArea->retain();
|
||||
if (dynamic_cast<GGraph*>(_dragArea) && ((GGraph*)_dragArea)->isEmpty())
|
||||
((GGraph*)_dragArea)->drawRect(_dragArea->getWidth(), _dragArea->getHeight(), 0, Color4F(0, 0, 0, 0), Color4F(0, 0, 0, 0));
|
||||
_dragArea->setDraggable(true);
|
||||
_dragArea->addEventListener(UIEventType::DragStart, CC_CALLBACK_1(Window::onDragStart, this), EventTag(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::show()
|
||||
{
|
||||
UIRoot->showWindow(this);
|
||||
}
|
||||
|
||||
void Window::hide()
|
||||
{
|
||||
if (isShowing())
|
||||
doHideAnimation();
|
||||
}
|
||||
|
||||
void Window::hideImmediately()
|
||||
{
|
||||
UIRoot->hideWindowImmediately(this);
|
||||
}
|
||||
|
||||
void Window::toggleStatus()
|
||||
{
|
||||
if (isTop())
|
||||
hide();
|
||||
else
|
||||
show();
|
||||
}
|
||||
|
||||
void Window::bringToFront()
|
||||
{
|
||||
UIRoot->bringToFront(this);
|
||||
}
|
||||
|
||||
bool Window::isTop() const
|
||||
{
|
||||
return _parent != nullptr && _parent->getChildIndex(this) == _parent->numChildren() - 1;
|
||||
}
|
||||
|
||||
void Window::showModalWait(int requestingCmd)
|
||||
{
|
||||
if (requestingCmd != 0)
|
||||
_requestingCmd = requestingCmd;
|
||||
|
||||
if (!UIConfig::windowModalWaiting.empty())
|
||||
{
|
||||
if (_modalWaitPane == nullptr)
|
||||
{
|
||||
_modalWaitPane = UIPackage::createObjectFromURL(UIConfig::windowModalWaiting);
|
||||
_modalWaitPane->retain();
|
||||
}
|
||||
|
||||
layoutModalWaitPane();
|
||||
|
||||
addChild(_modalWaitPane);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::layoutModalWaitPane()
|
||||
{
|
||||
if (_contentArea != nullptr)
|
||||
{
|
||||
Vec2 pt = _frame->localToGlobal(Vec2::ZERO);
|
||||
pt = globalToLocal(pt);
|
||||
_modalWaitPane->setPosition((int)pt.x + _contentArea->getX(), (int)pt.y + _contentArea->getY());
|
||||
_modalWaitPane->setSize(_contentArea->getWidth(), _contentArea->getHeight());
|
||||
}
|
||||
else
|
||||
_modalWaitPane->setSize(_size.width, _size.height);
|
||||
}
|
||||
|
||||
bool Window::closeModalWait(int requestingCmd)
|
||||
{
|
||||
if (requestingCmd != 0)
|
||||
{
|
||||
if (_requestingCmd != requestingCmd)
|
||||
return false;
|
||||
}
|
||||
_requestingCmd = 0;
|
||||
|
||||
if (_modalWaitPane != nullptr && _modalWaitPane->getParent() != nullptr)
|
||||
removeChild(_modalWaitPane);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Window::initWindow()
|
||||
{
|
||||
if (_inited || _loading)
|
||||
return;
|
||||
|
||||
if (!_uiSources.empty())
|
||||
{
|
||||
_loading = false;
|
||||
int cnt = (int)_uiSources.size();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
IUISource* lib = _uiSources.at(i);
|
||||
if (!lib->isLoaded())
|
||||
{
|
||||
lib->load(CC_CALLBACK_0(Window::onUILoadComplete, this));
|
||||
_loading = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_loading)
|
||||
_initWindow();
|
||||
}
|
||||
else
|
||||
_initWindow();
|
||||
}
|
||||
|
||||
void Window::_initWindow()
|
||||
{
|
||||
_inited = true;
|
||||
onInit();
|
||||
|
||||
if (isShowing())
|
||||
doShowAnimation();
|
||||
}
|
||||
|
||||
void Window::addUISource(IUISource * uiSource)
|
||||
{
|
||||
_uiSources.pushBack(uiSource);
|
||||
}
|
||||
|
||||
void Window::doShowAnimation()
|
||||
{
|
||||
onShown();
|
||||
}
|
||||
|
||||
void Window::doHideAnimation()
|
||||
{
|
||||
hideImmediately();
|
||||
}
|
||||
|
||||
void Window::closeEventHandler(EventContext * context)
|
||||
{
|
||||
hide();
|
||||
}
|
||||
|
||||
void Window::onUILoadComplete()
|
||||
{
|
||||
int cnt = (int)_uiSources.size();
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
IUISource* lib = _uiSources.at(i);
|
||||
if (!lib->isLoaded())
|
||||
return;
|
||||
}
|
||||
|
||||
_loading = false;
|
||||
_initWindow();
|
||||
}
|
||||
|
||||
void Window::onEnter()
|
||||
{
|
||||
GComponent::onEnter();
|
||||
|
||||
if (!_inited)
|
||||
initWindow();
|
||||
else
|
||||
doShowAnimation();
|
||||
}
|
||||
|
||||
void Window::onExit()
|
||||
{
|
||||
GComponent::onExit();
|
||||
|
||||
closeModalWait();
|
||||
onHide();
|
||||
}
|
||||
|
||||
void Window::onTouchBegin(EventContext * context)
|
||||
{
|
||||
if (isShowing() && _bringToFontOnClick)
|
||||
{
|
||||
bringToFront();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::onDragStart(EventContext * context)
|
||||
{
|
||||
context->preventDefault();
|
||||
|
||||
startDrag(context->getInput()->getTouchId());
|
||||
}
|
||||
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,99 @@
|
|||
#ifndef __WINDOW_H__
|
||||
#define __WINDOW_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
#include "GComponent.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class IUISource : public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
virtual const std::string& getFileName() = 0;
|
||||
virtual void setFileName(const std::string& value) = 0;
|
||||
virtual bool isLoaded() = 0;
|
||||
virtual void load(std::function<void()> callback) = 0;
|
||||
};
|
||||
|
||||
class Window : public GComponent
|
||||
{
|
||||
public:
|
||||
Window();
|
||||
virtual ~Window();
|
||||
|
||||
CREATE_FUNC(Window);
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
void hideImmediately();
|
||||
void toggleStatus();
|
||||
void bringToFront();
|
||||
bool isShowing() const { return _parent != nullptr; }
|
||||
bool isTop() const;
|
||||
bool isModal() const { return _modal; }
|
||||
void setModal(bool value) { _modal = value; }
|
||||
|
||||
void showModalWait() { showModalWait(0); }
|
||||
void showModalWait(int requestingCmd);
|
||||
bool closeModalWait() { return closeModalWait(0); }
|
||||
bool closeModalWait(int requestingCmd);
|
||||
|
||||
void initWindow();
|
||||
void addUISource(IUISource* uiSource);
|
||||
|
||||
bool isBringToFrontOnClick() { return _bringToFontOnClick; }
|
||||
void setBringToFrontOnClick(bool value) { _bringToFontOnClick = value; }
|
||||
|
||||
GComponent* getContentPane() const { return _contentPane; }
|
||||
void setContentPane(GComponent* value);
|
||||
GComponent* getFrame() const { return _frame; }
|
||||
|
||||
GObject* getCloseButton() const { return _closeButton; }
|
||||
void setCloseButton(GObject* value);
|
||||
GObject* getDragArea() const { return _dragArea; }
|
||||
void setDragArea(GObject* value);
|
||||
GObject* getContentArea() const { return _contentArea; }
|
||||
void setContentArea(GObject* value) { _contentArea = value; }
|
||||
|
||||
GObject* getModalWaitingPane() const { return _modalWaitPane; }
|
||||
|
||||
protected:
|
||||
virtual void handleInit() override;
|
||||
virtual void onInit() {};
|
||||
virtual void onShown() {};
|
||||
virtual void onHide() {};
|
||||
virtual void doShowAnimation();
|
||||
virtual void doHideAnimation();
|
||||
|
||||
virtual void onEnter() override;
|
||||
virtual void onExit() override;
|
||||
|
||||
void closeEventHandler(EventContext*context);
|
||||
|
||||
GComponent* _contentPane;
|
||||
|
||||
private:
|
||||
void layoutModalWaitPane();
|
||||
void onUILoadComplete();
|
||||
void _initWindow();
|
||||
|
||||
void onTouchBegin(EventContext* context);
|
||||
void onDragStart(EventContext* context);
|
||||
|
||||
int _requestingCmd;
|
||||
GComponent* _frame;
|
||||
GObject* _modalWaitPane;
|
||||
GObject* _closeButton;
|
||||
GObject* _dragArea;
|
||||
GObject* _contentArea;
|
||||
bool _modal;
|
||||
bool _bringToFontOnClick;
|
||||
cocos2d::Vector<IUISource*> _uiSources;
|
||||
bool _inited;
|
||||
bool _loading;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,50 @@
|
|||
#include "ChangePageAction.h"
|
||||
#include "Controller.h"
|
||||
#include "GComponent.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
void ChangePageAction::setup(ByteBuffer* buffer)
|
||||
{
|
||||
ControllerAction::setup(buffer);
|
||||
|
||||
objectId = buffer->readS();
|
||||
controllerName = buffer->readS();
|
||||
targetPage = buffer->readS();
|
||||
}
|
||||
|
||||
void ChangePageAction::enter(GController* controller)
|
||||
{
|
||||
if (controllerName.empty())
|
||||
return;
|
||||
|
||||
GComponent* gcom;
|
||||
if (!objectId.empty())
|
||||
gcom = controller->getParent()->getChildById(objectId)->as<GComponent>();
|
||||
else
|
||||
gcom = controller->getParent();
|
||||
if (gcom != nullptr)
|
||||
{
|
||||
GController* cc = gcom->getController(controllerName);
|
||||
if (cc != nullptr && cc != controller && !cc->changing)
|
||||
{
|
||||
if (targetPage.compare("~1") == 0)
|
||||
{
|
||||
if (controller->getSelectedIndex() < cc->getPageCount())
|
||||
cc->setSelectedIndex(controller->getSelectedIndex());
|
||||
}
|
||||
else if (targetPage.compare("~2") == 0)
|
||||
cc->setSelectedPage(controller->getSelectedPage());
|
||||
else
|
||||
cc->setSelectedPageId(targetPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChangePageAction::leave(GController* controller)
|
||||
{
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef __CHANGEPAGEACTION_H__
|
||||
#define __CHANGEPAGEACTION_H__
|
||||
|
||||
#include "ControllerAction.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class ChangePageAction : public ControllerAction
|
||||
{
|
||||
public:
|
||||
virtual void setup(ByteBuffer * buffer) override;
|
||||
|
||||
std::string objectId;
|
||||
std::string controllerName;
|
||||
std::string targetPage;
|
||||
|
||||
protected:
|
||||
virtual void enter(GController* controller) override;
|
||||
virtual void leave(GController* controller) override;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
#include "ControllerAction.h"
|
||||
#include "Controller.h"
|
||||
#include "ChangePageAction.h"
|
||||
#include "PlayTransitionAction.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
#include "utils/ToolSet.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
ControllerAction * ControllerAction::createAction(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
return new PlayTransitionAction();
|
||||
|
||||
case 1:
|
||||
return new ChangePageAction();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ControllerAction::ControllerAction()
|
||||
{
|
||||
}
|
||||
|
||||
ControllerAction::~ControllerAction()
|
||||
{
|
||||
}
|
||||
|
||||
void ControllerAction::run(GController * controller, const std::string & prevPage, const std::string & curPage)
|
||||
{
|
||||
if ((fromPage.empty() || std::find(fromPage.cbegin(), fromPage.cend(), prevPage) != fromPage.cend())
|
||||
&& (toPage.empty() || std::find(toPage.cbegin(), toPage.cend(), curPage) != toPage.cend()))
|
||||
enter(controller);
|
||||
else
|
||||
leave(controller);
|
||||
}
|
||||
|
||||
void ControllerAction::setup(ByteBuffer * buffer)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
cnt = buffer->readShort();
|
||||
fromPage.resize(cnt);
|
||||
for (int i = 0; i < cnt; i++)
|
||||
fromPage[i].assign(buffer->readS());
|
||||
|
||||
cnt = buffer->readShort();
|
||||
toPage.resize(cnt);
|
||||
for (int i = 0; i < cnt; i++)
|
||||
toPage[i].assign(buffer->readS());
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef __CONTROLLERACTION_H__
|
||||
#define __CONTROLLERACTION_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GController;
|
||||
class ByteBuffer;
|
||||
|
||||
class ControllerAction
|
||||
{
|
||||
public:
|
||||
static ControllerAction* createAction(int types);
|
||||
|
||||
ControllerAction();
|
||||
virtual ~ControllerAction();
|
||||
|
||||
void run(GController* controller, const std::string& prevPage, const std::string& curPage);
|
||||
virtual void setup(ByteBuffer * buffer);
|
||||
|
||||
std::vector<std::string> fromPage;
|
||||
std::vector<std::string> toPage;
|
||||
|
||||
protected:
|
||||
virtual void enter(GController* controller) = 0;
|
||||
virtual void leave(GController* controller) = 0;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,46 @@
|
|||
#include "PlayTransitionAction.h"
|
||||
#include "Controller.h"
|
||||
#include "GComponent.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
PlayTransitionAction::PlayTransitionAction() :
|
||||
playTimes(1), delay(0), stopOnExit(false), _currentTransition(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void PlayTransitionAction::setup(ByteBuffer * buffer)
|
||||
{
|
||||
ControllerAction::setup(buffer);
|
||||
|
||||
transitionName = buffer->readS();
|
||||
playTimes = buffer->readInt();
|
||||
delay = buffer->readFloat();
|
||||
stopOnExit = buffer->readBool();
|
||||
}
|
||||
|
||||
void PlayTransitionAction::enter(GController * controller)
|
||||
{
|
||||
Transition* trans = controller->getParent()->getTransition(transitionName);
|
||||
if (trans != nullptr)
|
||||
{
|
||||
if (_currentTransition != nullptr && _currentTransition->isPlaying())
|
||||
trans->changePlayTimes(playTimes);
|
||||
else
|
||||
trans->play(playTimes, delay, nullptr);
|
||||
_currentTransition = trans;
|
||||
}
|
||||
}
|
||||
|
||||
void PlayTransitionAction::leave(GController * controller)
|
||||
{
|
||||
if (stopOnExit && _currentTransition != nullptr)
|
||||
{
|
||||
_currentTransition->stop();
|
||||
_currentTransition = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef __PLAYTRNASITIONACTION_H__
|
||||
#define __PLAYTRNASITIONACTION_H__
|
||||
|
||||
#include "ControllerAction.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class Transition;
|
||||
|
||||
class PlayTransitionAction : public ControllerAction
|
||||
{
|
||||
public:
|
||||
PlayTransitionAction();
|
||||
virtual void setup(ByteBuffer * buffer) override;
|
||||
|
||||
std::string transitionName;
|
||||
int playTimes;
|
||||
float delay;
|
||||
bool stopOnExit;
|
||||
|
||||
protected:
|
||||
virtual void enter(GController* controller) override;
|
||||
virtual void leave(GController* controller) override;
|
||||
|
||||
Transition* _currentTransition;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#include "BitmapFont.h"
|
||||
|
||||
USING_NS_FGUI;
|
||||
|
||||
BitmapFont::BitmapFont():_fontAtlas(nullptr),_originalFontSize(0),_resizable(false)
|
||||
{
|
||||
}
|
||||
|
||||
BitmapFont::~BitmapFont()
|
||||
{
|
||||
}
|
||||
|
||||
BitmapFont * BitmapFont::create()
|
||||
{
|
||||
BitmapFont *font = new BitmapFont();
|
||||
font->autorelease();
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
int * BitmapFont::getHorizontalKerningForTextUTF32(const std::u32string & text, int & outNumLetters) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef __BITMAPFONT_H__
|
||||
#define __BITMAPFONT_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
#include "PackageItem.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class BitmapFont : public cocos2d::Font
|
||||
{
|
||||
public:
|
||||
BitmapFont();
|
||||
virtual ~BitmapFont();
|
||||
|
||||
static BitmapFont* create();
|
||||
|
||||
virtual int* getHorizontalKerningForTextUTF32(const std::u32string& text, int &outNumLetters) const override;
|
||||
virtual cocos2d::FontAtlas *createFontAtlas() override { return _fontAtlas; }
|
||||
void releaseAtlas() { _fontAtlas->release(); }
|
||||
void setFontSize(float fontSize) {}
|
||||
int getOriginalFontSize()const { return _originalFontSize; }
|
||||
bool isResizable() { return _resizable; }
|
||||
bool canTint() { return _canTint; }
|
||||
|
||||
private:
|
||||
float _originalFontSize;
|
||||
bool _resizable;
|
||||
bool _canTint;
|
||||
cocos2d::FontAtlas* _fontAtlas;
|
||||
|
||||
friend class UIPackage;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,507 @@
|
|||
#include "FUIContainer.h"
|
||||
#include "base/CCStencilStateManager.h"
|
||||
#include "utils/ToolSet.h"
|
||||
#include "GComponent.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
#if COCOS2D_VERSION < 0x00040000
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
|
||||
#define CC_CLIPPING_NODE_OPENGLES 0
|
||||
#else
|
||||
#define CC_CLIPPING_NODE_OPENGLES 1
|
||||
#endif
|
||||
|
||||
#if CC_CLIPPING_NODE_OPENGLES
|
||||
static void setProgram(Node *n, GLProgram *p)
|
||||
{
|
||||
n->setGLProgram(p);
|
||||
|
||||
auto& children = n->getChildren();
|
||||
for (const auto &child : children) {
|
||||
setProgram(child, p);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // COCOS2D_VERSION < 0x00040000
|
||||
|
||||
RectClippingSupport::RectClippingSupport() :
|
||||
_clippingEnabled(false),
|
||||
_scissorOldState(false),
|
||||
_clippingRectDirty(true)
|
||||
{
|
||||
}
|
||||
|
||||
StencilClippingSupport::StencilClippingSupport() :
|
||||
_stencil(nullptr),
|
||||
_originStencilProgram(nullptr),
|
||||
_stencilStateManager(new StencilStateManager())
|
||||
{
|
||||
}
|
||||
|
||||
FUIContainer::FUIContainer() :
|
||||
_rectClippingSupport(nullptr),
|
||||
_stencilClippingSupport(nullptr),
|
||||
gOwner(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
FUIContainer::~FUIContainer()
|
||||
{
|
||||
CC_SAFE_DELETE(_rectClippingSupport);
|
||||
if (_stencilClippingSupport)
|
||||
{
|
||||
if (_stencilClippingSupport->_stencil)
|
||||
{
|
||||
_stencilClippingSupport->_stencil->stopAllActions();
|
||||
_stencilClippingSupport->_stencil->release();
|
||||
}
|
||||
CC_SAFE_DELETE(_stencilClippingSupport->_stencilStateManager);
|
||||
delete _stencilClippingSupport;
|
||||
}
|
||||
}
|
||||
|
||||
bool FUIContainer::isClippingEnabled() const
|
||||
{
|
||||
if (_rectClippingSupport != nullptr)
|
||||
return _rectClippingSupport->_clippingEnabled;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void FUIContainer::setClippingEnabled(bool value)
|
||||
{
|
||||
if (_rectClippingSupport == nullptr)
|
||||
{
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
_rectClippingSupport = new RectClippingSupport();
|
||||
}
|
||||
|
||||
_rectClippingSupport->_clippingEnabled = value;
|
||||
}
|
||||
|
||||
const Rect & FUIContainer::getClippingRegion() const
|
||||
{
|
||||
if (_rectClippingSupport != nullptr)
|
||||
return _rectClippingSupport->_clippingRegion;
|
||||
else
|
||||
return Rect::ZERO;
|
||||
}
|
||||
|
||||
void FUIContainer::setClippingRegion(const Rect & clippingRegion)
|
||||
{
|
||||
if (_rectClippingSupport == nullptr)
|
||||
_rectClippingSupport = new RectClippingSupport();
|
||||
|
||||
_rectClippingSupport->_clippingRegion = clippingRegion;
|
||||
}
|
||||
|
||||
cocos2d::Node * FUIContainer::getStencil() const
|
||||
{
|
||||
if (_stencilClippingSupport != nullptr)
|
||||
return _stencilClippingSupport->_stencil;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FUIContainer::setStencil(cocos2d::Node * stencil)
|
||||
{
|
||||
if (_stencilClippingSupport == nullptr)
|
||||
{
|
||||
if (stencil == nullptr)
|
||||
return;
|
||||
|
||||
_stencilClippingSupport = new StencilClippingSupport();
|
||||
}
|
||||
|
||||
//early out if the stencil is already set
|
||||
if (_stencilClippingSupport->_stencil == stencil)
|
||||
return;
|
||||
|
||||
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
|
||||
auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
|
||||
if (sEngine)
|
||||
{
|
||||
if (_stencilClippingSupport->_stencil)
|
||||
sEngine->releaseScriptObject(this, _stencilClippingSupport->_stencil);
|
||||
if (stencil)
|
||||
sEngine->retainScriptObject(this, stencil);
|
||||
}
|
||||
#endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
|
||||
|
||||
//cleanup current stencil
|
||||
if (_stencilClippingSupport->_stencil != nullptr && _stencilClippingSupport->_stencil->isRunning())
|
||||
{
|
||||
_stencilClippingSupport->_stencil->onExitTransitionDidStart();
|
||||
_stencilClippingSupport->_stencil->onExit();
|
||||
}
|
||||
CC_SAFE_RELEASE_NULL(_stencilClippingSupport->_stencil);
|
||||
|
||||
//initialise new stencil
|
||||
_stencilClippingSupport->_stencil = stencil;
|
||||
CC_SAFE_RETAIN(_stencilClippingSupport->_stencil);
|
||||
if (_stencilClippingSupport->_stencil != nullptr && this->isRunning())
|
||||
{
|
||||
_stencilClippingSupport->_stencil->onEnter();
|
||||
if (this->_isTransitionFinished)
|
||||
{
|
||||
_stencilClippingSupport->_stencil->onEnterTransitionDidFinish();
|
||||
}
|
||||
}
|
||||
|
||||
if (_stencilClippingSupport->_stencil != nullptr)
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
_stencilClippingSupport->_originStencilProgram = _stencilClippingSupport->_stencil->getProgramState();
|
||||
#else
|
||||
_stencilClippingSupport->_originStencilProgram = _stencilClippingSupport->_stencil->getGLProgram();
|
||||
#endif
|
||||
}
|
||||
|
||||
float FUIContainer::getAlphaThreshold() const
|
||||
{
|
||||
if (_stencilClippingSupport != nullptr)
|
||||
return _stencilClippingSupport->_stencilStateManager->getAlphaThreshold();
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
void FUIContainer::setAlphaThreshold(float alphaThreshold)
|
||||
{
|
||||
if (_stencilClippingSupport == nullptr)
|
||||
_stencilClippingSupport = new StencilClippingSupport();
|
||||
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
if (alphaThreshold == 1 && alphaThreshold != _stencilClippingSupport->_stencilStateManager->getAlphaThreshold()) {
|
||||
if (_stencilClippingSupport->_stencil) {
|
||||
restoreAllProgramStates();
|
||||
}
|
||||
}
|
||||
#else
|
||||
#if CC_CLIPPING_NODE_OPENGLES
|
||||
if (alphaThreshold == 1 && alphaThreshold != _stencilClippingSupport->_stencilStateManager->getAlphaThreshold())
|
||||
{
|
||||
// should reset program used by _stencil
|
||||
if (_stencilClippingSupport->_stencil)
|
||||
setProgram(_stencilClippingSupport->_stencil, _stencilClippingSupport->_originStencilProgram);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_stencilClippingSupport->_stencilStateManager->setAlphaThreshold(alphaThreshold);
|
||||
}
|
||||
|
||||
bool FUIContainer::isInverted() const
|
||||
{
|
||||
if (_stencilClippingSupport != nullptr)
|
||||
return _stencilClippingSupport->_stencilStateManager->isInverted();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void FUIContainer::setInverted(bool inverted)
|
||||
{
|
||||
if (_stencilClippingSupport == nullptr)
|
||||
_stencilClippingSupport = new StencilClippingSupport();
|
||||
|
||||
_stencilClippingSupport->_stencilStateManager->setInverted(inverted);
|
||||
}
|
||||
|
||||
void FUIContainer::onEnter()
|
||||
{
|
||||
#if CC_ENABLE_SCRIPT_BINDING
|
||||
if (_scriptType == kScriptTypeJavascript)
|
||||
{
|
||||
if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnEnter))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Node::onEnter();
|
||||
|
||||
if (_stencilClippingSupport != nullptr && _stencilClippingSupport->_stencil != nullptr)
|
||||
_stencilClippingSupport->_stencil->onEnter();
|
||||
|
||||
if (_rectClippingSupport != nullptr)
|
||||
_rectClippingSupport->_clippingRectDirty = true;
|
||||
}
|
||||
|
||||
void FUIContainer::onEnterTransitionDidFinish()
|
||||
{
|
||||
#if CC_ENABLE_SCRIPT_BINDING
|
||||
if (_scriptType == kScriptTypeJavascript)
|
||||
{
|
||||
if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnEnterTransitionDidFinish))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Node::onEnterTransitionDidFinish();
|
||||
|
||||
if (_stencilClippingSupport != nullptr && _stencilClippingSupport->_stencil != nullptr)
|
||||
{
|
||||
_stencilClippingSupport->_stencil->onEnterTransitionDidFinish();
|
||||
}
|
||||
}
|
||||
|
||||
void FUIContainer::onExitTransitionDidStart()
|
||||
{
|
||||
#if CC_ENABLE_SCRIPT_BINDING
|
||||
if (_scriptType == kScriptTypeJavascript)
|
||||
{
|
||||
if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnExitTransitionDidStart))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_stencilClippingSupport != nullptr && _stencilClippingSupport->_stencil != nullptr)
|
||||
_stencilClippingSupport->_stencil->onExitTransitionDidStart();
|
||||
Node::onExitTransitionDidStart();
|
||||
}
|
||||
|
||||
void FUIContainer::onExit()
|
||||
{
|
||||
#if CC_ENABLE_SCRIPT_BINDING
|
||||
if (_scriptType == kScriptTypeJavascript)
|
||||
{
|
||||
if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnExit))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_stencilClippingSupport != nullptr && _stencilClippingSupport->_stencil != nullptr)
|
||||
_stencilClippingSupport->_stencil->onExit();
|
||||
|
||||
Node::onExit();
|
||||
}
|
||||
|
||||
void FUIContainer::setCameraMask(unsigned short mask, bool applyChildren)
|
||||
{
|
||||
Node::setCameraMask(mask, applyChildren);
|
||||
|
||||
if (_stencilClippingSupport != nullptr && _stencilClippingSupport->_stencil != nullptr)
|
||||
_stencilClippingSupport->_stencil->setCameraMask(mask, applyChildren);
|
||||
}
|
||||
|
||||
void FUIContainer::setContentSize(const Size & contentSize)
|
||||
{
|
||||
Node::setContentSize(contentSize);
|
||||
|
||||
if (_rectClippingSupport)
|
||||
_rectClippingSupport->_clippingRectDirty = true;
|
||||
}
|
||||
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
void FUIContainer::setProgramStateRecursively(Node* node, backend::ProgramState* programState)
|
||||
{
|
||||
_originalStencilProgramState[node] = node->getProgramState();
|
||||
node->setProgramState(programState);
|
||||
|
||||
auto& children = node->getChildren();
|
||||
for (const auto &child : children) {
|
||||
setProgramStateRecursively(child, programState);
|
||||
}
|
||||
}
|
||||
|
||||
void FUIContainer::restoreAllProgramStates()
|
||||
{
|
||||
for (auto item : _originalStencilProgramState)
|
||||
{
|
||||
auto node = item.first;
|
||||
auto programState = item.second;
|
||||
node->setProgramState(programState);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void FUIContainer::onBeforeVisitScissor()
|
||||
{
|
||||
auto glview = Director::getInstance()->getOpenGLView();
|
||||
_rectClippingSupport->_scissorOldState = glview->isScissorEnabled();
|
||||
Rect clippingRect = getClippingRect();
|
||||
if (false == _rectClippingSupport->_scissorOldState)
|
||||
{
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
Director::getInstance()->getRenderer()->setScissorTest(true);
|
||||
#else
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
_rectClippingSupport->_clippingOldRect = glview->getScissorRect();
|
||||
clippingRect = ToolSet::intersection(clippingRect, _rectClippingSupport->_clippingOldRect);
|
||||
}
|
||||
|
||||
glview->setScissorInPoints(clippingRect.origin.x,
|
||||
clippingRect.origin.y,
|
||||
clippingRect.size.width,
|
||||
clippingRect.size.height);
|
||||
}
|
||||
|
||||
void FUIContainer::onAfterVisitScissor()
|
||||
{
|
||||
if (_rectClippingSupport->_scissorOldState)
|
||||
{
|
||||
auto glview = Director::getInstance()->getOpenGLView();
|
||||
glview->setScissorInPoints(_rectClippingSupport->_clippingOldRect.origin.x,
|
||||
_rectClippingSupport->_clippingOldRect.origin.y,
|
||||
_rectClippingSupport->_clippingOldRect.size.width,
|
||||
_rectClippingSupport->_clippingOldRect.size.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
// revert scissor test
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
Director::getInstance()->getRenderer()->setScissorTest(false);
|
||||
#else
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
const Rect& FUIContainer::getClippingRect()
|
||||
{
|
||||
if (_rectClippingSupport->_clippingRectDirty)
|
||||
{
|
||||
Vec2 worldPos = convertToWorldSpaceAR(_rectClippingSupport->_clippingRegion.origin);
|
||||
AffineTransform t = getNodeToWorldAffineTransform();
|
||||
float scissorWidth = _rectClippingSupport->_clippingRegion.size.width*t.a;
|
||||
float scissorHeight = _rectClippingSupport->_clippingRegion.size.height*t.d;
|
||||
_rectClippingSupport->_clippingRect.setRect(worldPos.x - (scissorWidth * _anchorPoint.x), worldPos.y - (scissorHeight * _anchorPoint.y), scissorWidth, scissorHeight);
|
||||
_rectClippingSupport->_clippingRectDirty = false;
|
||||
}
|
||||
return _rectClippingSupport->_clippingRect;
|
||||
}
|
||||
|
||||
void FUIContainer::visit(cocos2d::Renderer * renderer, const cocos2d::Mat4 & parentTransform, uint32_t parentFlags)
|
||||
{
|
||||
if (_stencilClippingSupport != nullptr)
|
||||
{
|
||||
if (!_visible || _children.empty())
|
||||
return;
|
||||
|
||||
uint32_t flags = processParentFlags(parentTransform, parentFlags);
|
||||
|
||||
// IMPORTANT:
|
||||
// To ease the migration to v3.0, we still support the Mat4 stack,
|
||||
// but it is deprecated and your code should not rely on it
|
||||
Director* director = Director::getInstance();
|
||||
CCASSERT(nullptr != director, "Director is null when setting matrix stack");
|
||||
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
||||
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
|
||||
|
||||
//Add group command
|
||||
|
||||
_stencilClippingSupport->_groupCommand.init(_globalZOrder);
|
||||
renderer->addCommand(&_stencilClippingSupport->_groupCommand);
|
||||
|
||||
renderer->pushGroup(_stencilClippingSupport->_groupCommand.getRenderQueueID());
|
||||
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
_stencilClippingSupport->_stencilStateManager->onBeforeVisit(_globalZOrder);
|
||||
#else
|
||||
_stencilClippingSupport->_beforeVisitCmd.init(_globalZOrder);
|
||||
_stencilClippingSupport->_beforeVisitCmd.func = CC_CALLBACK_0(StencilStateManager::onBeforeVisit, _stencilClippingSupport->_stencilStateManager);
|
||||
renderer->addCommand(&_stencilClippingSupport->_beforeVisitCmd);
|
||||
#endif
|
||||
|
||||
auto alphaThreshold = this->getAlphaThreshold();
|
||||
if (alphaThreshold < 1)
|
||||
{
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST);
|
||||
auto programState = new (std::nothrow) backend::ProgramState(program);
|
||||
auto alphaLocation = programState->getUniformLocation("u_alpha_value");
|
||||
programState->setUniform(alphaLocation, &alphaThreshold, sizeof(alphaThreshold));
|
||||
setProgramStateRecursively(_stencilClippingSupport->_stencil, programState);
|
||||
CC_SAFE_RELEASE_NULL(programState);
|
||||
#else
|
||||
#if CC_CLIPPING_NODE_OPENGLES
|
||||
// since glAlphaTest do not exists in OES, use a shader that writes
|
||||
// pixel only if greater than an alpha threshold
|
||||
GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_ALPHA_TEST_NO_MV);
|
||||
GLint alphaValueLocation = glGetUniformLocation(program->getProgram(), GLProgram::UNIFORM_NAME_ALPHA_TEST_VALUE);
|
||||
// set our alphaThreshold
|
||||
program->use();
|
||||
program->setUniformLocationWith1f(alphaValueLocation, alphaThreshold);
|
||||
// we need to recursively apply this shader to all the nodes in the stencil node
|
||||
// FIXME: we should have a way to apply shader to all nodes without having to do this
|
||||
setProgram(_stencilClippingSupport->_stencil, program);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
_stencilClippingSupport->_stencil->visit(renderer, _modelViewTransform, flags);
|
||||
|
||||
_stencilClippingSupport->_afterDrawStencilCmd.init(_globalZOrder);
|
||||
_stencilClippingSupport->_afterDrawStencilCmd.func = CC_CALLBACK_0(StencilStateManager::onAfterDrawStencil, _stencilClippingSupport->_stencilStateManager);
|
||||
renderer->addCommand(&_stencilClippingSupport->_afterDrawStencilCmd);
|
||||
|
||||
int i = 0;
|
||||
bool visibleByCamera = isVisitableByVisitingCamera();
|
||||
|
||||
if (!_children.empty())
|
||||
{
|
||||
sortAllChildren();
|
||||
// draw children zOrder < 0
|
||||
for (auto size = _children.size(); i < size; ++i)
|
||||
{
|
||||
auto node = _children.at(i);
|
||||
|
||||
if (node && node->getLocalZOrder() < 0)
|
||||
node->visit(renderer, _modelViewTransform, flags);
|
||||
else
|
||||
break;
|
||||
}
|
||||
// self draw
|
||||
if (visibleByCamera)
|
||||
this->draw(renderer, _modelViewTransform, flags);
|
||||
|
||||
for (auto it = _children.cbegin() + i, itCend = _children.cend(); it != itCend; ++it)
|
||||
(*it)->visit(renderer, _modelViewTransform, flags);
|
||||
}
|
||||
else if (visibleByCamera)
|
||||
{
|
||||
this->draw(renderer, _modelViewTransform, flags);
|
||||
}
|
||||
|
||||
_stencilClippingSupport->_afterVisitCmd.init(_globalZOrder);
|
||||
_stencilClippingSupport->_afterVisitCmd.func = CC_CALLBACK_0(StencilStateManager::onAfterVisit, _stencilClippingSupport->_stencilStateManager);
|
||||
renderer->addCommand(&_stencilClippingSupport->_afterVisitCmd);
|
||||
|
||||
renderer->popGroup();
|
||||
|
||||
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
||||
}
|
||||
else if (_rectClippingSupport != nullptr && _rectClippingSupport->_clippingEnabled)
|
||||
{
|
||||
if (parentFlags & FLAGS_DIRTY_MASK)
|
||||
{
|
||||
_rectClippingSupport->_clippingRectDirty = true;
|
||||
}
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
_rectClippingSupport->_groupCommand.init(_globalZOrder);
|
||||
renderer->addCommand(&_rectClippingSupport->_groupCommand);
|
||||
renderer->pushGroup(_rectClippingSupport->_groupCommand.getRenderQueueID());
|
||||
#endif
|
||||
_rectClippingSupport->_beforeVisitCmdScissor.init(_globalZOrder);
|
||||
_rectClippingSupport->_beforeVisitCmdScissor.func = CC_CALLBACK_0(FUIContainer::onBeforeVisitScissor, this);
|
||||
renderer->addCommand(&_rectClippingSupport->_beforeVisitCmdScissor);
|
||||
|
||||
Node::visit(renderer, parentTransform, parentFlags);
|
||||
|
||||
_rectClippingSupport->_afterVisitCmdScissor.init(_globalZOrder);
|
||||
_rectClippingSupport->_afterVisitCmdScissor.func = CC_CALLBACK_0(FUIContainer::onAfterVisitScissor, this);
|
||||
renderer->addCommand(&_rectClippingSupport->_afterVisitCmdScissor);
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
renderer->popGroup();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
Node::visit(renderer, parentTransform, parentFlags);
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,115 @@
|
|||
#ifndef __FUICONTAINER_H__
|
||||
#define __FUICONTAINER_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GObject;
|
||||
|
||||
class RectClippingSupport
|
||||
{
|
||||
public:
|
||||
RectClippingSupport();
|
||||
|
||||
cocos2d::Rect _clippingRegion;
|
||||
bool _clippingEnabled;
|
||||
bool _scissorOldState;
|
||||
cocos2d::Rect _clippingOldRect;
|
||||
cocos2d::Rect _clippingRect;
|
||||
bool _clippingRectDirty;
|
||||
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
cocos2d::GroupCommand _groupCommand;
|
||||
cocos2d::CallbackCommand _beforeVisitCmdScissor;
|
||||
cocos2d::CallbackCommand _afterVisitCmdScissor;
|
||||
#else
|
||||
cocos2d::CustomCommand _beforeVisitCmdScissor;
|
||||
cocos2d::CustomCommand _afterVisitCmdScissor;
|
||||
#endif
|
||||
};
|
||||
|
||||
class StencilClippingSupport
|
||||
{
|
||||
public:
|
||||
StencilClippingSupport();
|
||||
|
||||
cocos2d::Node* _stencil;
|
||||
cocos2d::StencilStateManager* _stencilStateManager;
|
||||
cocos2d::GroupCommand _groupCommand;
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
cocos2d::backend::ProgramState* _originStencilProgram;
|
||||
cocos2d::CallbackCommand _beforeVisitCmd;
|
||||
cocos2d::CallbackCommand _afterDrawStencilCmd;
|
||||
cocos2d::CallbackCommand _afterVisitCmd;
|
||||
#else
|
||||
cocos2d::GLProgram* _originStencilProgram;
|
||||
cocos2d::CustomCommand _beforeVisitCmd;
|
||||
cocos2d::CustomCommand _afterDrawStencilCmd;
|
||||
cocos2d::CustomCommand _afterVisitCmd;
|
||||
#endif
|
||||
};
|
||||
|
||||
class FUIContainer : public cocos2d::Node
|
||||
{
|
||||
public:
|
||||
FUIContainer();
|
||||
virtual ~FUIContainer();
|
||||
|
||||
CREATE_FUNC(FUIContainer);
|
||||
|
||||
bool isClippingEnabled() const;
|
||||
void setClippingEnabled(bool value);
|
||||
const cocos2d::Rect& getClippingRegion() const;
|
||||
void setClippingRegion(const cocos2d::Rect& clippingRegion);
|
||||
|
||||
cocos2d::Node* getStencil() const;
|
||||
void setStencil(cocos2d::Node* stencil);
|
||||
float getAlphaThreshold() const;
|
||||
void setAlphaThreshold(float alphaThreshold);
|
||||
bool isInverted() const;
|
||||
void setInverted(bool inverted);
|
||||
|
||||
void onEnter() override;
|
||||
void onEnterTransitionDidFinish() override;
|
||||
void onExitTransitionDidStart() override;
|
||||
void onExit() override;
|
||||
void visit(cocos2d::Renderer *renderer, const cocos2d::Mat4 &parentTransform, uint32_t parentFlags) override;
|
||||
void setCameraMask(unsigned short mask, bool applyChildren = true) override;
|
||||
|
||||
virtual void setContentSize(const cocos2d::Size& contentSize) override;
|
||||
|
||||
GObject* gOwner;
|
||||
private:
|
||||
void onBeforeVisitScissor();
|
||||
void onAfterVisitScissor();
|
||||
const cocos2d::Rect& getClippingRect();
|
||||
|
||||
RectClippingSupport* _rectClippingSupport;
|
||||
StencilClippingSupport* _stencilClippingSupport;
|
||||
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
void setProgramStateRecursively(Node* node, cocos2d::backend::ProgramState* programState);
|
||||
void restoreAllProgramStates();
|
||||
|
||||
std::unordered_map<Node*, cocos2d::backend::ProgramState*> _originalStencilProgramState;
|
||||
#endif
|
||||
};
|
||||
|
||||
//internal use
|
||||
class FUIInnerContainer : public cocos2d::Node
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(FUIInnerContainer);
|
||||
|
||||
void setPosition2(const cocos2d::Vec2 &position) { setPosition(position.x, _parent->getContentSize().height - position.y); }
|
||||
cocos2d::Vec2 getPosition2() { return cocos2d::Vec2(_position.x, _parent->getContentSize().height - _position.y); }
|
||||
void setPosition2(float x, float y) { setPosition(x, _parent->getContentSize().height - y); }
|
||||
void setPositionY2(float y) { setPositionY(_parent->getContentSize().height - y); }
|
||||
float getPositionY2(void) const { return _parent->getContentSize().height - _position.y; }
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,102 @@
|
|||
#include "FUIInput.h"
|
||||
#include "UIPackage.h"
|
||||
#include "GTextInput.h"
|
||||
#include "UIConfig.h"
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
FUIInput * FUIInput::create()
|
||||
{
|
||||
FUIInput* pRet = new (std::nothrow) FUIInput();
|
||||
|
||||
if (pRet != nullptr && pRet->initWithSizeAndBackgroundSprite(Size(100, 100),
|
||||
(ui::Scale9Sprite*)ui::Scale9Sprite::createWithTexture(UIPackage::getEmptyTexture())))
|
||||
{
|
||||
pRet->autorelease();
|
||||
pRet->continueInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
CC_SAFE_DELETE(pRet);
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
|
||||
FUIInput::FUIInput() :
|
||||
_textFormat(new TextFormat()),
|
||||
_password(false),
|
||||
_keyboardType(0)
|
||||
{
|
||||
}
|
||||
|
||||
FUIInput::~FUIInput()
|
||||
{
|
||||
delete _textFormat;
|
||||
}
|
||||
|
||||
std::string FUIInput::getText() const
|
||||
{
|
||||
return ui::EditBox::getText();
|
||||
}
|
||||
|
||||
void FUIInput::setText(const std::string & value)
|
||||
{
|
||||
ui::EditBox::setText(value.c_str());
|
||||
}
|
||||
|
||||
void FUIInput::applyTextFormat()
|
||||
{
|
||||
setFontName(UIConfig::getRealFontName(_textFormat->face).c_str());
|
||||
setFontSize(_textFormat->fontSize);
|
||||
setPlaceholderFontSize(_textFormat->fontSize);
|
||||
setFontColor(_textFormat->color);
|
||||
//setPlaceholderFontColor(_textFormat->color);
|
||||
}
|
||||
|
||||
bool FUIInput::isSingleLine() const
|
||||
{
|
||||
return getInputMode() == ui::EditBox::InputMode::SINGLE_LINE;
|
||||
}
|
||||
|
||||
void FUIInput::setSingleLine(bool value)
|
||||
{
|
||||
setInputMode(ui::EditBox::InputMode::SINGLE_LINE);
|
||||
}
|
||||
|
||||
void FUIInput::setPassword(bool value)
|
||||
{
|
||||
_password = value;
|
||||
setInputFlag(ui::EditBox::InputFlag::PASSWORD);
|
||||
}
|
||||
|
||||
void FUIInput::setKeyboardType(int value)
|
||||
{
|
||||
//if (!_password)
|
||||
//setInputMode((ui::EditBox::InputMode)value);
|
||||
}
|
||||
|
||||
void FUIInput::openKeyboard()
|
||||
{
|
||||
#if COCOS2D_VERSION >= 0x00031700
|
||||
EditBox::openKeyboard();
|
||||
#else
|
||||
touchDownAction(this, cocos2d::ui::Widget::TouchEventType::ENDED);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FUIInput::continueInit()
|
||||
{
|
||||
applyTextFormat();
|
||||
|
||||
//disable default behavior
|
||||
this->setTouchEnabled(false);
|
||||
this->addTouchEventListener(CC_CALLBACK_2(FUIInput::_touchDownAction, this));
|
||||
}
|
||||
|
||||
void FUIInput::_touchDownAction(cocos2d::Ref *sender, cocos2d::ui::Widget::TouchEventType controlEvent)
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef __FUIINPUT_H__
|
||||
#define __FUIINPUT_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "ui/UIEditBox/UIEditBox.h"
|
||||
#include "TextFormat.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class FUIInput : public cocos2d::ui::EditBox
|
||||
{
|
||||
public:
|
||||
static FUIInput* create();
|
||||
|
||||
FUIInput();
|
||||
virtual ~FUIInput();
|
||||
|
||||
std::string getText() const;
|
||||
void setText(const std::string& value);
|
||||
|
||||
TextFormat* getTextFormat() const { return _textFormat; }
|
||||
void applyTextFormat();
|
||||
|
||||
bool isSingleLine() const;
|
||||
void setSingleLine(bool value);
|
||||
|
||||
bool isPassword() const { return _password; }
|
||||
void setPassword(bool value);
|
||||
|
||||
int keyboardType() const { return _keyboardType; }
|
||||
void setKeyboardType(int value);
|
||||
|
||||
void openKeyboard();
|
||||
|
||||
private:
|
||||
void continueInit();
|
||||
|
||||
void _touchDownAction(cocos2d::Ref *sender, cocos2d::ui::Widget::TouchEventType controlEvent);
|
||||
|
||||
TextFormat* _textFormat;
|
||||
bool _password;
|
||||
int _keyboardType;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,184 @@
|
|||
#include "FUILabel.h"
|
||||
#include "BitmapFont.h"
|
||||
#include "UIConfig.h"
|
||||
#include "UIPackage.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
static Color3B toGrayed(const Color3B& source)
|
||||
{
|
||||
Color3B c = source;
|
||||
c.r = c.g = c.b = c.r * 0.299f + c.g * 0.587f + c.b * 0.114f;
|
||||
return c;
|
||||
}
|
||||
|
||||
FUILabel::FUILabel() : _fontSize(-1),
|
||||
_bmFontCanTint(false),
|
||||
_textFormat(new TextFormat()),
|
||||
_grayed(false)
|
||||
{
|
||||
}
|
||||
|
||||
FUILabel::~FUILabel()
|
||||
{
|
||||
delete _textFormat;
|
||||
}
|
||||
|
||||
void FUILabel::setText(const std::string& value)
|
||||
{
|
||||
if (_fontSize < 0)
|
||||
applyTextFormat();
|
||||
|
||||
setString(value);
|
||||
}
|
||||
|
||||
void FUILabel::applyTextFormat()
|
||||
{
|
||||
if (_fontSize < 0 /**first time**/ || _fontName != _textFormat->face)
|
||||
{
|
||||
_fontName = _textFormat->face;
|
||||
Label::LabelType oldType = _currentLabelType;
|
||||
|
||||
if (_fontName.find("ui://") != -1)
|
||||
{
|
||||
setBMFontFilePath(_fontName);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool ttf = false;
|
||||
const std::string& fontName = UIConfig::getRealFontName(_fontName, &ttf);
|
||||
if (ttf)
|
||||
{
|
||||
_fontConfig.fontFilePath = fontName;
|
||||
_fontConfig.fontSize = _textFormat->fontSize;
|
||||
setTTFConfig(_fontConfig);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSystemFontName(fontName);
|
||||
}
|
||||
|
||||
if (oldType == LabelType::BMFONT)
|
||||
setTextColor((Color4B)_textFormat->color);
|
||||
}
|
||||
}
|
||||
|
||||
if (_fontSize != _textFormat->fontSize)
|
||||
{
|
||||
_fontSize = _textFormat->fontSize;
|
||||
if (_currentLabelType == LabelType::STRING_TEXTURE)
|
||||
{
|
||||
setSystemFontSize(_fontSize);
|
||||
}
|
||||
else if (_currentLabelType == LabelType::BMFONT)
|
||||
{
|
||||
setBMFontSize(_fontSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fontConfig.fontSize = _fontSize;
|
||||
setTTFConfig(_fontConfig);
|
||||
}
|
||||
}
|
||||
|
||||
if (_currentLabelType != LabelType::BMFONT)
|
||||
setTextColor((Color4B)(_grayed ? toGrayed(_textFormat->color) : _textFormat->color));
|
||||
else if (_bmFontCanTint)
|
||||
setColor(_grayed ? toGrayed(_textFormat->color) : _textFormat->color);
|
||||
|
||||
if (_textFormat->underline)
|
||||
enableUnderline();
|
||||
else
|
||||
disableEffect(LabelEffect::UNDERLINE);
|
||||
|
||||
if (_textFormat->italics)
|
||||
enableItalics();
|
||||
else
|
||||
disableEffect(LabelEffect::ITALICS);
|
||||
|
||||
if (_textFormat->bold && _currentLabelType != LabelType::STRING_TEXTURE)
|
||||
enableBold();
|
||||
else
|
||||
disableEffect(LabelEffect::BOLD);
|
||||
|
||||
setLineSpacing(_textFormat->lineSpacing);
|
||||
setHorizontalAlignment(_textFormat->align);
|
||||
setVerticalAlignment(_textFormat->verticalAlign);
|
||||
|
||||
if (_textFormat->hasEffect(TextFormat::OUTLINE))
|
||||
enableOutline((Color4B)(_grayed ? toGrayed(_textFormat->outlineColor) : _textFormat->outlineColor), _textFormat->outlineSize);
|
||||
else
|
||||
disableEffect(LabelEffect::OUTLINE);
|
||||
|
||||
if (_textFormat->hasEffect(TextFormat::SHADOW))
|
||||
enableShadow((Color4B)(_grayed ? toGrayed(_textFormat->shadowColor) : _textFormat->shadowColor), _textFormat->shadowOffset);
|
||||
else if (!_textFormat->bold)
|
||||
disableEffect(LabelEffect::SHADOW);
|
||||
}
|
||||
|
||||
bool FUILabel::setBMFontFilePath(const std::string& bmfontFilePath, const Vec2& imageOffset, float fontSize)
|
||||
{
|
||||
BitmapFont* bmFont = (BitmapFont*)UIPackage::getItemAssetByURL(bmfontFilePath, PackageItemType::FONT);
|
||||
if (bmFont == nullptr)
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
//assign the default fontSize
|
||||
if (std::abs(fontSize) < FLT_EPSILON)
|
||||
{
|
||||
float originalFontSize = bmFont->getOriginalFontSize();
|
||||
_bmFontSize = originalFontSize / CC_CONTENT_SCALE_FACTOR();
|
||||
}
|
||||
|
||||
if (fontSize > 0.0f && bmFont->isResizable())
|
||||
{
|
||||
_bmFontSize = fontSize;
|
||||
}
|
||||
|
||||
_bmFontPath = bmfontFilePath;
|
||||
_bmFontCanTint = bmFont->canTint();
|
||||
|
||||
_currentLabelType = LabelType::BMFONT;
|
||||
setFontAtlas(bmFont->createFontAtlas());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FUILabel::setGrayed(bool value)
|
||||
{
|
||||
if (_grayed != value)
|
||||
{
|
||||
_grayed = value;
|
||||
|
||||
if (_currentLabelType != LabelType::BMFONT)
|
||||
setTextColor((Color4B)(_grayed ? toGrayed(_textFormat->color) : _textFormat->color));
|
||||
else if (_bmFontCanTint)
|
||||
setColor(_grayed ? toGrayed(_textFormat->color) : _textFormat->color);
|
||||
|
||||
if (_textFormat->hasEffect(TextFormat::OUTLINE))
|
||||
enableOutline((Color4B)(_grayed ? toGrayed(_textFormat->outlineColor) : _textFormat->outlineColor), _textFormat->outlineSize);
|
||||
|
||||
if (_textFormat->hasEffect(TextFormat::SHADOW))
|
||||
enableShadow((Color4B)(_grayed ? toGrayed(_textFormat->shadowColor) : _textFormat->shadowColor), _textFormat->shadowOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void FUILabel::updateBMFontScale()
|
||||
{
|
||||
auto font = _fontAtlas->getFont();
|
||||
if (_currentLabelType == LabelType::BMFONT)
|
||||
{
|
||||
BitmapFont* bmFont = (BitmapFont*)font;
|
||||
float originalFontSize = bmFont->getOriginalFontSize();
|
||||
_bmfontScale = _bmFontSize * CC_CONTENT_SCALE_FACTOR() / originalFontSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
_bmfontScale = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef __FUILABEL_H__
|
||||
#define __FUILABEL_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "TextFormat.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class FUILabel : public cocos2d::Label
|
||||
{
|
||||
public:
|
||||
FUILabel();
|
||||
virtual ~FUILabel();
|
||||
|
||||
CREATE_FUNC(FUILabel);
|
||||
|
||||
const std::string& getText() const { return getString(); }
|
||||
void setText(const std::string& value);
|
||||
|
||||
TextFormat* getTextFormat() const { return _textFormat; }
|
||||
void applyTextFormat();
|
||||
|
||||
virtual bool setBMFontFilePath(const std::string& bmfontFilePath, const cocos2d::Vec2& imageOffset = cocos2d::Vec2::ZERO, float fontSize = 0) override;
|
||||
|
||||
void setGrayed(bool value);
|
||||
protected:
|
||||
/*
|
||||
注意!!!如果这里出现了编译错误,需要修改cocos2d的源码,文件2d/CCLabel.h,大约在672行,为updateBMFontScale函数打上virtual修饰符。
|
||||
因为这个方法里有强制字体对象指针为FontFnt类型的代码,但我们不使用FontFnt(FontFnt只支持从外部文件中载入配置,更糟糕的是BMFontConfiguration是定义在cpp里的。)
|
||||
所以需要重写这个方法。
|
||||
*/
|
||||
virtual void updateBMFontScale() override;
|
||||
|
||||
private:
|
||||
TextFormat* _textFormat;
|
||||
std::string _fontName;
|
||||
int _fontSize;
|
||||
bool _bmFontCanTint;
|
||||
bool _grayed;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,780 @@
|
|||
#include "FUIRichText.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <locale>
|
||||
#include <algorithm>
|
||||
|
||||
#include "utils/ToolSet.h"
|
||||
#include "UIPackage.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
static const int GUTTER_X = 2;
|
||||
static const int GUTTER_Y = 2;
|
||||
|
||||
static int getPrevWord(const std::string& text, int idx)
|
||||
{
|
||||
// start from idx-1
|
||||
for (int i = idx - 1; i >= 0; --i)
|
||||
{
|
||||
if (!std::isalnum(text[i], std::locale()))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool isWrappable(const std::string& text)
|
||||
{
|
||||
for (size_t i = 0, size = text.length(); i < size; ++i)
|
||||
{
|
||||
if (!std::isalnum(text[i], std::locale()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static float getPaddingAmount(TextHAlignment alignment, const float leftOver) {
|
||||
switch (alignment) {
|
||||
case TextHAlignment::CENTER:
|
||||
return leftOver / 2.f;
|
||||
case TextHAlignment::RIGHT:
|
||||
return leftOver;
|
||||
default:
|
||||
CCASSERT(false, "invalid horizontal alignment!");
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isWhitespace(char c) {
|
||||
return std::isspace(c, std::locale());
|
||||
}
|
||||
|
||||
static void ltrim(std::string& s) {
|
||||
s.erase(s.begin(), std::find_if_not(s.begin(),
|
||||
s.end(),
|
||||
isWhitespace));
|
||||
}
|
||||
|
||||
static void rtrim(std::string& s) {
|
||||
s.erase(std::find_if_not(s.rbegin(),
|
||||
s.rend(),
|
||||
isWhitespace).base(),
|
||||
s.end());
|
||||
}
|
||||
|
||||
static float stripTrailingWhitespace(const std::vector<cocos2d::Node*>& row) {
|
||||
if (!row.empty()) {
|
||||
if (auto label = dynamic_cast<Label*>(row.back())) {
|
||||
const auto width = label->getContentSize().width;
|
||||
auto str = label->getString();
|
||||
rtrim(str);
|
||||
if (label->getString() != str) {
|
||||
label->setString(str);
|
||||
return label->getContentSize().width - width;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
static std::string getSubStringOfUTF8String(const std::string& str, std::string::size_type start, std::string::size_type length)
|
||||
{
|
||||
std::u32string utf32;
|
||||
if (!StringUtils::UTF8ToUTF32(str, utf32)) {
|
||||
CCLOGERROR("Can't convert string to UTF-32: %s", str.c_str());
|
||||
return "";
|
||||
}
|
||||
if (utf32.size() < start) {
|
||||
CCLOGERROR("'start' is out of range: %ld, %s", static_cast<long>(start), str.c_str());
|
||||
return "";
|
||||
}
|
||||
std::string result;
|
||||
if (!StringUtils::UTF32ToUTF8(utf32.substr(start, length), result)) {
|
||||
CCLOGERROR("Can't convert internal UTF-32 string to UTF-8: %s", str.c_str());
|
||||
return "";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class FUIRichElement
|
||||
{
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
TEXT,
|
||||
IMAGE,
|
||||
LINK
|
||||
};
|
||||
|
||||
FUIRichElement(Type type);
|
||||
virtual ~FUIRichElement() {};
|
||||
|
||||
Type _type;
|
||||
std::string text;
|
||||
TextFormat textFormat;
|
||||
int width;
|
||||
int height;
|
||||
FUIRichElement* link;
|
||||
};
|
||||
|
||||
FUIRichElement::FUIRichElement(Type type) :
|
||||
_type(type),
|
||||
width(0),
|
||||
height(0),
|
||||
link(nullptr)
|
||||
{
|
||||
};
|
||||
|
||||
class FUIXMLVisitor : public SAXDelegator
|
||||
{
|
||||
public:
|
||||
explicit FUIXMLVisitor(FUIRichText* richText);
|
||||
virtual ~FUIXMLVisitor();
|
||||
|
||||
void startElement(void *ctx, const char *name, const char **atts) override;
|
||||
void endElement(void *ctx, const char *name) override;
|
||||
void textHandler(void *ctx, const char *s, size_t len) override;
|
||||
|
||||
private:
|
||||
ValueMap tagAttrMapWithXMLElement(const char ** attrs);
|
||||
int attributeInt(const ValueMap& vm, const std::string& key, int defaultValue);
|
||||
|
||||
void pushTextFormat();
|
||||
void popTextFormat();
|
||||
void addNewLine(bool check);
|
||||
void finishTextBlock();
|
||||
|
||||
FUIRichText* _richText;
|
||||
std::vector<TextFormat> _textFormatStack;
|
||||
std::vector<FUIRichElement*> _linkStack;
|
||||
TextFormat _format;
|
||||
size_t _textFormatStackTop;
|
||||
int _skipText;
|
||||
bool _ignoreWhiteSpace;
|
||||
std::string _textBlock;
|
||||
};
|
||||
|
||||
FUIXMLVisitor::FUIXMLVisitor(FUIRichText* richText)
|
||||
: _richText(richText),
|
||||
_textFormatStackTop(0),
|
||||
_skipText(0),
|
||||
_ignoreWhiteSpace(false)
|
||||
{
|
||||
_format = *_richText->_defaultTextFormat;
|
||||
}
|
||||
|
||||
FUIXMLVisitor::~FUIXMLVisitor()
|
||||
{
|
||||
}
|
||||
|
||||
void FUIXMLVisitor::pushTextFormat()
|
||||
{
|
||||
if (_textFormatStack.size() <= _textFormatStackTop)
|
||||
_textFormatStack.push_back(_format);
|
||||
else
|
||||
_textFormatStack[_textFormatStackTop] = _format;
|
||||
_textFormatStackTop++;
|
||||
}
|
||||
|
||||
void FUIXMLVisitor::popTextFormat()
|
||||
{
|
||||
if (_textFormatStackTop > 0)
|
||||
{
|
||||
_format = _textFormatStack[_textFormatStackTop - 1];
|
||||
_textFormatStackTop--;
|
||||
}
|
||||
}
|
||||
|
||||
void FUIXMLVisitor::addNewLine(bool check)
|
||||
{
|
||||
FUIRichElement* lastElement = _richText->_richElements.empty() ? nullptr : _richText->_richElements.back();
|
||||
if (lastElement && lastElement->_type == FUIRichElement::Type::TEXT)
|
||||
{
|
||||
if (!check || lastElement->text.back() != '\n')
|
||||
lastElement->text += "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
FUIRichElement* element = new FUIRichElement(FUIRichElement::Type::TEXT);
|
||||
element->textFormat = _format;
|
||||
element->text = "\n";
|
||||
_richText->_richElements.push_back(element);
|
||||
if (!_linkStack.empty())
|
||||
element->link = _linkStack.back();
|
||||
}
|
||||
|
||||
void FUIXMLVisitor::finishTextBlock()
|
||||
{
|
||||
if (!_textBlock.empty())
|
||||
{
|
||||
FUIRichElement* element = new FUIRichElement(FUIRichElement::Type::TEXT);
|
||||
element->textFormat = _format;
|
||||
element->text = _textBlock;
|
||||
_textBlock.clear();
|
||||
_richText->_richElements.push_back(element);
|
||||
if (!_linkStack.empty())
|
||||
element->link = _linkStack.back();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning(once:4307)
|
||||
void FUIXMLVisitor::startElement(void* /*ctx*/, const char *elementName, const char **atts)
|
||||
{
|
||||
finishTextBlock();
|
||||
|
||||
if (strcasecmp(elementName, "b") == 0)
|
||||
{
|
||||
pushTextFormat();
|
||||
_format.bold = true;
|
||||
}
|
||||
else if (strcasecmp(elementName, "i") == 0)
|
||||
{
|
||||
pushTextFormat();
|
||||
_format.italics = true;
|
||||
}
|
||||
else if (strcasecmp(elementName, "u") == 0)
|
||||
{
|
||||
pushTextFormat();
|
||||
_format.underline = true;
|
||||
}
|
||||
else if (strcasecmp(elementName, "font") == 0)
|
||||
{
|
||||
pushTextFormat();
|
||||
ValueMap&& tagAttrValueMap = tagAttrMapWithXMLElement(atts);
|
||||
_format.fontSize = attributeInt(tagAttrValueMap, "size", _format.fontSize);
|
||||
|
||||
auto it = tagAttrValueMap.find("color");
|
||||
if (it != tagAttrValueMap.end())
|
||||
{
|
||||
_format.color = (Color3B)ToolSet::hexToColor(it->second.asString().c_str());
|
||||
_format._hasColor = true;
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(elementName, "br") == 0)
|
||||
{
|
||||
addNewLine(false);
|
||||
}
|
||||
else if (strcasecmp(elementName, "img") == 0)
|
||||
{
|
||||
std::string src;
|
||||
ValueMap&& tagAttrValueMap = tagAttrMapWithXMLElement(atts);
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
auto it = tagAttrValueMap.find("src");
|
||||
if (it != tagAttrValueMap.end()) {
|
||||
src = it->second.asString();
|
||||
}
|
||||
|
||||
if (!src.empty()) {
|
||||
PackageItem* pi = UIPackage::getItemByURL(src);
|
||||
if (pi)
|
||||
{
|
||||
width = pi->width;
|
||||
height = pi->height;
|
||||
}
|
||||
}
|
||||
|
||||
width = attributeInt(tagAttrValueMap, "width", width);
|
||||
height = attributeInt(tagAttrValueMap, "height", height);
|
||||
if (width == 0)
|
||||
width = 5;
|
||||
if (height == 0)
|
||||
height = 10;
|
||||
|
||||
FUIRichElement* element = new FUIRichElement(FUIRichElement::Type::IMAGE);
|
||||
element->width = width;
|
||||
element->height = height;
|
||||
element->text = src;
|
||||
_richText->_richElements.push_back(element);
|
||||
if (!_linkStack.empty())
|
||||
element->link = _linkStack.back();
|
||||
}
|
||||
else if (strcasecmp(elementName, "a") == 0)
|
||||
{
|
||||
pushTextFormat();
|
||||
|
||||
std::string href;
|
||||
ValueMap&& tagAttrValueMap = tagAttrMapWithXMLElement(atts);
|
||||
auto it = tagAttrValueMap.find("href");
|
||||
if (it != tagAttrValueMap.end())
|
||||
href = it->second.asString();
|
||||
|
||||
FUIRichElement* element = new FUIRichElement(FUIRichElement::Type::LINK);
|
||||
element->text = href;
|
||||
_richText->_richElements.push_back(element);
|
||||
_linkStack.push_back(element);
|
||||
|
||||
if (_richText->_anchorTextUnderline)
|
||||
_format.underline = true;
|
||||
if (!_format._hasColor)
|
||||
_format.color = _richText->_anchorFontColor;
|
||||
}
|
||||
else if (strcasecmp(elementName, "p") == 0 || strcasecmp(elementName, "ui") == 0 || strcasecmp(elementName, "div") == 0
|
||||
|| strcasecmp(elementName, "li") == 0)
|
||||
{
|
||||
addNewLine(true);
|
||||
}
|
||||
else if (strcasecmp(elementName, "html") == 0 || strcasecmp(elementName, "body") == 0)
|
||||
{
|
||||
//full html
|
||||
_ignoreWhiteSpace = true;
|
||||
}
|
||||
else if (strcasecmp(elementName, "head") == 0 || strcasecmp(elementName, "style") == 0 || strcasecmp(elementName, "script") == 0
|
||||
|| strcasecmp(elementName, "form") == 0)
|
||||
{
|
||||
_skipText++;
|
||||
}
|
||||
}
|
||||
|
||||
void FUIXMLVisitor::endElement(void* /*ctx*/, const char *elementName)
|
||||
{
|
||||
finishTextBlock();
|
||||
|
||||
if (strcasecmp(elementName, "b") == 0 || strcasecmp(elementName, "i") == 0 || strcasecmp(elementName, "u") == 0
|
||||
|| strcasecmp(elementName, "font") == 0)
|
||||
{
|
||||
popTextFormat();
|
||||
}
|
||||
else if (strcasecmp(elementName, "a") == 0)
|
||||
{
|
||||
popTextFormat();
|
||||
|
||||
if (!_linkStack.empty())
|
||||
_linkStack.pop_back();
|
||||
}
|
||||
else if (strcasecmp(elementName, "head") == 0 || strcasecmp(elementName, "style") == 0 || strcasecmp(elementName, "script") == 0
|
||||
|| strcasecmp(elementName, "form") == 0)
|
||||
{
|
||||
_skipText--;
|
||||
}
|
||||
}
|
||||
#pragma warning(default:4307)
|
||||
|
||||
void FUIXMLVisitor::textHandler(void* /*ctx*/, const char *str, size_t len)
|
||||
{
|
||||
if (_skipText != 0)
|
||||
return;
|
||||
|
||||
if (_ignoreWhiteSpace)
|
||||
{
|
||||
string s(str, len);
|
||||
ltrim(s);
|
||||
rtrim(s);
|
||||
_textBlock += s;
|
||||
}
|
||||
else
|
||||
_textBlock += string(str, len);
|
||||
}
|
||||
|
||||
ValueMap FUIXMLVisitor::tagAttrMapWithXMLElement(const char ** attrs)
|
||||
{
|
||||
ValueMap tagAttrValueMap;
|
||||
for (const char** attr = attrs; *attr != nullptr; attr = (attrs += 2)) {
|
||||
if (attr[0] && attr[1]) {
|
||||
tagAttrValueMap[attr[0]] = attr[1];
|
||||
}
|
||||
}
|
||||
return tagAttrValueMap;
|
||||
}
|
||||
|
||||
int FUIXMLVisitor::attributeInt(const ValueMap& valueMap, const std::string& key, int defaultValue)
|
||||
{
|
||||
auto it = valueMap.find(key);
|
||||
if (it != valueMap.end()) {
|
||||
string str = it->second.asString();
|
||||
if (!str.empty() && str.back() == '%')
|
||||
return ceil(atoi(str.substr(0, str.size() - 1).c_str()) / 100.0f*defaultValue);
|
||||
else
|
||||
return atoi(str.c_str());
|
||||
}
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
FUIRichText::FUIRichText() :
|
||||
_formatTextDirty(true),
|
||||
_textChanged(false),
|
||||
_leftSpaceWidth(0.0f),
|
||||
_textRectWidth(0.0f),
|
||||
_numLines(0),
|
||||
_overflow(Label::Overflow::NONE),
|
||||
_anchorTextUnderline(true),
|
||||
_anchorFontColor(Color3B::BLUE),
|
||||
_defaultTextFormat(new TextFormat())
|
||||
{
|
||||
}
|
||||
|
||||
FUIRichText::~FUIRichText()
|
||||
{
|
||||
for (auto &it : _richElements)
|
||||
delete it;
|
||||
}
|
||||
|
||||
bool FUIRichText::init()
|
||||
{
|
||||
if (!Node::init())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FUIRichText::setDimensions(float width, float height)
|
||||
{
|
||||
if ((_numLines > 1 && width != _dimensions.width) || width < _contentSize.width)
|
||||
_formatTextDirty = true;
|
||||
_dimensions.setSize(width, height);
|
||||
}
|
||||
|
||||
void FUIRichText::setText(const std::string & value)
|
||||
{
|
||||
_formatTextDirty = true;
|
||||
_textChanged = true;
|
||||
_text = value;
|
||||
}
|
||||
|
||||
void FUIRichText::applyTextFormat()
|
||||
{
|
||||
_textChanged = true;
|
||||
_formatTextDirty = true;
|
||||
}
|
||||
|
||||
void FUIRichText::setOverflow(cocos2d::Label::Overflow overflow)
|
||||
{
|
||||
if (_overflow != overflow)
|
||||
{
|
||||
_overflow = overflow;
|
||||
_formatTextDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
const Size & FUIRichText::getContentSize() const
|
||||
{
|
||||
if (_formatTextDirty)
|
||||
const_cast<FUIRichText*>(this)->formatText();
|
||||
|
||||
return Node::getContentSize();
|
||||
}
|
||||
|
||||
void FUIRichText::setAnchorTextUnderline(bool enable)
|
||||
{
|
||||
if (_anchorTextUnderline != enable)
|
||||
{
|
||||
_anchorTextUnderline = enable;
|
||||
_formatTextDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void FUIRichText::setAnchorFontColor(const cocos2d::Color3B & color)
|
||||
{
|
||||
_anchorFontColor = color;
|
||||
_formatTextDirty = true;
|
||||
}
|
||||
|
||||
const char* FUIRichText::hitTestLink(const cocos2d::Vec2 & worldPoint)
|
||||
{
|
||||
Rect rect;
|
||||
for (auto &child : _children)
|
||||
{
|
||||
FUIRichElement* element = (FUIRichElement*)child->getUserData();
|
||||
if (!element || !element->link)
|
||||
continue;
|
||||
|
||||
rect.size = child->getContentSize();
|
||||
if (rect.containsPoint(child->convertToNodeSpace(worldPoint)))
|
||||
return element->link->text.c_str();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FUIRichText::visit(cocos2d::Renderer * renderer, const cocos2d::Mat4 & parentTransform, uint32_t parentFlags)
|
||||
{
|
||||
if (_visible)
|
||||
formatText();
|
||||
|
||||
Node::visit(renderer, parentTransform, parentFlags);
|
||||
}
|
||||
|
||||
void FUIRichText::formatText()
|
||||
{
|
||||
if (!_formatTextDirty)
|
||||
return;
|
||||
|
||||
if (_textChanged)
|
||||
{
|
||||
_textChanged = false;
|
||||
_richElements.clear();
|
||||
_numLines = 0;
|
||||
|
||||
if (!_text.empty())
|
||||
{
|
||||
string xmlText = "<dummy>" + _text + "</dummy>";
|
||||
FUIXMLVisitor visitor(this);
|
||||
SAXParser parser;
|
||||
parser.setDelegator(&visitor);
|
||||
parser.parseIntrusive(&xmlText.front(), xmlText.length());
|
||||
}
|
||||
}
|
||||
|
||||
removeAllChildrenWithCleanup(true);
|
||||
_elementRenders.clear();
|
||||
_imageLoaders.clear();
|
||||
if (_overflow == Label::Overflow::NONE)
|
||||
_textRectWidth = FLT_MAX;
|
||||
else
|
||||
_textRectWidth = _dimensions.width - GUTTER_X * 2;
|
||||
|
||||
int size = (int)_richElements.size();
|
||||
if (size == 0)
|
||||
{
|
||||
formarRenderers();
|
||||
_formatTextDirty = false;
|
||||
return;
|
||||
}
|
||||
|
||||
addNewLine();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
FUIRichElement* element = static_cast<FUIRichElement*>(_richElements.at(i));
|
||||
switch (element->_type)
|
||||
{
|
||||
case FUIRichElement::Type::TEXT:
|
||||
{
|
||||
FastSplitter fs;
|
||||
fs.start(element->text.c_str(), (int)element->text.size(), '\n');
|
||||
bool first = true;
|
||||
while (fs.next())
|
||||
{
|
||||
if (!first)
|
||||
addNewLine();
|
||||
if (fs.getTextLength() > 0)
|
||||
handleTextRenderer(element, element->textFormat, string(fs.getText(), fs.getTextLength()));
|
||||
first = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FUIRichElement::Type::IMAGE:
|
||||
handleImageRenderer(element);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
formarRenderers();
|
||||
_formatTextDirty = false;
|
||||
}
|
||||
|
||||
void FUIRichText::addNewLine()
|
||||
{
|
||||
_leftSpaceWidth = _textRectWidth;
|
||||
_elementRenders.emplace_back();
|
||||
_numLines++;
|
||||
}
|
||||
|
||||
void FUIRichText::handleTextRenderer(FUIRichElement* element, const TextFormat& format, const std::string& text)
|
||||
{
|
||||
FUILabel* textRenderer = FUILabel::create();
|
||||
textRenderer->setCascadeOpacityEnabled(true);
|
||||
textRenderer->getTextFormat()->setFormat(format);
|
||||
textRenderer->applyTextFormat();
|
||||
textRenderer->setString(text);
|
||||
textRenderer->setUserData(element);
|
||||
|
||||
float textRendererWidth = textRenderer->getContentSize().width;
|
||||
_leftSpaceWidth -= textRendererWidth;
|
||||
if (_leftSpaceWidth >= 0)
|
||||
{
|
||||
_elementRenders.back().push_back(textRenderer);
|
||||
return;
|
||||
}
|
||||
|
||||
int leftLength = findSplitPositionForWord(textRenderer, text);
|
||||
|
||||
//The minimum cut length is 1, otherwise will cause the infinite loop.
|
||||
if (0 == leftLength) leftLength = 1;
|
||||
std::string leftWords = getSubStringOfUTF8String(text, 0, leftLength);
|
||||
int rightStart = leftLength;
|
||||
if (std::isspace(text[rightStart], std::locale()))
|
||||
rightStart++;
|
||||
std::string cutWords = getSubStringOfUTF8String(text, rightStart, text.length() - leftLength);
|
||||
if (leftLength > 0)
|
||||
{
|
||||
FUILabel* leftRenderer = FUILabel::create();
|
||||
leftRenderer->setCascadeOpacityEnabled(true);
|
||||
leftRenderer->getTextFormat()->setFormat(format);
|
||||
leftRenderer->applyTextFormat();
|
||||
leftRenderer->setString(getSubStringOfUTF8String(leftWords, 0, leftLength));
|
||||
leftRenderer->setUserData(element);
|
||||
_elementRenders.back().push_back(leftRenderer);
|
||||
}
|
||||
|
||||
if (cutWords.length() > 0)
|
||||
{
|
||||
addNewLine();
|
||||
handleTextRenderer(element, format, cutWords);
|
||||
}
|
||||
}
|
||||
|
||||
int FUIRichText::findSplitPositionForWord(cocos2d::Label* label, const std::string& text)
|
||||
{
|
||||
auto originalLeftSpaceWidth = _leftSpaceWidth + label->getContentSize().width;
|
||||
|
||||
bool startingNewLine = (_textRectWidth == originalLeftSpaceWidth);
|
||||
if (!isWrappable(text))
|
||||
{
|
||||
if (startingNewLine)
|
||||
return (int)text.length();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int idx = (int)text.size() - 1; idx >= 0; )
|
||||
{
|
||||
int newidx = getPrevWord(text, idx);
|
||||
if (newidx >= 0)
|
||||
{
|
||||
idx = newidx;
|
||||
auto leftStr = getSubStringOfUTF8String(text, 0, idx);
|
||||
label->setString(leftStr);
|
||||
if (label->getContentSize().width <= originalLeftSpaceWidth)
|
||||
return idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (startingNewLine)
|
||||
return idx;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// no spaces... return the original label + size
|
||||
label->setString(text);
|
||||
return (int)text.size();
|
||||
}
|
||||
|
||||
void FUIRichText::handleImageRenderer(FUIRichElement* element)
|
||||
{
|
||||
GLoader* loader = GLoader::create();
|
||||
_imageLoaders.pushBack(loader);
|
||||
loader->setSize(element->width, element->height);
|
||||
loader->setFill(LoaderFillType::SCALE_FREE);
|
||||
loader->setURL(element->text);
|
||||
loader->displayObject()->setUserData(element);
|
||||
|
||||
_leftSpaceWidth -= (element->width + 4);
|
||||
if (_leftSpaceWidth < 0.0f)
|
||||
{
|
||||
addNewLine();
|
||||
_elementRenders.back().push_back(loader->displayObject());
|
||||
_leftSpaceWidth -= (element->width + 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
_elementRenders.back().push_back(loader->displayObject());
|
||||
}
|
||||
}
|
||||
|
||||
void FUIRichText::formarRenderers()
|
||||
{
|
||||
float nextPosY = GUTTER_Y;
|
||||
float textWidth = 0;
|
||||
float textHeight = 0;
|
||||
for (auto& row : _elementRenders)
|
||||
{
|
||||
if (nextPosY != GUTTER_Y)
|
||||
nextPosY += _defaultTextFormat->lineSpacing - 3;
|
||||
|
||||
float nextPosX = GUTTER_X;
|
||||
float lineHeight = 0.0f;
|
||||
float lineTextHeight = 0.0f;
|
||||
for (auto& node : row)
|
||||
{
|
||||
lineHeight = MAX(node->getContentSize().height, lineHeight);
|
||||
if (((FUIRichElement*)node->getUserData())->_type == FUIRichElement::Type::TEXT)
|
||||
lineTextHeight = MAX(node->getContentSize().height, lineTextHeight);
|
||||
}
|
||||
|
||||
nextPosY += lineHeight;
|
||||
|
||||
for (auto& node : row)
|
||||
{
|
||||
node->setAnchorPoint(Vec2::ZERO);
|
||||
int adjustment = 0;
|
||||
if (((FUIRichElement*)node->getUserData())->_type == FUIRichElement::Type::IMAGE)
|
||||
{
|
||||
nextPosX += 2;
|
||||
adjustment = floor((lineHeight - node->getContentSize().height) / 2);
|
||||
}
|
||||
else //text
|
||||
{
|
||||
adjustment = floor((lineHeight - lineTextHeight) / 2);
|
||||
}
|
||||
node->setPosition(nextPosX, _dimensions.height - nextPosY + adjustment);
|
||||
this->addChild(node, 1);
|
||||
nextPosX += node->getContentSize().width;
|
||||
if (((FUIRichElement*)node->getUserData())->_type == FUIRichElement::Type::IMAGE)
|
||||
nextPosX += 2;
|
||||
}
|
||||
nextPosX += GUTTER_X;
|
||||
if (nextPosX > textWidth)
|
||||
textWidth = nextPosX;
|
||||
|
||||
if (_overflow != Label::Overflow::NONE)
|
||||
doHorizontalAlignment(row, nextPosX);
|
||||
}
|
||||
if (textWidth == GUTTER_X + GUTTER_X)
|
||||
textWidth = 0;
|
||||
else if (_numLines > 1 || (_defaultTextFormat->align != TextHAlignment::LEFT && _overflow != Label::Overflow::NONE))
|
||||
textWidth = MAX(_dimensions.width, textWidth);
|
||||
if (nextPosY != GUTTER_Y)
|
||||
textHeight = nextPosY + GUTTER_Y;
|
||||
else
|
||||
textHeight = 0;
|
||||
setContentSize(Size(textWidth, textHeight));
|
||||
|
||||
float oldDimensionsHeight = _dimensions.height;
|
||||
if (_overflow == Label::Overflow::NONE)
|
||||
_dimensions = _contentSize;
|
||||
else if (_overflow == Label::Overflow::RESIZE_HEIGHT)
|
||||
_dimensions.height = _contentSize.height;
|
||||
float delta = _contentSize.height - oldDimensionsHeight;
|
||||
if (_defaultTextFormat->verticalAlign == TextVAlignment::CENTER)
|
||||
delta -= floor((_dimensions.height - textHeight) * 0.5f);
|
||||
else if (_defaultTextFormat->verticalAlign == TextVAlignment::BOTTOM)
|
||||
delta -= _dimensions.height - textHeight;
|
||||
if (delta != 0)
|
||||
{
|
||||
Vec2 offset(0, delta);
|
||||
for (auto& row : _elementRenders)
|
||||
{
|
||||
for (auto& node : row)
|
||||
{
|
||||
node->setPosition(node->getPosition() + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_elementRenders.clear();
|
||||
}
|
||||
|
||||
void FUIRichText::doHorizontalAlignment(const std::vector<cocos2d::Node*> &row, float rowWidth) {
|
||||
if (_defaultTextFormat->align != TextHAlignment::LEFT) {
|
||||
const auto diff = stripTrailingWhitespace(row);
|
||||
const auto leftOver = _dimensions.width - (rowWidth + diff);
|
||||
const float leftPadding = getPaddingAmount(_defaultTextFormat->align, leftOver);
|
||||
const Vec2 offset(leftPadding, 0.f);
|
||||
for (auto& node : row) {
|
||||
node->setPosition(node->getPosition() + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef __FUIRICHTEXT_H__
|
||||
#define __FUIRICHTEXT_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "TextFormat.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class FUIXMLVisitor;
|
||||
class GLoader;
|
||||
class FUIRichElement;
|
||||
|
||||
class FUIRichText : public cocos2d::Node
|
||||
{
|
||||
public:
|
||||
FUIRichText();
|
||||
virtual ~FUIRichText();
|
||||
|
||||
CREATE_FUNC(FUIRichText);
|
||||
|
||||
const cocos2d::Size& getDimensions() const { return _dimensions; }
|
||||
void setDimensions(float width, float height);
|
||||
|
||||
void setText(const std::string& value);
|
||||
|
||||
TextFormat* getTextFormat() const { return _defaultTextFormat; }
|
||||
void applyTextFormat();
|
||||
|
||||
cocos2d::Label::Overflow getOverflow()const { return _overflow; }
|
||||
void setOverflow(cocos2d::Label::Overflow overflow);
|
||||
|
||||
bool isAnchorTextUnderline() { return _anchorTextUnderline; }
|
||||
void setAnchorTextUnderline(bool enable);
|
||||
|
||||
const cocos2d::Color3B& getAnchorFontColor() { return _anchorFontColor; }
|
||||
void setAnchorFontColor(const cocos2d::Color3B& color);
|
||||
|
||||
const char* hitTestLink(const cocos2d::Vec2& worldPoint);
|
||||
virtual void visit(cocos2d::Renderer *renderer, const cocos2d::Mat4 &parentTransform, uint32_t parentFlags) override;
|
||||
|
||||
virtual const cocos2d::Size& getContentSize() const override;
|
||||
|
||||
protected:
|
||||
virtual bool init() override;
|
||||
void formatText();
|
||||
void formarRenderers();
|
||||
void handleTextRenderer(FUIRichElement* element, const TextFormat& format, const std::string& text);
|
||||
void handleImageRenderer(FUIRichElement* element);
|
||||
void addNewLine();
|
||||
int findSplitPositionForWord(cocos2d::Label* label, const std::string& text);
|
||||
void doHorizontalAlignment(const std::vector<cocos2d::Node*>& row, float rowWidth);
|
||||
|
||||
std::vector<FUIRichElement*> _richElements;
|
||||
std::vector<std::vector<Node*>> _elementRenders;
|
||||
cocos2d::Vector<GLoader*> _imageLoaders;
|
||||
bool _formatTextDirty;
|
||||
bool _textChanged;
|
||||
cocos2d::Size _dimensions;
|
||||
float _leftSpaceWidth;
|
||||
float _textRectWidth;
|
||||
int _numLines;
|
||||
cocos2d::Label::Overflow _overflow;
|
||||
TextFormat* _defaultTextFormat;
|
||||
bool _anchorTextUnderline;
|
||||
cocos2d::Color3B _anchorFontColor;
|
||||
std::string _text;
|
||||
|
||||
friend class FUIXMLVisitor;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,535 @@
|
|||
#include "FUISprite.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
#define kProgressTextureCoordsCount 4
|
||||
// kProgressTextureCoords holds points {0,1} {0,0} {1,0} {1,1} we can represent it as bits
|
||||
const char kProgressTextureCoords = 0x4b;
|
||||
|
||||
Texture2D* FUISprite::_empty = nullptr;
|
||||
|
||||
FUISprite::FUISprite()
|
||||
: _fillMethod(FillMethod::None),
|
||||
_fillOrigin(FillOrigin::Left),
|
||||
_fillAmount(0),
|
||||
_fillClockwise(false),
|
||||
_vertexDataCount(0),
|
||||
_vertexData(nullptr),
|
||||
_vertexIndex(nullptr),
|
||||
_scaleByTile(false)
|
||||
{
|
||||
}
|
||||
|
||||
FUISprite::~FUISprite()
|
||||
{
|
||||
CC_SAFE_FREE(_vertexData);
|
||||
CC_SAFE_FREE(_vertexIndex);
|
||||
}
|
||||
|
||||
void FUISprite::clearContent()
|
||||
{
|
||||
setTexture(nullptr);
|
||||
CC_SAFE_RELEASE_NULL(_spriteFrame);
|
||||
setCenterRectNormalized(Rect(0, 0, 1, 1));
|
||||
|
||||
_empty = _texture;
|
||||
}
|
||||
|
||||
void FUISprite::setScale9Grid(Rect* value)
|
||||
{
|
||||
if (value == nullptr)
|
||||
{
|
||||
setCenterRectNormalized(Rect(0, 0, 1, 1));
|
||||
return;
|
||||
}
|
||||
|
||||
Rect insets = *value;
|
||||
|
||||
// When Insets == Zero --> we should use a 1/3 of its untrimmed size
|
||||
if (insets.equals(Rect::ZERO))
|
||||
{
|
||||
insets = Rect(_originalContentSize.width / 3.0f,
|
||||
_originalContentSize.height / 3.0f,
|
||||
_originalContentSize.width / 3.0f,
|
||||
_originalContentSize.height / 3.0f);
|
||||
}
|
||||
|
||||
// emulate invalid insets. shouldn't be supported, but the original code supported it.
|
||||
if (insets.origin.x > _originalContentSize.width)
|
||||
insets.origin.x = 0;
|
||||
if (insets.origin.y > _originalContentSize.height)
|
||||
insets.origin.y = 0;
|
||||
if (insets.size.width > _originalContentSize.width)
|
||||
insets.size.width = 1;
|
||||
if (insets.size.height > _originalContentSize.height)
|
||||
insets.size.height = 1;
|
||||
|
||||
// we have to convert from untrimmed to trimmed
|
||||
// Sprite::setCenterRect is using trimmed values (to be compatible with Cocos Creator)
|
||||
// Scale9Sprite::setCapInsects uses untrimmed values (which makes more sense)
|
||||
|
||||
// use _rect coordinates. recenter origin to calculate the
|
||||
// intersecting rectangle
|
||||
// can't use _offsetPosition since it is calculated using bottom-left as origin,
|
||||
// and the center rect is calculated using top-left
|
||||
insets.origin.x -= (_originalContentSize.width - _rect.size.width) / 2 + _unflippedOffsetPositionFromCenter.x;
|
||||
insets.origin.y -= (_originalContentSize.height - _rect.size.height) / 2 - _unflippedOffsetPositionFromCenter.y;
|
||||
|
||||
// intersecting rectangle
|
||||
const float x1 = std::max(insets.origin.x, 0.0f);
|
||||
const float y1 = std::max(insets.origin.y, 0.0f);
|
||||
const float x2 = std::min(insets.origin.x + insets.size.width, 0.0f + _rect.size.width);
|
||||
const float y2 = std::min(insets.origin.y + insets.size.height, 0.0f + _rect.size.height);
|
||||
|
||||
// centerRect uses the trimmed frame origin as 0,0.
|
||||
// so, recenter inset rect
|
||||
insets.setRect(x1,
|
||||
y1,
|
||||
x2 - x1,
|
||||
y2 - y1);
|
||||
|
||||
// Only update center rect while in slice mode.
|
||||
setCenterRect(insets);
|
||||
}
|
||||
|
||||
void FUISprite::setScaleByTile(bool value)
|
||||
{
|
||||
_scaleByTile = value;
|
||||
}
|
||||
|
||||
void FUISprite::setGrayed(bool value)
|
||||
{
|
||||
#if defined(ENGINEX_VERSION)
|
||||
auto isETC1 = getTexture();
|
||||
Sprite::setProgramState(cocos2d::backend::ProgramType::POSITION_TEXTURE);
|
||||
#elif COCOS2D_VERSION >= 0x00040000
|
||||
auto isETC1 = getTexture() && getTexture()->getAlphaTextureName();
|
||||
if (value) {
|
||||
Sprite::updateShaders(positionTextureColor_vert, (isETC1)?etc1Gray_frag:grayScale_frag);
|
||||
} else {
|
||||
Sprite::updateShaders(positionTextureColor_vert, (isETC1)?etc1_frag:positionTextureColor_frag);
|
||||
}
|
||||
#else
|
||||
GLProgramState* glState = nullptr;
|
||||
if (value)
|
||||
glState = GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_GRAYSCALE, getTexture());
|
||||
else
|
||||
glState = GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP, getTexture());
|
||||
|
||||
setGLProgramState(glState);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FUISprite::setFillMethod(FillMethod value)
|
||||
{
|
||||
if (_fillMethod != value)
|
||||
{
|
||||
_fillMethod = value;
|
||||
|
||||
if (_fillMethod != FillMethod::None)
|
||||
setupFill();
|
||||
else
|
||||
{
|
||||
CC_SAFE_FREE(_vertexData);
|
||||
CC_SAFE_FREE(_vertexIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FUISprite::setFillOrigin(FillOrigin value)
|
||||
{
|
||||
if (_fillOrigin != value)
|
||||
{
|
||||
_fillOrigin = value;
|
||||
|
||||
if (_fillMethod != FillMethod::None)
|
||||
setupFill();
|
||||
}
|
||||
}
|
||||
|
||||
void FUISprite::setFillClockwise(bool value)
|
||||
{
|
||||
if (_fillClockwise != value)
|
||||
{
|
||||
_fillClockwise = value;
|
||||
|
||||
if (_fillMethod != FillMethod::None)
|
||||
setupFill();
|
||||
}
|
||||
}
|
||||
|
||||
void FUISprite::setFillAmount(float value)
|
||||
{
|
||||
if (_fillAmount != value)
|
||||
{
|
||||
_fillAmount = value;
|
||||
|
||||
if (_fillMethod != FillMethod::None)
|
||||
setupFill();
|
||||
}
|
||||
}
|
||||
|
||||
void FUISprite::setContentSize(const Size& size)
|
||||
{
|
||||
if (_scaleByTile)
|
||||
setTextureRect(Rect(Vec2::ZERO, size));
|
||||
else
|
||||
Sprite::setContentSize(size);
|
||||
}
|
||||
|
||||
void FUISprite::setupFill()
|
||||
{
|
||||
if (_fillMethod == FillMethod::Horizontal || _fillMethod == FillMethod::Vertical)
|
||||
updateBar();
|
||||
else
|
||||
updateRadial();
|
||||
}
|
||||
|
||||
//from CCFUISprite.h
|
||||
///
|
||||
// @returns the vertex position from the texture coordinate
|
||||
///
|
||||
Tex2F FUISprite::textureCoordFromAlphaPoint(Vec2 alpha)
|
||||
{
|
||||
Tex2F ret(0.0f, 0.0f);
|
||||
|
||||
V3F_C4B_T2F_Quad quad = getQuad();
|
||||
Vec2 min(quad.bl.texCoords.u, quad.bl.texCoords.v);
|
||||
Vec2 max(quad.tr.texCoords.u, quad.tr.texCoords.v);
|
||||
// Fix bug #1303 so that progress timer handles sprite frame texture rotation
|
||||
if (isTextureRectRotated())
|
||||
{
|
||||
std::swap(alpha.x, alpha.y);
|
||||
}
|
||||
return Tex2F(min.x * (1.f - alpha.x) + max.x * alpha.x, min.y * (1.f - alpha.y) + max.y * alpha.y);
|
||||
}
|
||||
|
||||
Vec3 FUISprite::vertexFromAlphaPoint(Vec2 alpha)
|
||||
{
|
||||
Vec3 ret(0.0f, 0.0f, 0.0f);
|
||||
|
||||
V3F_C4B_T2F_Quad quad = getQuad();
|
||||
Vec2 min(quad.bl.vertices.x, quad.bl.vertices.y);
|
||||
Vec2 max(quad.tr.vertices.x, quad.tr.vertices.y);
|
||||
ret.x = min.x * (1.f - alpha.x) + max.x * alpha.x;
|
||||
ret.y = min.y * (1.f - alpha.y) + max.y * alpha.y;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FUISprite::updateColor(void)
|
||||
{
|
||||
Sprite::updateColor();
|
||||
|
||||
if (_vertexData)
|
||||
{
|
||||
Color4B sc = getQuad().tl.colors;
|
||||
for (int i = 0; i < _vertexDataCount; ++i)
|
||||
{
|
||||
_vertexData[i].colors = sc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
// Update does the work of mapping the texture onto the triangles
|
||||
// It now doesn't occur the cost of free/alloc data every update cycle.
|
||||
// It also only changes the percentage point but no other points if they have not
|
||||
// been modified.
|
||||
//
|
||||
// It now deals with flipped texture. If you run into this problem, just use the
|
||||
// sprite property and enable the methods flipX, flipY.
|
||||
///
|
||||
void FUISprite::updateRadial(void)
|
||||
{
|
||||
float angle = 2.f * ((float)M_PI) * (_fillClockwise ? (1.0f - _fillAmount) : _fillAmount);
|
||||
|
||||
// We find the vector to do a hit detection based on the percentage
|
||||
// We know the first vector is the one @ 12 o'clock (top,mid) so we rotate
|
||||
// from that by the progress angle around the _midpoint pivot
|
||||
Vec2 midpoint(0.5f, 0.5f);
|
||||
Vec2 topMid(0.5f, 1.f);
|
||||
Vec2 percentagePt = topMid.rotateByAngle(midpoint, angle);
|
||||
|
||||
int index = 0;
|
||||
Vec2 hit;
|
||||
|
||||
if (_fillAmount == 0.f)
|
||||
{
|
||||
// More efficient since we don't always need to check intersection
|
||||
// If the alpha is zero then the hit point is top mid and the index is 0.
|
||||
hit = topMid;
|
||||
index = 0;
|
||||
}
|
||||
else if (_fillAmount == 1.f)
|
||||
{
|
||||
// More efficient since we don't always need to check intersection
|
||||
// If the alpha is one then the hit point is top mid and the index is 4.
|
||||
hit = topMid;
|
||||
index = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We run a for loop checking the edges of the texture to find the
|
||||
// intersection point
|
||||
// We loop through five points since the top is split in half
|
||||
|
||||
float min_t = FLT_MAX;
|
||||
|
||||
for (int i = 0; i <= kProgressTextureCoordsCount; ++i)
|
||||
{
|
||||
int pIndex = (i + (kProgressTextureCoordsCount - 1)) % kProgressTextureCoordsCount;
|
||||
|
||||
Vec2 edgePtA = boundaryTexCoord(i % kProgressTextureCoordsCount);
|
||||
Vec2 edgePtB = boundaryTexCoord(pIndex);
|
||||
|
||||
// Remember that the top edge is split in half for the 12 o'clock position
|
||||
// Let's deal with that here by finding the correct endpoints
|
||||
if (i == 0)
|
||||
{
|
||||
edgePtB = edgePtA.lerp(edgePtB, 1 - midpoint.x);
|
||||
}
|
||||
else if (i == 4)
|
||||
{
|
||||
edgePtA = edgePtA.lerp(edgePtB, 1 - midpoint.x);
|
||||
}
|
||||
|
||||
// s and t are returned by ccpLineIntersect
|
||||
float s = 0, t = 0;
|
||||
if (Vec2::isLineIntersect(edgePtA, edgePtB, midpoint, percentagePt, &s, &t))
|
||||
{
|
||||
|
||||
// Since our hit test is on rays we have to deal with the top edge
|
||||
// being in split in half so we have to test as a segment
|
||||
if ((i == 0 || i == 4))
|
||||
{
|
||||
// s represents the point between edgePtA--edgePtB
|
||||
if (!(0.f <= s && s <= 1.f))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// As long as our t isn't negative we are at least finding a
|
||||
// correct hitpoint from _midpoint to percentagePt.
|
||||
if (t >= 0.f)
|
||||
{
|
||||
// Because the percentage line and all the texture edges are
|
||||
// rays we should only account for the shortest intersection
|
||||
if (t < min_t)
|
||||
{
|
||||
min_t = t;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have the minimum magnitude we can use that to find our intersection
|
||||
hit = midpoint + ((percentagePt - midpoint) * min_t);
|
||||
}
|
||||
|
||||
// The size of the vertex data is the index from the hitpoint
|
||||
// the 3 is for the _midpoint, 12 o'clock point and hitpoint position.
|
||||
|
||||
bool sameIndexCount = true;
|
||||
int triangleCount = 0;
|
||||
if (_vertexDataCount != index + 3)
|
||||
{
|
||||
sameIndexCount = false;
|
||||
CC_SAFE_FREE(_vertexData);
|
||||
CC_SAFE_FREE(_vertexIndex);
|
||||
_vertexDataCount = 0;
|
||||
}
|
||||
|
||||
if (!_vertexData)
|
||||
{
|
||||
_vertexDataCount = index + 3;
|
||||
triangleCount = _vertexDataCount - 2;
|
||||
_vertexData = (V3F_C4B_T2F*)malloc(_vertexDataCount * sizeof(*_vertexData));
|
||||
_vertexIndex = (unsigned short *)malloc(triangleCount * 3 * sizeof(*_vertexIndex));
|
||||
CCASSERT(_vertexData, "FUISprite. Not enough memory");
|
||||
}
|
||||
else
|
||||
{
|
||||
triangleCount = _vertexDataCount - 2;
|
||||
}
|
||||
|
||||
updateColor();
|
||||
|
||||
if (!sameIndexCount)
|
||||
{
|
||||
|
||||
// First we populate the array with the _midpoint, then all
|
||||
// vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint
|
||||
_vertexData[0].texCoords = textureCoordFromAlphaPoint(midpoint);
|
||||
_vertexData[0].vertices = vertexFromAlphaPoint(midpoint);
|
||||
|
||||
_vertexData[1].texCoords = textureCoordFromAlphaPoint(topMid);
|
||||
_vertexData[1].vertices = vertexFromAlphaPoint(topMid);
|
||||
|
||||
for (int i = 0; i < index; ++i)
|
||||
{
|
||||
Vec2 alphaPoint = boundaryTexCoord(i);
|
||||
_vertexData[i + 2].texCoords = textureCoordFromAlphaPoint(alphaPoint);
|
||||
_vertexData[i + 2].vertices = vertexFromAlphaPoint(alphaPoint);
|
||||
}
|
||||
}
|
||||
|
||||
// hitpoint will go last
|
||||
_vertexData[_vertexDataCount - 1].texCoords = textureCoordFromAlphaPoint(hit);
|
||||
_vertexData[_vertexDataCount - 1].vertices = vertexFromAlphaPoint(hit);
|
||||
|
||||
for (int i = 0; i < triangleCount; i++) {
|
||||
_vertexIndex[i * 3] = 0;
|
||||
_vertexIndex[i * 3 + 1] = i + 1;
|
||||
_vertexIndex[i * 3 + 2] = i + 2;
|
||||
}
|
||||
|
||||
_fillTriangles.verts = _vertexData;
|
||||
_fillTriangles.vertCount = _vertexDataCount;
|
||||
_fillTriangles.indices = _vertexIndex;
|
||||
_fillTriangles.indexCount = triangleCount * 3;
|
||||
}
|
||||
|
||||
///
|
||||
// Update does the work of mapping the texture onto the triangles for the bar
|
||||
// It now doesn't occur the cost of free/alloc data every update cycle.
|
||||
// It also only changes the percentage point but no other points if they have not
|
||||
// been modified.
|
||||
//
|
||||
// It now deals with flipped texture. If you run into this problem, just use the
|
||||
// sprite property and enable the methods flipX, flipY.
|
||||
///
|
||||
void FUISprite::updateBar(void)
|
||||
{
|
||||
Vec2 min, max;
|
||||
|
||||
if (_fillMethod == FillMethod::Horizontal)
|
||||
{
|
||||
if (_fillOrigin == FillOrigin::Left || _fillOrigin == FillOrigin::Top)
|
||||
{
|
||||
min = Vec2(0, 0);
|
||||
max = Vec2(_fillAmount, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
min = Vec2(1 - _fillAmount, 0);
|
||||
max = Vec2(1, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_fillOrigin == FillOrigin::Left || _fillOrigin == FillOrigin::Top)
|
||||
{
|
||||
min = Vec2(0, 1 - _fillAmount);
|
||||
max = Vec2(1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
min = Vec2(0, 0);
|
||||
max = Vec2(1, _fillAmount);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_vertexData)
|
||||
{
|
||||
_vertexDataCount = 4;
|
||||
_vertexData = (V3F_C4B_T2F*)malloc(_vertexDataCount * sizeof(*_vertexData));
|
||||
_vertexIndex = (unsigned short*)malloc(6 * sizeof(*_vertexIndex));
|
||||
CCASSERT(_vertexData, "FUISprite. Not enough memory");
|
||||
}
|
||||
// TOPLEFT
|
||||
_vertexData[0].texCoords = textureCoordFromAlphaPoint(Vec2(min.x, max.y));
|
||||
_vertexData[0].vertices = vertexFromAlphaPoint(Vec2(min.x, max.y));
|
||||
|
||||
// BOTLEFT
|
||||
_vertexData[1].texCoords = textureCoordFromAlphaPoint(Vec2(min.x, min.y));
|
||||
_vertexData[1].vertices = vertexFromAlphaPoint(Vec2(min.x, min.y));
|
||||
|
||||
// TOPRIGHT
|
||||
_vertexData[2].texCoords = textureCoordFromAlphaPoint(Vec2(max.x, max.y));
|
||||
_vertexData[2].vertices = vertexFromAlphaPoint(Vec2(max.x, max.y));
|
||||
|
||||
// BOTRIGHT
|
||||
_vertexData[3].texCoords = textureCoordFromAlphaPoint(Vec2(max.x, min.y));
|
||||
_vertexData[3].vertices = vertexFromAlphaPoint(Vec2(max.x, min.y));
|
||||
|
||||
_vertexIndex[0] = 0;
|
||||
_vertexIndex[1] = 1;
|
||||
_vertexIndex[2] = 2;
|
||||
_vertexIndex[3] = 2;
|
||||
_vertexIndex[4] = 1;
|
||||
_vertexIndex[5] = 3;
|
||||
|
||||
_fillTriangles.verts = _vertexData;
|
||||
_fillTriangles.vertCount = 4;
|
||||
_fillTriangles.indices = _vertexIndex;
|
||||
_fillTriangles.indexCount = 6;
|
||||
|
||||
updateColor();
|
||||
}
|
||||
|
||||
Vec2 FUISprite::boundaryTexCoord(char index)
|
||||
{
|
||||
if (index < kProgressTextureCoordsCount)
|
||||
{
|
||||
if (!_fillClockwise)
|
||||
{
|
||||
return Vec2((kProgressTextureCoords >> (7 - (index << 1))) & 1, (kProgressTextureCoords >> (7 - ((index << 1) + 1))) & 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Vec2((kProgressTextureCoords >> ((index << 1) + 1)) & 1, (kProgressTextureCoords >> (index << 1)) & 1);
|
||||
}
|
||||
}
|
||||
return Vec2::ZERO;
|
||||
}
|
||||
|
||||
void FUISprite::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags)
|
||||
{
|
||||
if (_texture == _empty)
|
||||
return;
|
||||
|
||||
if (_fillMethod == FillMethod::None)
|
||||
Sprite::draw(renderer, transform, flags);
|
||||
else
|
||||
{
|
||||
#if COCOS2D_VERSION >= 0x00040000
|
||||
setMVPMatrixUniform();
|
||||
#endif
|
||||
|
||||
#if CC_USE_CULLING
|
||||
// Don't calculate the culling if the transform was not updated
|
||||
auto visitingCamera = Camera::getVisitingCamera();
|
||||
auto defaultCamera = Camera::getDefaultCamera();
|
||||
if (visitingCamera == nullptr) {
|
||||
_insideBounds = true;
|
||||
}
|
||||
else if (visitingCamera == defaultCamera) {
|
||||
_insideBounds = ((flags & FLAGS_TRANSFORM_DIRTY) || visitingCamera->isViewProjectionUpdated()) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX: this always return true since
|
||||
_insideBounds = renderer->checkVisibility(transform, _contentSize);
|
||||
}
|
||||
|
||||
if(_insideBounds)
|
||||
#endif
|
||||
{
|
||||
_trianglesCommand.init(_globalZOrder,
|
||||
_texture,
|
||||
#if COCOS2D_VERSION < 0x00040000
|
||||
getGLProgramState(),
|
||||
#endif
|
||||
_blendFunc,
|
||||
_fillTriangles,
|
||||
transform,
|
||||
flags);
|
||||
|
||||
renderer->addCommand(&_trianglesCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,66 @@
|
|||
#ifndef __FUISPRITE_H__
|
||||
#define __FUISPRITE_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class FUISprite : public cocos2d::Sprite
|
||||
{
|
||||
public:
|
||||
FUISprite();
|
||||
virtual ~FUISprite();
|
||||
|
||||
CREATE_FUNC(FUISprite);
|
||||
|
||||
void clearContent();
|
||||
void setScale9Grid(cocos2d::Rect* value);
|
||||
void setGrayed(bool value);
|
||||
|
||||
FillMethod getFillMethod() const { return _fillMethod; }
|
||||
void setFillMethod(FillMethod value);
|
||||
|
||||
FillOrigin getFillOrigin() const { return _fillOrigin; }
|
||||
void setFillOrigin(FillOrigin value);
|
||||
|
||||
bool isFillClockwise() const { return _fillClockwise; }
|
||||
void setFillClockwise(bool value);
|
||||
|
||||
float getFillAmount() const { return _fillAmount; }
|
||||
void setFillAmount(float value);
|
||||
|
||||
bool isScaleByTile() const { return _scaleByTile; }
|
||||
void setScaleByTile(bool value);
|
||||
|
||||
virtual void setContentSize(const cocos2d::Size& size) override;
|
||||
|
||||
protected:
|
||||
virtual void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) override;
|
||||
|
||||
cocos2d::Tex2F textureCoordFromAlphaPoint(cocos2d::Vec2 alpha);
|
||||
cocos2d::Vec3 vertexFromAlphaPoint(cocos2d::Vec2 alpha);
|
||||
void updateBar(void);
|
||||
void updateRadial(void);
|
||||
virtual void updateColor(void) override;
|
||||
cocos2d::Vec2 boundaryTexCoord(char index);
|
||||
|
||||
void setupFill();
|
||||
|
||||
private:
|
||||
FillMethod _fillMethod;
|
||||
FillOrigin _fillOrigin;
|
||||
float _fillAmount;
|
||||
bool _fillClockwise;
|
||||
bool _scaleByTile;
|
||||
int _vertexDataCount;
|
||||
cocos2d::TrianglesCommand::Triangles _fillTriangles;
|
||||
cocos2d::V3F_C4B_T2F *_vertexData;
|
||||
unsigned short *_vertexIndex;
|
||||
|
||||
static cocos2d::Texture2D* _empty;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,59 @@
|
|||
#include "TextFormat.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
USING_NS_CC;
|
||||
|
||||
TextFormat::TextFormat() :
|
||||
fontSize(12),
|
||||
color(Color3B::BLACK),
|
||||
bold(false),
|
||||
italics(false),
|
||||
underline(false),
|
||||
lineSpacing(3),
|
||||
letterSpacing(0),
|
||||
align(TextHAlignment::LEFT),
|
||||
verticalAlign(TextVAlignment::TOP),
|
||||
effect(0),
|
||||
outlineSize(1),
|
||||
shadowBlurRadius(0),
|
||||
_hasColor(false)
|
||||
{
|
||||
}
|
||||
|
||||
TextFormat::TextFormat(const TextFormat & other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
TextFormat & TextFormat::operator=(const TextFormat & other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
face = other.face;
|
||||
fontSize = other.fontSize;
|
||||
color = other.color;
|
||||
bold = other.bold;
|
||||
italics = other.italics;
|
||||
underline = other.underline;
|
||||
lineSpacing = other.lineSpacing;
|
||||
letterSpacing = other.letterSpacing;
|
||||
align = other.align;
|
||||
verticalAlign = other.verticalAlign;
|
||||
effect = other.effect;
|
||||
outlineColor = other.outlineColor;
|
||||
outlineSize = other.outlineSize;
|
||||
shadowColor = other.shadowColor;
|
||||
shadowOffset = other.shadowOffset;
|
||||
shadowBlurRadius = other.shadowBlurRadius;
|
||||
glowColor = other.glowColor;
|
||||
_hasColor = other._hasColor;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void TextFormat::setFormat(const TextFormat & format)
|
||||
{
|
||||
*this = format;
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef __TEXTFORMAT_H__
|
||||
#define __TEXTFORMAT_H__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "FairyGUIMacros.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class TextFormat
|
||||
{
|
||||
public:
|
||||
TextFormat();
|
||||
TextFormat(const TextFormat & other);
|
||||
TextFormat &operator =(const TextFormat & other);
|
||||
|
||||
void setFormat(const TextFormat& format);
|
||||
void enableEffect(int effectFlag) { effect |= effectFlag; }
|
||||
void disableEffect(int effectFlag) { effect &= ~effectFlag; }
|
||||
bool hasEffect(int effectFlag) const { return (effect & effectFlag) != 0; }
|
||||
|
||||
static const int OUTLINE = 1;
|
||||
static const int SHADOW = 2;
|
||||
static const int GLOW = 4;
|
||||
|
||||
std::string face;
|
||||
float fontSize;
|
||||
cocos2d::Color3B color;
|
||||
bool bold;
|
||||
bool italics;
|
||||
bool underline;
|
||||
int lineSpacing;
|
||||
int letterSpacing;
|
||||
cocos2d::TextHAlignment align;
|
||||
cocos2d::TextVAlignment verticalAlign;
|
||||
|
||||
int effect;
|
||||
cocos2d::Color3B outlineColor;
|
||||
int outlineSize;
|
||||
cocos2d::Color3B shadowColor;
|
||||
cocos2d::Size shadowOffset;
|
||||
int shadowBlurRadius;
|
||||
cocos2d::Color3B glowColor;
|
||||
|
||||
//internal use
|
||||
bool _hasColor;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#include "EventContext.h"
|
||||
#include "GObject.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
EventContext::EventContext() :
|
||||
_sender(nullptr),
|
||||
_data(nullptr),
|
||||
_inputEvent(nullptr),
|
||||
_isStopped(false),
|
||||
_defaultPrevented(false),
|
||||
_touchCapture(0),
|
||||
_type(0)
|
||||
{
|
||||
}
|
||||
|
||||
EventContext::~EventContext()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
NS_FGUI_END
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef __EVENTCONTEXT_H__
|
||||
#define __EVENTCONTEXT_H__
|
||||
|
||||
#include "FairyGUIMacros.h"
|
||||
#include "cocos2d.h"
|
||||
#include "InputEvent.h"
|
||||
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
class GObject;
|
||||
class InputProcessor;
|
||||
|
||||
class EventContext
|
||||
{
|
||||
public:
|
||||
EventContext();
|
||||
~EventContext();
|
||||
|
||||
int getType() const { return _type; }
|
||||
cocos2d::Ref* getSender() const { return _sender; }
|
||||
InputEvent* getInput() const { return _inputEvent; }
|
||||
void stopPropagation() { _isStopped = true; }
|
||||
void preventDefault() { _defaultPrevented = true; }
|
||||
bool isDefaultPrevented() { return _defaultPrevented; }
|
||||
void captureTouch() { _touchCapture = 1; }
|
||||
void uncaptureTouch() { _touchCapture = 2; }
|
||||
|
||||
const cocos2d::Value& getDataValue() const { return _dataValue; }
|
||||
void* getData() const { return _data; }
|
||||
|
||||
private:
|
||||
cocos2d::Ref* _sender;
|
||||
InputEvent* _inputEvent;
|
||||
cocos2d::Value _dataValue;
|
||||
void* _data;
|
||||
bool _isStopped;
|
||||
bool _defaultPrevented;
|
||||
int _touchCapture;
|
||||
int _type;
|
||||
|
||||
friend class UIEventDispatcher;
|
||||
};
|
||||
|
||||
NS_FGUI_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,58 @@
|
|||
#include "HitTest.h"
|
||||
#include "GComponent.h"
|
||||
#include "utils/ByteBuffer.h"
|
||||
|
||||
USING_NS_CC;
|
||||
NS_FGUI_BEGIN
|
||||
|
||||
PixelHitTestData::PixelHitTestData() :
|
||||
pixels(nullptr),
|
||||
pixelsLength(0),
|
||||
pixelWidth(0),
|
||||
scale(1)
|
||||
{
|
||||
}
|
||||
|
||||
PixelHitTestData::~PixelHitTestData()
|
||||
{
|
||||
CC_SAFE_DELETE(pixels);
|
||||
}
|
||||
|
||||
void PixelHitTestData::load(ByteBuffer* buffer)
|
||||
{
|
||||
buffer->skip(4);
|
||||
pixelWidth = buffer->readInt();
|
||||
scale = 1.0f / buffer->readByte();
|
||||
pixelsLength = buffer->readInt();
|
||||
pixels = new unsigned char[pixelsLength];
|
||||
for (size_t i = 0; i < pixelsLength; i++)
|
||||
pixels[i] = buffer->readByte();
|
||||
}
|
||||
|
||||
PixelHitTest::PixelHitTest(PixelHitTestData * data, int offsetX, int offsetY) :
|
||||
offsetX(offsetX),
|
||||
offsetY(offsetY),
|
||||
scaleX(1),
|
||||
scaleY(1),
|
||||
_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
bool PixelHitTest::hitTest(GComponent * obj, const cocos2d::Vec2 & localPoint)
|
||||
{
|
||||
int x = floor((localPoint.x / scaleX - offsetX) * _data->scale);
|
||||
int y = floor(((obj->getHeight() - localPoint.y) / scaleY - offsetY) * _data->scale);
|
||||
if (x < 0 || y < 0 || x >= _data->pixelWidth)
|
||||
return false;
|
||||
|
||||
ssize_t pos = y * _data->pixelWidth + x;
|
||||
ssize_t pos2 = pos / 8;
|
||||
ssize_t pos3 = pos % 8;
|
||||
|
||||
if (pos2 >= 0 && pos2 < (ssize_t)_data->pixelsLength)
|
||||
return ((_data->pixels[pos2] >> pos3) & 0x1) > 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_FGUI_END
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue