How to represent Box2D joints Back-story: I'm using blender as a level editor for a game I'm making, this means I write an addon in Python to export the relevant data in my format, and manipulate the blender interface to add options I need. Fixtures and Bodies (basically shapes) are easy to represent with 2D meshes, and I use Properties to add my specific options. Whenever I can, I exploit existing blender options (like the rigid body stuff) instead of adding my own. I am no avid blender user otherwise, so I guess that makes me a noob vs all everyday users.

[TL;DR: just read from here...]

What blender object resembles/represents Box2D Joints the best? And if none is perfect, what can I start with and how do I modify it to suit my needs?

I need it to have:


Two "object properties" (references to other existing objects) which will represent which two bodies to connect. In Box2D these are called BodyA and BodyB.
Two "point/vector" properties. These would represent what specific points on the two bodies to link together. Box2D name: AnchorA and AnchorB


What would also be nice:


Have it visualize the joint between the two anchor points, if it draws a line or something that'd be great.
Really nice if it actually restricted the objects to, say, a certain distance away from each other when I move them.


[...to here]

Then, I'm sure I could add more specific properties like joint type, break strength, etc. myself through Python Property registration.

Note: I am a programmer; I'm not afraid to code.

Oh, and before you mention it: I have seen "rigid body constraints", but among other things they don't satisfy condition 2. I've also found them generally messy and hard to understand (if the constraint is already applied to a body, what does it need two parent properties for?) I'm assuming a lot of this is because they are focused towards 3D not 2D, but am open for suggestions if someone still sees an opportunity there.
Storing the data in collection property:

import bpy

# specify the data structure - each item will be group of properties:
class Box2DJoint(bpy.types.PropertyGroup):
    # name = bpy.props.StringProperty()
    body_a = bpy.props.StringProperty()    # reference object name
    body_b = bpy.props.StringProperty()    # reference object name
    anchor_a = bpy.props.FloatVectorProperty()
    anchor_b = bpy.props.FloatVectorProperty()

# store them under scene:
bpy.utils.register_module(__name__)
bpy.types.Scene.box_2d_joints = bpy.props.CollectionProperty(type=Box2DJoint)

# populate like so:
new_joint = bpy.context.scene.box_2d_joints.add()
new_joint.name = "silly_box_joint"
new_joint.body_a = 'Some_object_name'
# ...etc.

# remove with index:
id = bpy.context.scene.box_2d_joints.find("silly_box_joint")
bpy.context.scene.box_2d_joints.remove(id)


The advantage of the data storage like this is you can also display it in UI lists which is nice: Populate a list with custom property dictionary data

If the user renames objects in blender or deletes them, the references must be adjusted: Execute a python function whenever the user interacts with the program. This offers the most flexibility, the code can catch almost anything. The handicap is that the frame change handler runs all the time.

Other approach would be to give objects some random hash which is stored with object name and searched for when the object is not found. Here is how to set it up for objects:

import bpy
import string
import random

def random_id(length = 12):
    return "".join([random.choice(string.ascii_uppercase) for i in range(length)])

bpy.types.Object.hash = bpy.props.StringProperty()
bpy.context.object.hash = random_id()


To check if object name exists:

if bpy.data.objects.get("FooBar") is not None:
    # do something with bpy.data.objects['FooBar']
else:
    # deal with it
    # look through all objects for hash and if found update name reference
    # if hash not found object is deleted or a ninja


Use bgl module to display such custom objects in view-port: Draw points on screen with bgl? (python)

The drawing code runs inside modal operator and has access to bpy.context, you can draw points, lines, triangles etc. in 3d float coords (init with 'POST_VIEW' tag) or in 2d pixel coords (init with 'POST_PIXEL'). BGL Wrapper Reference. The BLF module can be used to draw text. There are python templates in text editor for this.

Keeping this simple is good because drawing with python is not very fast. Too many draw-calls and Blender view-port fps will suffer.