1
\$\begingroup\$

Many guides used userData. But with the source of Box2d I have, I don't see the SetUserData functions in the code as I see them in the guides.

After understanding it, I realized that these manuals were outdated, and now there is no such function and userData should be set in a different way. After digging through the Box2d files for three days, I realized that I could not cope alone.

I found out that it is possible to edit the b2FixtureDef structure to add my new data there. But I don't understand how to do this correctly, because just adding a line to the structure of the program crashes.

This is what I want to do:

class MyContactListener : public b2ContactListener
{
    void BeginContact(b2Contact* contact) 
    {
        //check if fixture A was the foot sensor
        std::string fixtureUserData = contact->GetFixtureA()->getmy();
        if ((int)fixtureUserData == 3)
            fixturesUnderfoot.insert(contact->GetFixtureB());//A is foot so B is ground
        //check if fixture B was the foot sensor
        fixtureUserData = contact->GetFixtureB()->GetUserData();
        if ((int)fixtureUserData == 3)
            fixturesUnderfoot.insert(contact->GetFixtureA());//B is foot so A is ground
    }

    void EndContact(b2Contact* contact) 
    {
        //check if fixture A was the foot sensor
        void* fixtureUserData = contact->GetFixtureA()->GetUserData();
        if ((int)fixtureUserData == 3)
            fixturesUnderfoot.erase(contact->GetFixtureB());//A is foot so B is ground
        //check if fixture B was the foot sensor
        fixtureUserData = contact->GetFixtureB()->GetUserData();
        if ((int)fixtureUserData == 3)
            fixturesUnderfoot.erase(contact->GetFixtureA());//B is foot so A is ground
    }
};

previously, it was possible, as I understood, to create a body and write:

body.setUserData = smth;
body.getUserData();

but this is not possible because the method returns a structure:

b2BodyUserData& b2Body::GetUserData()
{
    return m_userData;
}

struct b2BodyUserData
{
    b2BodyUserData()
    {
        pointer = 0;
    }

    /// For legacy compatibility
    uintptr_t pointer;
};

next to the structure definition, it is written "You can define this to inject whatever data you want in b2Fixture".

When I did something like this, the program is crashing:

struct B2_API b2FixtureUserData
{
    b2FixtureUserData()
    {
        pointer = 0;
        objectType = "";
    }
    std::string objectType;
    /// For legacy compatibility
    uintptr_t pointer;
};
\$\endgroup\$
6
  • \$\begingroup\$ Hmm, b2Fixture does not have a getmy function, shouldn't it be GetUserData? Also, how do you set this user data? \$\endgroup\$
    – Vaillancourt
    Sep 24, 2021 at 15:52
  • \$\begingroup\$ i set it like : b2FixtureDef boxFDef; boxFDef.userData.objectType = "box"; and then the program crashes with this code -1073741819. \$\endgroup\$
    – slverwolf
    Sep 24, 2021 at 16:02
  • \$\begingroup\$ @Vaillancourt, I didn't finish it once and forgot it. I apologize. reading data should look like this, right? std::string fixtureUserData = contact->GetFixtureA()->GetUserData().objectType; where objectType its my new data; \$\endgroup\$
    – slverwolf
    Sep 24, 2021 at 16:07
  • \$\begingroup\$ Before I spend too much time on this, I just want to make sure you've read this part of the official documentation. \$\endgroup\$
    – Vaillancourt
    Sep 24, 2021 at 17:00
  • \$\begingroup\$ @Vaillancourt, I spent three days searching for this information in other parts of this manual. Thank u so much \$\endgroup\$
    – slverwolf
    Sep 24, 2021 at 17:36

1 Answer 1

2
\$\begingroup\$

It seems that box2d recently changed the way they manage userData. They went from storing void pointers to storing an actual object. So it may explain why you see tutorials around that "do no work" with a more recent version of Box2d.

This part of the official documentation illustrates how this should be done now, however it lacks an important information, IMHO.

The user data is an object that you control and you need hold alive for the whole life of the box2d object.

Since the userData deals with "opaque pointers" (Box2d does not know what those are nor what they're for, only you do), and the example uses raw pointers, Box2d will not clean the memory associated to those once the Box2d objects are destroyed, you need to take care of cleaning those.

A way to do it is to wrap those into smart pointers.

So somewhere in your code you need to create your own class:

struct MyFixtureUserDataType
{
    int mObjectType {};
    b2Fixture* mOwningFixture {};
}

Then when you create your fixtures, you also create the data:

// Store this somewhere in your game managing classes
std::vector<std::unique_ptr<MyFixtureUserDataType>> mFixtureUserData;

// Create your userData object
auto myUserData = std::make_unique<MyFixtureUserDataType>();
myUserData->mObjectType = 3; // whatever this fixture is about

// create the def
b2FixtureDef fixtureDef;
fixtureDef.userData.pointer = reinterpret_cast<uintptr_t>(myUserData.get());

// create your fixture
myUserData->mOwningFixture = body->CreateFixture( fixtureDef );

// Now you store you data
mFixtureUserData.emplace_back( std::move(myUserData) );
myUserData = nullptr;

Then when you destroy the fixture, you can remove the associated instance of MyFixtureUserDataType.

b2Fixture* myFixtureToDestroy = ....;

body->DestroyFixture(myFixtureToDestroy);

for ( int i = 0; i < mFixtureUserData.size(); ++i )
{
  if( mFixtureUserData[i]->mOwningFixture == myFixtureToDestroy )
  {
    std::swap( mFixtureUserData[i], mFixtureUserData[mFixtureUserData.size() - 1] );
    mFixtureUserData.pop_back();
    break;
  }
}

This is a trivial example; mFixtureUserData could also be an std::map<[fixture pointer], std::unique_ptr<MyFixtureUserDataType>> to allow faster search.

But you get the gist of it, the idea is to keep track of your user data in some way an make sure you clean it when you destroy the associated Box2d objects.

I've created a small complete-ish example here on coliru of this workflow.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .