SocketService

February 7, 2026 · View on GitHub

Overview

SocketService is one of the more ancient of the services, tracing its roots back to when the main purpose of MPFB was to interact with a running MakeHuman instance. It has little use beyond that purpose.

SocketService handles asynchronous communication with a separate MakeHuman socket server. It manages JSON and binary remote calls for retrieving mesh data, material information, skeleton data, and proxy asset information from a running MakeHuman instance.

Unlike most MPFB services which are static classes, SocketService is instantiated as a module-level singleton. This is because it maintains connection state (host, port) and a result cache across multiple calls.

The service uses Python's asyncio library for non-blocking network I/O. It supports two types of remote calls: JSON calls for structured data (mesh metadata, material info, skeleton definitions) and binary calls for large numeric data (vertex positions, face indices, weights). Binary transfers are significantly more efficient for bulk geometry data.

The socket protocol is defined by MakeHuman's socket server API. Each call sends a function name and optional parameters as JSON, and receives either a JSON response or raw binary data depending on the function. See JsonCall for details on the call format.

SocketService caches results for certain calls (like directory paths) to avoid repeated network round-trips for static information.

Source

src/mpfb/services/socketservice.py

Dependencies

DependencyUsage
LogServiceLogging via LogService.get_logger("services.socketservice")
JsonCallJSON-serializable function call model

Connection Defaults

SettingDefaultDescription
Host127.0.0.1Localhost by default
Port12345MakeHuman's default socket port

Public API

Connection Configuration

set_host(host)

Set the host address for socket connections.

ArgumentTypeDefaultDescription
hoststrThe hostname or IP address

Returns: None


set_port(port)

Set the port number for socket connections.

ArgumentTypeDefaultDescription
portintThe port number

Returns: None


Directory Information

get_user_dir()

Get the MakeHuman user directory path.

Returns: str — The user data directory path as reported by MakeHuman.

Results are cached after the first call.


get_sys_dir()

Get the MakeHuman system directory path.

Returns: str — The system data directory path as reported by MakeHuman.

Results are cached after the first call.


Body Mesh Data

get_body_mesh_info()

Get metadata about the body mesh.

Returns: dict — Mesh metadata including vertex count, face count, and other properties.


get_body_vertices()

Get body vertex positions as binary data.

Returns: bytearray — Raw binary data containing vertex coordinates.

The data is packed as 32-bit floats in x, y, z order for each vertex.


get_body_faces()

Get body face indices as binary data.

Returns: bytearray — Raw binary data containing face vertex indices.


get_body_texture_coords()

Get body texture coordinates as binary data.

Returns: bytearray — Raw binary data containing UV coordinates.


get_body_uv_mapping()

Get body UV face mappings as binary data.

Returns: bytearray — Raw binary data mapping faces to UV coordinates.


Body Material Data

get_body_material_info()

Get material information for the body mesh.

Returns: dict — Material properties including texture paths, colors, and shader settings.


Skeleton Data

get_skeleton()

Get the skeleton definition.

Returns: dict — Complete skeleton data including bone hierarchy, positions, and constraints.


Body Weight Data

get_body_weight_info()

Get metadata about body vertex weights.

Returns: dict — Weight metadata including bone names and weight counts.


get_body_weight_vertices()

Get the list of weighted vertices as binary data.

Returns: bytearray — Raw binary data containing vertex indices that have weights.


get_body_weights()

Get body vertex weights as binary data.

Returns: bytearray — Raw binary data containing weight values for each vertex-bone pair.


Proxy (Asset) Data

All proxy methods require a UUID parameter identifying the specific proxy asset.

get_proxies_info()

Get information about all loaded proxy assets.

Returns: dict — Dictionary of proxy metadata keyed by UUID.


get_proxy_vertices(uuid)

Get proxy vertex positions as binary data.

ArgumentTypeDefaultDescription
uuidstrThe proxy's unique identifier

Returns: bytearray — Raw binary vertex data.


get_proxy_faces(uuid)

Get proxy face indices as binary data.

ArgumentTypeDefaultDescription
uuidstrThe proxy's unique identifier

Returns: bytearray — Raw binary face data.


get_proxy_texture_coords(uuid)

Get proxy texture coordinates as binary data.

ArgumentTypeDefaultDescription
uuidstrThe proxy's unique identifier

Returns: bytearray — Raw binary UV data.


get_proxy_uv_mapping(uuid)

Get proxy UV face mappings as binary data.

ArgumentTypeDefaultDescription
uuidstrThe proxy's unique identifier

Returns: bytearray — Raw binary UV mapping data.


get_proxy_weight_info(uuid)

Get metadata about proxy vertex weights.

ArgumentTypeDefaultDescription
uuidstrThe proxy's unique identifier

Returns: dict — Weight metadata for the proxy.


get_proxy_weight_vertices(uuid)

Get the list of weighted proxy vertices as binary data.

ArgumentTypeDefaultDescription
uuidstrThe proxy's unique identifier

Returns: bytearray — Raw binary vertex index data.


