Cocos2d-x V4.0 released

In the upgrade guide (https://docs.cocos2d-x.org/cocos2d-x/v4/en/upgradeGuide/) it says “V4 only works on those devices that support Metal for iOS/macOS platforms.”

Does it mean there’s no fallback to opengles for older devices?

I’m working on updating our project from v3 to v4 and need some help with the migration.
This project runs on iOS, android and mac.
Current setup for v3 is this:

Root folder for the project is myProject/ which was generated with cocos new command, inside there are different folders for each platform project like proj.android-studio/ and proj.ios_mac/ among others.
Right now myProject/ is a git repo and has cocos2d-x added as a submodule, this submodule is located in myProject/cocos2d/. The cocos2d submodule is our own repo forked from cocos2d repository on github.

I’m following the migration guide at https://docs.cocos2d-x.org/cocos2d-x/v4/en/upgradeGuide/migration.html
Our case being scenario 1, where we currently have a game running on v3.

My first step for migration was to fetch v4 from upstream and create our local branch for v4 and checkout it. No problems here.
Then the guide says to generate the different projects. I start with mac and iOS first so I generate both projects.

Here’s my first doubt, the guide says (using mac project as an example):

cd cocos2d-x
mkdir mac-build && cd mac-build
cmake .. -GXcode
open Cocos2d-x.xcodeproj

At first I thought I should create mac-build/ and ios-build/ inside myProject/. However cmake command didn’t work. So I created mac-build/ and ios-build/ in myProject/cocos2d/ and cmake command works fine.
Is this correct?

When I go to step 3 of migration guide it says, after generating cmake project "find the v4 engine project at cocos2d-x/build/engine/cocos/core/" and step 4 says to add the new v4 engine project to my game project. However I have two v4 engine projects now, one in mac-build/ and one in ios-build/
The only engine/cocos/core/ I can find are inside mac-build/ and ios-build/

I’m probably missing something obvious but I’m a bit lost since I have two different cmake generated projects now (ios and mac).

Do I have to create a new project for each platform my game runs on? Atleast for ios and mac I’m lost at which one would be the correct cocos2d_libs to add to my game project.

edit: from reading previous posts it seems I should create ios-build/ and mac-build/ inside myProject/ and not myProject/cocos2d/. However I still don’t understand how to work with both the mac and ios generated projects while migrating my v3 game.

Yes. You can use V3 if you want to use opengles.

It doesn’t matter where to create the build folder. You can follow step 3 to specify the build directory.

Yes. If you target a mac platform, then you should attach the project inside the mac-build/engine/cocos/core/. If you target an iOS platform, use project inside the ios-build/engine/cocos/core/ instead.

So I can’t have a single xcode project for both ios and mac as with v3? Right now, with v3, you can have a single project which targets mac and iOS.

I’d have to migrate my current project and have it either be ios or mac and then create a new project for the other platform?

@coulsonwang What about this fix? I see it has not been integrated.

=====
And one new thing. It seems there is memory leak. Take a look please at the

MeshIndexData::~MeshIndexData()
{
    CC_SAFE_RELEASE(_indexBuffer);
    _indexData.clear();
#if CC_ENABLE_CACHE_TEXTURE_DATA
    Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener);
#endif
} 

_indexBuffer reference count is equal 2 here, since it is retained at the

MeshIndexData::create(const std::string& id, MeshVertexData* vertexData, backend::Buffer* indexbuffer, const AABB& aabb)

But I think it should not be retained since indexBuffer is not ‘autoreleased’ in the place where it is created at the

static MeshVertexData* create(const MeshData& meshdata, backend::BufferUsage vert_use, backend::BufferUsage ind_use)

===========
Little desire if you wish.
Potentially it would be convenient to allow backend::Buffer::updateData(void* data, std::size_t size) to recreate backend dependent buffer if updated buffer size more than allocated. Now it only has assert about this.

Yes. CMake do not support configure multiple platform targets in a project. So it is a bit difference with V3.

It had merged now.

Yes, the indexBuffer needs to be ‘autoreleased’. Fixed in PR 20423.

As the updateData literal meaning, it just update datas. I think it’s better to resize the buffer somewhere outside.

Autorelease is useful when cocos2d library creates some object which user can forget to retain himself. For example look at the end of

MeshVertexData* MeshVertexData::create(const MeshData& meshdata)

There is изображение

But indexBuffer will be stored to the indexdata varriable in any case. Take a look please that indexdata is not autoreleased, because it is stored to the vertexdata->_indexs.
By the following logic there is no autorelease for the vertexdata->_vertexBuffer.

I believe that this is extra cpu cycles to do indexBuffer autoreleased, since it is added to the indexdata.

//===============================

It looks like I was wrong :upside_down_face: and indexdata is autoreleased.
indexBuffer is added to the indexdata from outside and it should be retained in this case.
I apologize, your fix is well!)

