Site Tools


tool:wem-mapper

Table of Contents

WEM Mapper

Authors: WindShadowRuins

Preamble

Put this inside python script inside your soundbank folder where the soundbank.json is located and it will generate a csv file that will tell you what Play_c and Play_s ID plays Wem files.

Script

#!/usr/bin/env python3
import json
import os
import csv

def extract_wem_mappings(json_file):
    print("Starting extraction...")

    # Load JSON data
    try:
        with open(json_file, 'r', encoding='utf-8') as f:
            data = json.load(f)
    except json.JSONDecodeError as e:
        print(f"Error loading JSON: {e}")
        input("Press Enter to exit...")
        return

    # Extract all HIRC objects from all sections
    hirc_objects = []
    for section in data.get("sections", []):
        body = section.get("body", {})
        hirc = body.get("HIRC", {})
        objects = hirc.get("objects", [])
        hirc_objects.extend(objects)
    print(f"Extracted {len(hirc_objects)} HIRC objects.")

    # Build mapping from Sound objects:
    # Mapping: direct_parent_id -> list of WEM source_ids
    parent_to_wems = {}
    sound_count = 0
    for obj in hirc_objects:
        if not isinstance(obj, dict):
            continue
        sound = obj.get("body", {}).get("Sound", {})
        if not isinstance(sound, dict):
            continue
        bank_source = sound.get("bank_source_data", {})
        if bank_source.get("plugin") == "VORBIS":
            source_id = bank_source.get("media_information", {}).get("source_id")
            node_params = sound.get("node_base_params", {})
            direct_parent_id = node_params.get("direct_parent_id")
            if isinstance(source_id, int) and isinstance(direct_parent_id, int):
                parent_to_wems.setdefault(direct_parent_id, []).append(source_id)
                sound_count += 1
    print(f"Found {sound_count} WEM sound entries. Parent-to-WEM mapping has {len(parent_to_wems)} keys.")

    # Build mapping for Action objects:
    # Mapping: action object's id (Hash) -> external_id
    action_id_to_external = {}
    action_count = 0
    for obj in hirc_objects:
        if not isinstance(obj, dict):
            continue
        action = obj.get("body", {}).get("Action")
        if isinstance(action, dict):
            act_hash = obj.get("id", {}).get("Hash")
            external_id = action.get("external_id")
            if isinstance(act_hash, int) and isinstance(external_id, int):
                action_id_to_external[act_hash] = external_id
                action_count += 1
    print(f"Found {action_count} Action objects with external IDs.")

    # Extract play events (Play_c and Play_s) and determine their external_id.
    play_to_external = {}
    play_count = 0
    for obj in hirc_objects:
        if not isinstance(obj, dict):
            continue
        play_name = obj.get("id", {}).get("String")
        if play_name and (play_name.startswith("Play_c") or play_name.startswith("Play_s")):
            event = obj.get("body", {}).get("Event")
            if isinstance(event, dict):
                actions = event.get("actions", [])
                found_external = None
                for act in actions:
                    if isinstance(act, dict):
                        # If action is a dict, try to get external_id directly.
                        ext = act.get("external_id")
                        if isinstance(ext, int):
                            found_external = ext
                            break
                    elif isinstance(act, int):
                        # If action is an integer, use it as key in our Action mapping.
                        if act in action_id_to_external:
                            found_external = action_id_to_external[act]
                            break
                if found_external is not None:
                    play_to_external[play_name] = found_external
                    play_count += 1
    print(f"Found {play_count} play events with external IDs.")

    # Build the final mapping: for each play event, match its external_id with the Sound's direct_parent_id
    final_mappings = []
    for play, external_id in play_to_external.items():
        wem_ids = parent_to_wems.get(external_id, [])
        wem_str = ", ".join(map(str, wem_ids)) if wem_ids else "N/A"
        final_mappings.append((play, external_id, wem_str))
    print(f"Built final mapping for {len(final_mappings)} play events.")

    # Write the output to a CSV file
    output_file = "wem_mappings.csv"
    try:
        with open(output_file, "w", encoding="utf-8", newline="") as csvfile:
            writer = csv.writer(csvfile)
            writer.writerow(["Play Name", "External ID", "WEM Source IDs"])
            for row in final_mappings:
                writer.writerow(row)
        print(f"Extraction complete! Output saved to {output_file}")
    except Exception as e:
        print(f"Error writing to file: {e}")

    input("Press Enter to exit...")

if __name__ == "__main__":
    json_file = "soundbank.json"
    if os.path.exists(json_file):
        extract_wem_mappings(json_file)
    else:
        print(f"Error: {json_file} not found in the current directory.")
        input("Press Enter to exit...")
tool/wem-mapper.txt · Last modified: by admin