get_proxy_weights(uuid)

Get proxy vertex weights as binary data.

ArgumentTypeDefaultDescription
uuidstrThe proxy's unique identifier

Returns: bytearray — Raw binary weight data.


get_proxy_material_info(uuid)

Get material information for a proxy.

ArgumentTypeDefaultDescription
uuidstrThe proxy's unique identifier

Returns: dict — Material properties for the proxy.


Examples

Basic Connection Setup

from mpfb.services.socketservice import SocketService

# Configure connection (if not using defaults)
SocketService.set_host("127.0.0.1")
SocketService.set_port(12345)

# Get directory information
user_dir = SocketService.get_user_dir()
sys_dir = SocketService.get_sys_dir()
print(f"MakeHuman user dir: {user_dir}")
print(f"MakeHuman system dir: {sys_dir}")

Fetching Body Mesh Data

from mpfb.services.socketservice import SocketService
import struct

# Get mesh metadata
mesh_info = SocketService.get_body_mesh_info()
print(f"Vertex count: {mesh_info.get('numVertices')}")
print(f"Face count: {mesh_info.get('numFaces')}")

# Get vertex data as binary
vertex_data = SocketService.get_body_vertices()

# Parse binary data (3 floats per vertex)
num_floats = len(vertex_data) // 4
coords = struct.unpack(f'{num_floats}f', vertex_data)

# Reshape into vertices
vertices = []
for i in range(0, len(coords), 3):
    vertices.append((coords[i], coords[i+1], coords[i+2]))

print(f"Parsed {len(vertices)} vertices")

Fetching Skeleton Data

from mpfb.services.socketservice import SocketService

# Get skeleton definition
skeleton = SocketService.get_skeleton()

# skeleton contains bone hierarchy and transforms
for bone_name, bone_data in skeleton.get('bones', {}).items():
    head = bone_data.get('head')
    tail = bone_data.get('tail')
    print(f"Bone '{bone_name}': head={head}, tail={tail}")

Working with Proxies (Clothes, Hair, etc.)

from mpfb.services.socketservice import SocketService

# Get all loaded proxies
proxies_info = SocketService.get_proxies_info()

for uuid, proxy_data in proxies_info.items():
    proxy_name = proxy_data.get('name', 'Unknown')
    proxy_type = proxy_data.get('type', 'Unknown')
    print(f"Proxy: {proxy_name} ({proxy_type}) - UUID: {uuid}")

    # Get this proxy's vertices
    vertices = SocketService.get_proxy_vertices(uuid)
    print(f"  Vertex data size: {len(vertices)} bytes")

    # Get material info
    material = SocketService.get_proxy_material_info(uuid)
    print(f"  Material: {material.get('name', 'default')}")

Fetching Weight Data

from mpfb.services.socketservice import SocketService
import struct

# Get weight metadata
weight_info = SocketService.get_body_weight_info()
bone_names = weight_info.get('bones', [])
print(f"Bones with weights: {bone_names}")

# Get the actual weights
weight_vertices = SocketService.get_body_weight_vertices()
weights = SocketService.get_body_weights()

# Parse and process weight data...

Complete Import Workflow

from mpfb.services.socketservice import SocketService
from mpfb.services.meshservice import MeshService
import struct

def import_from_makehuman():
    """Import the current MakeHuman character."""

    # Get mesh info
    mesh_info = SocketService.get_body_mesh_info()

    # Get vertex positions
    vert_data = SocketService.get_body_vertices()
    num_verts = len(vert_data) // 12  # 3 floats * 4 bytes
    vert_coords = struct.unpack(f'{num_verts * 3}f', vert_data)

    vertices = []
    for i in range(0, len(vert_coords), 3):
        vertices.append((
            vert_coords[i],
            vert_coords[i + 1],
            vert_coords[i + 2]
        ))

    # Get face data
    face_data = SocketService.get_body_faces()
    # Parse face data...

    # Create the mesh object
    mesh_obj = MeshService.create_mesh_object(
        vertices, [], faces,  # faces parsed from face_data
        name="ImportedHuman"
    )

    # Get and apply skeleton
    skeleton = SocketService.get_skeleton()
    # Create armature from skeleton data...

    # Get and apply materials
    material_info = SocketService.get_body_material_info()
    # Create materials...

    # Import proxies
    proxies = SocketService.get_proxies_info()
    for uuid in proxies:
        # Import each proxy...
        pass

    return mesh_obj

Error Handling

from mpfb.services.socketservice import SocketService

def safe_fetch():
    """Fetch with error handling."""
    try:
        mesh_info = SocketService.get_body_mesh_info()
        return mesh_info
    except ConnectionRefusedError:
        print("Could not connect to MakeHuman. Is it running with socket enabled?")
        return None
    except asyncio.TimeoutError:
        print("Connection timed out")
        return None
    except Exception as e:
        print(f"Unexpected error: {e}")
        return None

result = safe_fetch()
if result:
    print("Successfully fetched mesh info")