@coulsonwang Could you check please the following functions:

void CustomCommand::setVertexBuffer(backend::Buffer *vertexBuffer)
{
    if (_vertexBuffer == vertexBuffer)
        return;

    _vertexBuffer = vertexBuffer;
    CC_SAFE_RETAIN(_vertexBuffer);
}

void CustomCommand::setIndexBuffer(backend::Buffer *indexBuffer, IndexFormat format)
{
    if (_indexBuffer == indexBuffer && _indexFormat == format)
        return;

    _indexBuffer = indexBuffer;
    CC_SAFE_RETAIN(_indexBuffer);

    _indexFormat = format;
    _indexSize = computeIndexSize();
} 

Looks like there is needed CC_SAFE_RELEASE for _vertexBuffer and _indexBuffer.

@zhangxm When will next cocos v3.x releasing?

The _vertexBuffer and _indexBuffer will be released in the CustomCommand destructor.

CustomCommand::~CustomCommand()
{
    CC_SAFE_RELEASE(_vertexBuffer);
    CC_SAFE_RELEASE(_indexBuffer);
}

@coulsonwang They will be released in destructor when whole object deleting.

I need opportunity to increase Sprite3D::_meshVertexDatas[i]::_vertexBuffer and Sprite3D::_meshVertexDatas[i]::_indexs[j]::_indexBuffer in run time.
I wrote you that there is no interface for backend::Buffer class that allow to increase it. You answered:

I see only one approach to achieve this goal. Exchage Sprite3D::_meshVertexDatas[i]::_vertexBuffer and Sprite3D::_meshVertexDatas[i]::_indexs[j]::_indexBuffer through the outside addition Sprite3D interface with some new buffers with updated data’s.
But now I can’t properly remove the corresponding buffers, since they were caught by the MeshCommand while performing the following function:

It is called each frame, and according to the CustomCommand::setIndexBuffer/setVertexBuffer
, the older indexBuffer/vertexBuffer will cause memory leak, if they were changed.

Besides Take attention that CustomCommand::setIndexBuffer/setVertexBuffer are public interfaces in any case. They can be used in many other contexts.

@solan Yes, there is a memory leak issue, and it was fixed in PR 20440. Thanks for your work.

1 Like

I’m making this post incase anyone else is having trouble with this.

I’m currently creating a new project using v4 and setting up everything using cmake and learning as I go.
Project is created fine with cmake and compiles both for mac and iOS, however on iOS project I noticed only iPhone device comes checked by default.Screen Shot 2020-01-10 at 4.03.18 PM .

Obviously you just can’t check iPad from xcode… you have to somehow make cmake set this for you.
From cocos2d-x/README.md at v4 · cocos2d/cocos2d-x · GitHub it says:

Bundle Identifier, Version numbers and Device Support

All this information is held in the Info.plist file that is part of the app’s source files and is therefore not generated by cmake . Therefore you can update these values from the General page of the Xcode target and the values will be preserved the next time you regenerate the project from cmake :

However I could see Info.plist wasn’t being edited so after deleting and regenerating the project with cmake I was back to having only iPhone selected.
After trying cmake stuff with no luck I did some googling and found this:

From here I gathered

XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY “1,2”

was what I needed so I added the following line to my CMakeLists.txt:
set_xcode_property(${APP_NAME} TARGETED_DEVICE_FAMILY "1,2")

This works fine, regenerating the project has both iPhone and iPad selected.

1 Like

+1

I think I had a similar issue a while ago which caused issue on ipads
https://discuss.cocos2d-x.org/t/3-17-1-android-cmake-issue/45362/20?u=sleicreider

Why does the android studio project come generated? Shouldn’t we generate it using cmake as with the other platforms?

I’m looking around for info why this decision was made but found nothing :frowning:

Also, should we open it as a new project or use import project form android studio?
Screen Shot 2020-01-14 at 11.15.43 AM

@bolin Click the Open an existing Android Studio project and select the proj.android folder.

1 Like

What’s’ the correct/preferred workflow when using cmake and version control when working as a team?

For example: I create some new source files in xcode, add them to CMakeLists.txt and push the changes to a git repo. Someone else fetches the changes, merges and then has to regenerate the project. This has to be done each time someone adds new files to the project… it seems cumbersome. I’m sure there’s some way to automate part of the steps (regenerating project when CMakeLists.txt has changed for example).

Android project isn’t working for me :frowning:

This is after creating a new project with v4 and opening proj.android/ in Android Studio 3.1.3
Gradle project sync fails with error:

org.jetbrains.plugins.gradle.tooling.util.ModuleComponentIdentifierImpl.getModuleIdentifier()Lorg/gradle/api/artifacts/ModuleIdentifier;

I noticed in app/build.gradle that the line
import org.gradle.internal.os.OperatingSystem

Is giving error since gradle symbole can’t be resolved.