cocosbuilder的ccb文件對應的c++類可以用自動生成c++代碼的方式實現快速開發。不過作者寫的針對cocos2d-x2.1 + cocosbuilder3.0稍微有點問題,都是cocos2d-x的版本更新太快,修改太大的問題。新版的ccb類bind的方法參考點擊打開鏈接
需要把codeGen稍微改了下就OK了,代碼如下:
//
// CodeGen.h
// cocos2dCodeGen
//
// Created by user on 13-4-25.
// Copyright (c) 2013年 user. All rights reserved.
//
#ifndef __cocos2dCodeGen__CodeGen__
#define __cocos2dCodeGen__CodeGen__
#include <iostream>
#include "utility.h"
#include <vector>
class CodeGen
{
public:
std::string m_className; //要生成的類名
std::string m_baseClass; //生成類的父類
std::vector<TypeName> m_listAssignMember; //需要賦值的場景對象
std::vector<TypeName> m_listCutomProperty; //需要賦值的自定義變量
std::vector<std::string> m_listCContorlCallBack;//menu回調函數名
std::vector<std::string> m_listMenuCallBack; //control回調函數名
void GenerateHeaderFile()
{
GenerateClassDec();
GenerateInterfaceDec();
GenerateCallBackControlDec();
GenerateCallBackMenuDec();
GenerateAssignMemberDec();
GenerateCustomMemberDec();
GenerateLayerClassEnd();
GenerateNodeLeader();
GenerateEnd();
}
void GenerateCppFile()
{
GenerateCppHeader();
GenerateCallBackControl();
GenerateCallBackMenu();
GlueMenuCallBack();
GlueControlCallBack();
GlueAssignMember();
GlueCustomMember();
}
CodeGen(std::ostream& h,std::ostream& c);
private:
//header file
void GenerateClassDec();
void GenerateInterfaceDec();
void GenerateCallBackControlDec();
void GenerateCallBackMenuDec();
void GenerateAssignMemberDec();
void GenerateCustomMemberDec();
void GenerateLayerClassEnd();
void GenerateNodeLeader();
void GenerateEnd();
//cpp file
void GenerateCppHeader();
void GenerateCallBackControl();
void GenerateCallBackMenu();
void GlueMenuCallBack();
void GlueControlCallBack();
void GlueAssignMember();
void GlueCustomMember();
//void GeneateClass();
std::ostream& m_header;
std::ostream& m_cpp;
};
#endif /* defined(__cocos2dCodeGen__CodeGen__) */
對應的.mm文件:
//
// CodeGen.cpp
// cocos2dCodeGen
//
// Created by user on 13-4-25.
// Copyright (c) 2013年 user. All rights reserved.
//
#include "CodeGen.h"
#include <fstream>
#include <sstream>
#include <set>
using namespace std;
//cpp file
std::string m_cppHeader;
std::string m_callBackControl;
std::string m_callBackMenu;
std::string m_glueAssignMember;
std::string m_glueControlCallBack;
std::string m_glueMenuCallBack;
std::string m_glueCustomMember;
//header file
std::string m_classDec;
std::string m_interfaceDec;
std::string m_callBackControlDec;
std::string m_callBackMenuDec;
void string_replace( std::string &strBig, const std::string &strsrc, const std::string &strdst )
{
std::string::size_type pos = 0;
std::string::size_type srclen = strsrc.size();
std::string::size_type dstlen = strdst.size();
while( (pos=strBig.find(strsrc, pos)) != std::string::npos )
{
strBig.replace( pos, srclen, strdst );
pos += dstlen;
}
}
std::string ReadTemplateFromDic(const std::string& fileName,NSDictionary * templateCppCode)
{
return std::string(
[ [templateCppCode objectForKey: [NSString stringWithFormat:@"%s",fileName.c_str()]] UTF8String]
);
}
CodeGen::CodeGen(std::ostream& h,std::ostream& c)
:m_header(h),m_cpp(c)
{
//read header dec
//read
if (m_cppHeader == "") {
NSString *codeTemplatePath = [[NSBundle mainBundle] pathForResource:@"codeTemplateCpp" ofType:@"plist"];
NSDictionary * templateCppCode = [NSDictionary dictionaryWithContentsOfFile:codeTemplatePath];
m_classDec = ReadTemplateFromDic("ClassDec.txt",templateCppCode);
m_interfaceDec = ReadTemplateFromDic("InterfaceDec.txt",templateCppCode);
m_callBackControlDec = ReadTemplateFromDic("CallBackCControlDec.txt",templateCppCode);
m_callBackMenuDec = ReadTemplateFromDic("CallBackMenuDec.txt",templateCppCode);
m_glueMenuCallBack = ReadTemplateFromDic("GlueMenuCallBack.txt",templateCppCode);
m_glueCustomMember = ReadTemplateFromDic("GlueCustomMember.txt",templateCppCode);
m_cppHeader = ReadTemplateFromDic("CppHeader.txt",templateCppCode);
m_glueAssignMember = ReadTemplateFromDic("GlueAssignMember.txt",templateCppCode);
m_glueControlCallBack = ReadTemplateFromDic("GlueControlCallBack.txt",templateCppCode );
m_callBackControl = ReadTemplateFromDic("CallBackControl.txt",templateCppCode);
m_callBackMenu = ReadTemplateFromDic("CallBackMenu.txt",templateCppCode);
}
}
void CodeGen::GlueAssignMember()
{
m_cpp << "// glue assigned member here ;\n";
std::string glueBegin = m_glueAssignMember;
string_replace(glueBegin, "%class_name%", m_className);
m_cpp << glueBegin ;
for (const TypeName& item : m_listAssignMember)
{
m_cpp << "\tCCB_MEMBERVARIABLEASSIGNER_GLUE(this," << "\"" << item.name << "\"," << item.type << "*," << "this->" << item.name << ");\n";
}
m_cpp << "\treturn false;\n";
m_cpp << "}\n";
}
void CodeGen::GlueCustomMember()
{
m_cpp << "// glue custom member here ;\n";
std::string glueBegin = m_glueCustomMember;
string_replace(glueBegin, "%class_name%", m_className);
m_cpp << glueBegin ;
for (const TypeName& item : m_listCutomProperty)
{
m_cpp << "\t\tif (0 == strcmp(pMemberVariableName, \"" << item.name << "\")){\n";
m_cpp << "\t\t\t"<<item.name<< " = ";
if (item.type == "string" || item.type == "std::string")
{
m_cpp << "pCCBValue->getStringValue();\n";
}
else if(item.type == "int")
{
m_cpp << "pCCBValue->getIntValue();\n";
}
else if(item.type == "float")
{
m_cpp << "pCCBValue->getFloatValue();\n";
}
else if(item.type == "bool")
{
m_cpp << "pCCBValue->getBoolValue();\n";
}
else
{
m_cpp << "0;\n";
}
m_cpp << "\t\t\treturn true;\n";
m_cpp << "\t\t}\n";
}
m_cpp << "\t}\n";
m_cpp << "\treturn false;\n";
m_cpp << "}\n\n";
}
void CodeGen::GlueControlCallBack()
{
m_cpp << "// glue control button call back here ;\n";
std::string glueBegin = m_glueControlCallBack;
string_replace(glueBegin, "%class_name%", m_className);
m_cpp << glueBegin ;
for (const std::string& item : m_listCContorlCallBack)
{
m_cpp << "\tCCB_SELECTORRESOLVER_CCCONTROL_GLUE(this," << "\"" << item << "\"," << m_className << "::" << item << ");\n";
}
m_cpp << "\treturn false;\n";
m_cpp << "}\n\n";
}
void CodeGen::GlueMenuCallBack()
{
m_cpp << "// glue menu callback here ;\n";
std::string glueBegin = m_glueMenuCallBack;
string_replace(glueBegin, "%class_name%", m_className);
m_cpp << glueBegin ;
for (const std::string& item : m_listMenuCallBack)
{
m_cpp << "\tCCB_SELECTORRESOLVER_CCMENUITEM_GLUE(this," << "\"" << item << "\"," << m_className << "::" << item << ");\n";
}
m_cpp << "\treturn false;\n";
m_cpp << "}\n\n";
}
void CodeGen::GenerateCppHeader()
{
std::string cppHeader = m_cppHeader;
string_replace(cppHeader, "%class_name%", m_className);
m_cpp << cppHeader;
}
void CodeGen::GenerateCallBackControl()
{
m_cpp << "//control button call back here ;\n";
for(const std::string& fName : m_listCContorlCallBack)
{
std::string callBackImpli = m_callBackControl;
string_replace(callBackImpli, "%class_name%", m_className);
string_replace(callBackImpli, "%control_call%", fName);
m_cpp << callBackImpli ;
}
m_cpp << "// end control call back\n\n";
}
void CodeGen::GenerateCallBackMenu()
{
m_cpp << "// menu call back here ;\n";
for(const std::string& fName : m_listMenuCallBack)
{
std::string callBackImpli = m_callBackMenu;
string_replace(callBackImpli, "%class_name%", m_className);
string_replace(callBackImpli, "%menu_call%", fName);
m_cpp << callBackImpli;
}
m_cpp << "// end menu call back\n\n";
}
void CodeGen::GenerateClassDec()
{
std::string classDec = m_classDec;
string_replace(classDec, "%class_name%", m_className);
string_replace(classDec, "%base_class%", m_baseClass);
m_header<< classDec<<"\n";
//initialize member or custom member
for (const TypeName& item :m_listAssignMember) {
if (item.type == "string" || item.type == "std::string") {
continue;
}
m_header <<"\t," << item.name << "(0)\n";
}
for (const TypeName& item :m_listCutomProperty) {
if (item.type == "string" || item.type == "std::string") {
continue;
}
m_header <<"\t," << item.name << "(0)\n";
}
m_header << "{}\n";
//generate loader
if (m_baseClass == "CCNode") {
m_header << "CREATE_FUNC("<< m_className << ");\n\n";
}
else if(m_baseClass == "CCLayer")
{
m_header << "CREATE_FUNC("<< m_className << ");\n\n";
}
}
void CodeGen::GenerateInterfaceDec()
{
m_header << "\n//virtual function from base !\n";
m_header << m_interfaceDec;
}
void CodeGen::GenerateCallBackControlDec()
{
m_header << "\n //control call back function;\n";
m_header << "protected:" << std::endl;
for (auto iter = m_listCContorlCallBack.cbegin(); iter != m_listCContorlCallBack.cend(); ++iter) {
std::string call_control = m_callBackControlDec;
string_replace(call_control, "%control_call%", *iter);
m_header << call_control;
}
}
void CodeGen::GenerateCallBackMenuDec()
{
m_header << "\n // menu call back fuction \n";
m_header << "protected:" << std::endl;
for (auto iter = m_listMenuCallBack.cbegin(); iter != m_listMenuCallBack.cend(); ++iter) {
std::string call_menu = m_callBackMenuDec;
string_replace(call_menu, "%menu_call%", *iter);
m_header << call_menu;
}
}
void CodeGen::GenerateCustomMemberDec()
{
m_header << "\n //custom member list \n";
m_header << "protected:" << std::endl;
for (const TypeName& item :m_listCutomProperty) {
m_header << "\t"<< item.type << "\t\t" << item.name << ";\n";
}
}
const static std::set<std::string> cocos2dClass =
{
"CCNode",
"CCSprite",
"CCLayer",
"CCLayerColor",
"CCLayerGradient",
"CCMenu",
"CCLabelBMFont",
"CCLabelTTF",
"CCParticleSystem",
"CCParticleSystemQuad",
"CCParticleSystemPoint",
"CCMenuItemImage",
"CCBFile",
"CCScale9Sprite",
"CCControl",
"CCControlButton",
"CCScrollView",
};
const static std::set<std::string> extensionClass=
{
"CCBFile",
"CCScale9Sprite",
"CCControl",
"CCControlButton",
"CCScrollView",
};
void CodeGen::GenerateAssignMemberDec()
{
m_header << "\n //member will assigned form ccbi file\n";
m_header << "protected:" << std::endl;
for (const TypeName& item :m_listAssignMember) {
m_header << "\t";
if (cocos2dClass.find(item.type) != cocos2dClass.end()) {
m_header<<"cocos2d::";
}
if (extensionClass.find(item.type) != extensionClass.end()) {
m_header <<"extension::";
}
m_header<< item.type << "*\t\t" << item.name << ";\n";
}
}
void CodeGen::GenerateLayerClassEnd()
{
m_header << "};\n";
}
void CodeGen::GenerateNodeLeader()
{
std::string classHeader = "class %class_name%Loader: public cocos2d::extension::CCLayerLoader {";
string_replace(classHeader, "%class_name%", m_className);
m_header << classHeader << "\n";
m_header << "public:\n";
m_header << "\tvirtual bool init(){ return true; }\n";
std::string staticNewObjc = "\tCCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(%class_name%Loader, loader);";
std::string virtualRewriteObjc = "\tCCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD(%class_name%);";
string_replace(staticNewObjc, "%class_name%", m_className);
string_replace(virtualRewriteObjc, "%class_name%", m_className);
m_header << staticNewObjc << "\n";
m_header << virtualRewriteObjc << "\n";
m_header << "};";
}
void CodeGen::GenerateEnd()
{
m_header << "\n#endif\n";
}