cocos3.x 编写C++控件在lua上面调用(一)
2014-08-08 14:30
330 查看
由于之前的代码出现了许多不足的地方,所以花了一段时间来重写这个控件的代码。
编写cocos的控件,那么首先设计的应该是C++的类
.h文件
#ifndef __ACCORDION__
#define __ACCORDION__
#include "cocos2d.h"
#include "cocos-ext.h"
#include "GUI/CCControlExtension/CCControlButton.h"
#include "CCLuaEngine.h"
#include "CCLuaStack.h"
USING_NS_CC;
USING_NS_CC_EXT;
typedef ControlButton FRAccordionItemTitle;
typedef Node FRAccordionItemContent;
/** Create mode模式
*/
typedef enum
{
kFRAccordionModeCreateAll,
kFRAccordionModeCreateDynamic,
} FRAccordionCreateMode;
/** The item pair to show in FRAccordion
*/
class FRAccordionItem : public
Node
{
/** The item title & content
*/
CC_SYNTHESIZE_READONLY(FRAccordionItemTitle*,
_title, Title);
CC_SYNTHESIZE_READONLY(FRAccordionItemContent*,
_content, Content);
CC_SYNTHESIZE(int,
_tag, Tag);
public:
FRAccordionItem();
~FRAccordionItem();
static
FRAccordionItem* create(FRAccordionItemTitle* title,
FRAccordionItemContent* content);
protected:
bool init(FRAccordionItemTitle* title,
FRAccordionItemContent* content);
};
#define kTagNothingSelected 0
/** FRAccordion
*/
class FRAccordion : public
Layer
{
public:
FRAccordion();
~FRAccordion();
/** Lua listener for title tapped event
*/
void registerChangeScriptFunc(int onChangeCallback);
void unregisterChangeScriptFunc();
/** Mode FRAccordionCreateDynamic: set the displaying content
*/
void setCurrentContent(FRAccordionItemContent* content);
/** For unition of Lua usage
*/
void setCurrentIndex(unsigned
int index);
unsigned int getCurrentIndex();
/** If using mode FRAccordionModeCreateAll, items must contain children of type FRAccordionItem*
* Else, if using mode FRAccordionModeCreateDynamic, items must contain children of tyoe FRAccordionTitle*
*/
static FRAccordion* create(const
Size& dimension, Vector<Node*>& items,
int mode, float gap =
0.f);
bool init(const
Size& dimension, Vector<Node*>& items,
int mode, float gap =
0.f);
/**
鼠标点击时候的相应函数
*/
void touchDown(cocos2d::Ref *senderz,
Control::EventType controlEvent);
/**
按钮移动的函数
*/
void moveAction();
/**
lua的相应函数
*/
void luaCallback();
private:
unsigned int currentIndex;//用来保存当前点击的按钮的index
float _gap;//用来保存按钮直接的距离
Vector<FRAccordionItem*> vecItems;//用来保存FRAccordionitems
Vector<FRAccordionItemTitle*> vecTitles;//用来保存FRAccordionTitle
int modeNum;//用来保存mode模式
int luaHandle;//用来保存lua的函数id
};
#endif
以上为类的头文件,最后一个luaHandle可能会有些疑惑的地方。其实就是lua和C++相互调用得问题了,在cocos里面有了一个封装C++类来得到一个.hpp .cpp得tolua工具,使得lua上面可以调用到C++类上面得函数。而如果C++想要调用lua上面得函数得话,就没有相应得工具,所以上面就需要一个registerChangeScriptFunc(int)得函数来得到lua函数得id。上篇文章中有个链接地址是说这个得,不明白得话可以去看一下。简单得说来,就是因为C++和lua之间只能通过栈来交互。
.c
4000
pp文件
//
// Accordion.cpp
// Raccordion
//
// Created by awally on 14-8-7.
//
//
#include "Accordion.h"
#include "lua.h"
FRAccordionItem::FRAccordionItem()
:_title(nullptr)
,_content(nullptr)
,_tag(0){
}
FRAccordionItem::~FRAccordionItem(){
this->_title->release();
this->_content->release();
}
FRAccordionItem* FRAccordionItem::create(FRAccordionItemTitle *title,
FRAccordionItemContent *content){
FRAccordionItem* accordionItem =
new FRAccordionItem();
if (accordionItem && accordionItem->init(title, content)) {
accordionItem->autorelease();
}else{
CC_SAFE_DELETE(accordionItem);
}
return accordionItem;
}
bool FRAccordionItem::init(FRAccordionItemTitle *title,
FRAccordionItemContent *content){
if (!Node::create()) {
return false;
}
this->_title = title;
this->_title->retain();
this->_content = content;
this->_content->retain();
this->_tag =
_tag + 1;
return true;
}
FRAccordion::FRAccordion()
:currentIndex(0)
,_gap(0.0)
,modeNum(0)
,luaHandle(0){
}
FRAccordion::~FRAccordion(){
}
void FRAccordion::registerChangeScriptFunc(int onChangeCallback){
this->luaHandle = onChangeCallback;
}
void FRAccordion::unregisterChangeScriptFunc(){
this->luaHandle =
0;
lua_State* pl = lua_open();
lua_pop(pl, 1);
lua_close(pl);
}
void FRAccordion::setCurrentContent(FRAccordionItemContent *content){
content->setPosition(150,
450-58*this->currentIndex);
if(this->getChildByTag(2)){
this->removeChildByTag(2);
}
this->addChild(content,
0, 2);
}
void FRAccordion::setCurrentIndex(unsigned
int index){
this->currentIndex = index;
}
unsigned int
FRAccordion::getCurrentIndex(){
return
this->currentIndex;
}
FRAccordion* FRAccordion::create(const
cocos2d::Size &dimension,
Vector<cocos2d::Node *> &items,
int mode, float gap){
FRAccordion* accordion =
new FRAccordion();
if (accordion && accordion->init(dimension, items, mode, gap)) {
accordion->autorelease();
}else{
CC_SAFE_DELETE(accordion);
}
return accordion;
}
bool FRAccordion::init(const
cocos2d::Size &dimension,
Vector<cocos2d::Node *> &items,
int mode, float gap){
this->setContentSize(dimension);
this->_gap = gap;
if (mode == 1) {
this->modeNum =
1;
for (int num=0; num<items.size(); num=num+2) {
Scale9Sprite* bgSprite =
Scale9Sprite::create("button.png");
ControlButton* controlBtn =
ControlButton::create(items.at(num), bgSprite);
controlBtn->setMargins(50,
12);
controlBtn->setPosition(150,
500-58*num/2);
this->addChild(controlBtn);
FRAccordionItem* item =
FRAccordionItem::create(controlBtn, items.at(num+1));
this->vecItems.pushBack(item);
controlBtn->addTargetWithActionForControlEvents(this,
cccontrol_selector(FRAccordion::touchDown),
Control::EventType::TOUCH_DOWN);
}
return true;
}else if (mode ==
2){
this->modeNum =
2;
for (int num=0; num<items.size(); num++) {
Scale9Sprite* bgSprite =
Scale9Sprite::create("button.png");
ControlButton* controlBtn =
ControlButton::create(items.at(num), bgSprite);
controlBtn->setMargins(50,
12);
controlBtn->setPosition(150,
500-58*num);
this->vecTitles.pushBack(controlBtn);
this->addChild(controlBtn);
controlBtn->addTargetWithActionForControlEvents(this,
cccontrol_selector(FRAccordion::touchDown),
Control::EventType::TOUCH_DOWN);
}
return true;
}else{
printf("enter wrong mode");
return false;
}
}
void FRAccordion::touchDown(cocos2d::Ref *senderz,
Control::EventType controlEvent){
if (this->getChildByTag(1)) {
this->removeChildByTag(1);
}
if (this->modeNum ==
1) {
for (int num=0; num<this->vecItems.size(); num++) {
if (this->vecItems.at(num)->getTitle()==senderz) {
this->setCurrentIndex(num);
this->vecItems.at(num)->getContent()->setPosition(150,
450-num*58);
this->addChild(this->vecItems.at(num)->getContent(),
0, 1);
this->moveAction();
}
}
}else{
for (int num=0; num<this->vecTitles.size(); num++) {
if (this->vecTitles.at(num)==senderz) {
this->setCurrentIndex(num);
this->moveAction();
}
}
}
}
void FRAccordion::moveAction(){
if (this->modeNum==1) {
for (int num=0; num<this->vecItems.size(); num++) {
if (num>this->currentIndex) {
MoveTo* action =
MoveTo::create(0.1,
Vec2(150, 500-142-58*num));
vecItems.at(num)->getTitle()->runAction(action);
}else{
MoveTo* action =
MoveTo::create(0.1,
Vec2(150, 500-58*num));
vecItems.at(num)->getTitle()->runAction(action);
}
}
}else{
for (int num=0; num<this->vecTitles.size(); num++) {
if (num>this->currentIndex) {
MoveTo* action =
MoveTo::create(0.1,
Vec2(150, 500-142-58*num));
vecTitles.at(num)->runAction(action);
}else{
MoveTo* action =
MoveTo::create(0.1,
Vec2(150, 500-58*num));
vecTitles.at(num)->runAction(action);
}
}
//这里调用lua回调函数
this->luaCallback();
}
}
void FRAccordion::luaCallback(){
if (luaHandle>0) {
LuaStack* stack =
LuaEngine::getInstance()->getLuaStack();
stack->executeFunctionByHandler(luaHandle,
0);
stack->clean();
}
}
整体流程比较简单,主要是C++和lua交互得情况。luaCallback()正是C++通过lua的函数id(luaHandle)来调用编写在lua上面的函数。下一篇是介绍C++类怎样绑定,使得lua可以调用的。
编写cocos的控件,那么首先设计的应该是C++的类
.h文件
#ifndef __ACCORDION__
#define __ACCORDION__
#include "cocos2d.h"
#include "cocos-ext.h"
#include "GUI/CCControlExtension/CCControlButton.h"
#include "CCLuaEngine.h"
#include "CCLuaStack.h"
USING_NS_CC;
USING_NS_CC_EXT;
typedef ControlButton FRAccordionItemTitle;
typedef Node FRAccordionItemContent;
/** Create mode模式
*/
typedef enum
{
kFRAccordionModeCreateAll,
kFRAccordionModeCreateDynamic,
} FRAccordionCreateMode;
/** The item pair to show in FRAccordion
*/
class FRAccordionItem : public
Node
{
/** The item title & content
*/
CC_SYNTHESIZE_READONLY(FRAccordionItemTitle*,
_title, Title);
CC_SYNTHESIZE_READONLY(FRAccordionItemContent*,
_content, Content);
CC_SYNTHESIZE(int,
_tag, Tag);
public:
FRAccordionItem();
~FRAccordionItem();
static
FRAccordionItem* create(FRAccordionItemTitle* title,
FRAccordionItemContent* content);
protected:
bool init(FRAccordionItemTitle* title,
FRAccordionItemContent* content);
};
#define kTagNothingSelected 0
/** FRAccordion
*/
class FRAccordion : public
Layer
{
public:
FRAccordion();
~FRAccordion();
/** Lua listener for title tapped event
*/
void registerChangeScriptFunc(int onChangeCallback);
void unregisterChangeScriptFunc();
/** Mode FRAccordionCreateDynamic: set the displaying content
*/
void setCurrentContent(FRAccordionItemContent* content);
/** For unition of Lua usage
*/
void setCurrentIndex(unsigned
int index);
unsigned int getCurrentIndex();
/** If using mode FRAccordionModeCreateAll, items must contain children of type FRAccordionItem*
* Else, if using mode FRAccordionModeCreateDynamic, items must contain children of tyoe FRAccordionTitle*
*/
static FRAccordion* create(const
Size& dimension, Vector<Node*>& items,
int mode, float gap =
0.f);
bool init(const
Size& dimension, Vector<Node*>& items,
int mode, float gap =
0.f);
/**
鼠标点击时候的相应函数
*/
void touchDown(cocos2d::Ref *senderz,
Control::EventType controlEvent);
/**
按钮移动的函数
*/
void moveAction();
/**
lua的相应函数
*/
void luaCallback();
private:
unsigned int currentIndex;//用来保存当前点击的按钮的index
float _gap;//用来保存按钮直接的距离
Vector<FRAccordionItem*> vecItems;//用来保存FRAccordionitems
Vector<FRAccordionItemTitle*> vecTitles;//用来保存FRAccordionTitle
int modeNum;//用来保存mode模式
int luaHandle;//用来保存lua的函数id
};
#endif
以上为类的头文件,最后一个luaHandle可能会有些疑惑的地方。其实就是lua和C++相互调用得问题了,在cocos里面有了一个封装C++类来得到一个.hpp .cpp得tolua工具,使得lua上面可以调用到C++类上面得函数。而如果C++想要调用lua上面得函数得话,就没有相应得工具,所以上面就需要一个registerChangeScriptFunc(int)得函数来得到lua函数得id。上篇文章中有个链接地址是说这个得,不明白得话可以去看一下。简单得说来,就是因为C++和lua之间只能通过栈来交互。
.c
4000
pp文件
//
// Accordion.cpp
// Raccordion
//
// Created by awally on 14-8-7.
//
//
#include "Accordion.h"
#include "lua.h"
FRAccordionItem::FRAccordionItem()
:_title(nullptr)
,_content(nullptr)
,_tag(0){
}
FRAccordionItem::~FRAccordionItem(){
this->_title->release();
this->_content->release();
}
FRAccordionItem* FRAccordionItem::create(FRAccordionItemTitle *title,
FRAccordionItemContent *content){
FRAccordionItem* accordionItem =
new FRAccordionItem();
if (accordionItem && accordionItem->init(title, content)) {
accordionItem->autorelease();
}else{
CC_SAFE_DELETE(accordionItem);
}
return accordionItem;
}
bool FRAccordionItem::init(FRAccordionItemTitle *title,
FRAccordionItemContent *content){
if (!Node::create()) {
return false;
}
this->_title = title;
this->_title->retain();
this->_content = content;
this->_content->retain();
this->_tag =
_tag + 1;
return true;
}
FRAccordion::FRAccordion()
:currentIndex(0)
,_gap(0.0)
,modeNum(0)
,luaHandle(0){
}
FRAccordion::~FRAccordion(){
}
void FRAccordion::registerChangeScriptFunc(int onChangeCallback){
this->luaHandle = onChangeCallback;
}
void FRAccordion::unregisterChangeScriptFunc(){
this->luaHandle =
0;
lua_State* pl = lua_open();
lua_pop(pl, 1);
lua_close(pl);
}
void FRAccordion::setCurrentContent(FRAccordionItemContent *content){
content->setPosition(150,
450-58*this->currentIndex);
if(this->getChildByTag(2)){
this->removeChildByTag(2);
}
this->addChild(content,
0, 2);
}
void FRAccordion::setCurrentIndex(unsigned
int index){
this->currentIndex = index;
}
unsigned int
FRAccordion::getCurrentIndex(){
return
this->currentIndex;
}
FRAccordion* FRAccordion::create(const
cocos2d::Size &dimension,
Vector<cocos2d::Node *> &items,
int mode, float gap){
FRAccordion* accordion =
new FRAccordion();
if (accordion && accordion->init(dimension, items, mode, gap)) {
accordion->autorelease();
}else{
CC_SAFE_DELETE(accordion);
}
return accordion;
}
bool FRAccordion::init(const
cocos2d::Size &dimension,
Vector<cocos2d::Node *> &items,
int mode, float gap){
this->setContentSize(dimension);
this->_gap = gap;
if (mode == 1) {
this->modeNum =
1;
for (int num=0; num<items.size(); num=num+2) {
Scale9Sprite* bgSprite =
Scale9Sprite::create("button.png");
ControlButton* controlBtn =
ControlButton::create(items.at(num), bgSprite);
controlBtn->setMargins(50,
12);
controlBtn->setPosition(150,
500-58*num/2);
this->addChild(controlBtn);
FRAccordionItem* item =
FRAccordionItem::create(controlBtn, items.at(num+1));
this->vecItems.pushBack(item);
controlBtn->addTargetWithActionForControlEvents(this,
cccontrol_selector(FRAccordion::touchDown),
Control::EventType::TOUCH_DOWN);
}
return true;
}else if (mode ==
2){
this->modeNum =
2;
for (int num=0; num<items.size(); num++) {
Scale9Sprite* bgSprite =
Scale9Sprite::create("button.png");
ControlButton* controlBtn =
ControlButton::create(items.at(num), bgSprite);
controlBtn->setMargins(50,
12);
controlBtn->setPosition(150,
500-58*num);
this->vecTitles.pushBack(controlBtn);
this->addChild(controlBtn);
controlBtn->addTargetWithActionForControlEvents(this,
cccontrol_selector(FRAccordion::touchDown),
Control::EventType::TOUCH_DOWN);
}
return true;
}else{
printf("enter wrong mode");
return false;
}
}
void FRAccordion::touchDown(cocos2d::Ref *senderz,
Control::EventType controlEvent){
if (this->getChildByTag(1)) {
this->removeChildByTag(1);
}
if (this->modeNum ==
1) {
for (int num=0; num<this->vecItems.size(); num++) {
if (this->vecItems.at(num)->getTitle()==senderz) {
this->setCurrentIndex(num);
this->vecItems.at(num)->getContent()->setPosition(150,
450-num*58);
this->addChild(this->vecItems.at(num)->getContent(),
0, 1);
this->moveAction();
}
}
}else{
for (int num=0; num<this->vecTitles.size(); num++) {
if (this->vecTitles.at(num)==senderz) {
this->setCurrentIndex(num);
this->moveAction();
}
}
}
}
void FRAccordion::moveAction(){
if (this->modeNum==1) {
for (int num=0; num<this->vecItems.size(); num++) {
if (num>this->currentIndex) {
MoveTo* action =
MoveTo::create(0.1,
Vec2(150, 500-142-58*num));
vecItems.at(num)->getTitle()->runAction(action);
}else{
MoveTo* action =
MoveTo::create(0.1,
Vec2(150, 500-58*num));
vecItems.at(num)->getTitle()->runAction(action);
}
}
}else{
for (int num=0; num<this->vecTitles.size(); num++) {
if (num>this->currentIndex) {
MoveTo* action =
MoveTo::create(0.1,
Vec2(150, 500-142-58*num));
vecTitles.at(num)->runAction(action);
}else{
MoveTo* action =
MoveTo::create(0.1,
Vec2(150, 500-58*num));
vecTitles.at(num)->runAction(action);
}
}
//这里调用lua回调函数
this->luaCallback();
}
}
void FRAccordion::luaCallback(){
if (luaHandle>0) {
LuaStack* stack =
LuaEngine::getInstance()->getLuaStack();
stack->executeFunctionByHandler(luaHandle,
0);
stack->clean();
}
}
整体流程比较简单,主要是C++和lua交互得情况。luaCallback()正是C++通过lua的函数id(luaHandle)来调用编写在lua上面的函数。下一篇是介绍C++类怎样绑定,使得lua可以调用的。
相关文章推荐
- cocos3.x 编写C++控件在lua上面调用(二)
- cocos3.x 编写C++控件在lua上面调用
- cocos2d-x 3.x中lua调用原理1--从基本的c++与lua互相调用开始
- C#调用C++编写的OCX控件
- 如何使用cocos的自动绑定工具实现lua调用c++的类
- C++编写ActiveX ocx控件在网页中调用失败问题
- C#调用C++编写的COM DLL
- C#调用C++编写的COM DLL封装库的问题解决方案
- 编写的activeX 控件如何被IE调用?
- VC6.0配置LUA编译环境及LUA调用C++函数的简单示例
- 不调用C++/C的字符串库函数,请编写函数 strcpy
- C/C++中调用LUA函数
- [编程实例]Dev-C++编写动态调用dll杀进程的程序
- C#调用C++编写的COM DLL
- com调用的几种方法 及 C#调用C++编写的的COM DLL
- com调用的几种方法 及 C#调用C++编写的的COM DLL收藏
- C#调用C++编写的COM DLL
- C++默认编写并调用的函数
- c#.net下成功调用c++编写的标准dll
- 用托管C++编写自定义Web组合控件