How to add platform and close ModalDialog in script?

I’m working on a script, but I’m running into two problems.


The first problem:
I can get all the platforms in the current preference via studio.project.workspace.platforms, and I can make changes to them, but I can’t add a platform.

I think maybe I need to create a (ManagedObject:Platform) object, but I don’t seem to be able to find any information on how to do that from the documentation.


Second question:
I have used studio.ui.showModalDialog() to create a window that has a number of buttons. I want this dialog to be closed when the function is executed after pressing the buttons. But again there is no information about it.

I tried using studio.window.triggerAction(studio.window.actions.WindowClose), but it directly closes the FMOD Studio window, not the dialog.

For the first problem, the bare minimum you need to do to avoid any project issues is the following:

var platform = studio.project.create("Platform");
studio.project.workspace.platforms.push(platform);
platform.encodingSettings.platform = platform;

This will create a new platform with the associated encoding setting, though you’ll want to populate the Platform and associated EncodingSetting with the settings you want. Note that you can create any ManagedObject you need in Studio using studio.project.create().

For the second problem, can I get you to share a code snippet containing any code you’re using for the modal dialog and buttons?

1 Like

Thanks for the code, it’s very useful. However, I have encountered other problems.
(1)
Actually my intention is to add a platform according to a preset (with defaults for its name and subpaths), as if I had chosen Add Platform in the context menu. So is it possible to add a new preset to this context menu?
export

(2)
Also, while it is possible to add platforms using studio.project.workspace.platforms.push(platform);, it doesn’t seem to be possible to remove platforms from it? According to the console, this seems to require ManagedRelationship.remove, but I haven’t found the correct way to use that either.

(3)
Regarding the dialog, my code looks like this:

function createButton(buttonContent, execute) {
    return {
        widgetType: studio.ui.widgetType.PushButton,
        text: buttonContent,
        sizePolicy: {
            horizontalPolicy: studio.ui.sizePolicy.Expanding,
            verticalPolicy: studio.ui.sizePolicy.Expanding
        },
        onClicked: execute
    };
}

var window_Export = {
    windowTitle: "My Dialog Tool",
    windowWidth: 200,
    windowHeight: 200,
    widgetType: studio.ui.widgetType.Layout,
    layout: studio.ui.layoutType.HBoxLayout,
    spacing: 10,
    items: [
        createButton("Do Something", function () {
            // I will export some data here.
            exportDatas("MyData.data");
            // And I want to close the dialog after that.
            // Maybe something like this:
            studio.ui.closeDialog();
        }),
    ]
};

studio.menu.addMenuItem({
    name: "My Dialog Tool",
    execute: function () {
        studio.ui.showModalDialog(window_Export);
    }
});

Unfortunately, it isn’t. The options in the “Add Platform” menu are based on a hard-coded list of platform hardware. Creating your own Platform in a script that you duplicate as needed as a preset may be an option though.

The simplest way to do this is to delete the Platform outright with studio.project.deleteObject(). If you want to remove the Platform without deletion, you can use studio.project.workspace.relationships.platforms.remove(), but the removed Platform will trigger a project validation issue since it’s now a dangling object.

To close the dialog from a widget, in this case the studio.ui.widgetType.PushButton, instead of calling studio.ui.closeDialog(); you’ll want to call this.closeDialog();.

1 Like

We coincided on this point, and I wrote this piece of code to accomplish this.
First, add all the platforms that are in the context menu to the list.
Then execute the following code in the console:

function generateDefaultPlatformCode() {
    var code = [];
    code.push("var platform = studio.project.create(\"Platform\");");
    code.push("platform.encodingSettings.platform = platform;");
    code.push("switch (platform.name) {");

    for (var i = 0; i < studio.project.workspace.platforms.length; i++) {
        var p = studio.project.workspace.platforms[i];
        code.push("    case \"{0}\":".format(p.name));
        if (p.name == "Custom") {
            code.push("    default:");
        }
        code.push("        platform.name = \"{0}\";".format(p.name));
        code.push("        platform.subDirectory = \"{0}\";".format(p.subDirectory));
        code.push("        platform.hardwareType = {0};".format(p.hardwareType));
        code.push("        platform.speakerFormat = {0};".format(p.speakerFormat));
        code.push("        platform.encodingSettings.encodingFormat = {0};".format(p.encodingSettings.encodingFormat));
        code.push("        platform.encodingSettings.quality = {0};".format(p.encodingSettings.quality));
        code.push("        platform.encodingSettings.sampleRateMode = {0};".format(p.encodingSettings.sampleRateMode));
        code.push("        platform.encodingSettings.sampleRate = {0};".format(p.encodingSettings.sampleRate));
        code.push("        platform.encodingSettings.loadingMode = {0};".format(p.encodingSettings.loadingMode));
        code.push("        break;");
    }

    code.push("}");

    console.log(code.join("\n"));
}

Then you can get the output like this:

var platform = studio.project.create("Platform");
platform.encodingSettings.platform = platform;
switch (platform.name) {
    case "Desktop":
        platform.name = "Desktop";
        platform.subDirectory = "Desktop";
        platform.hardwareType = 0;
        platform.speakerFormat = 5;
        platform.encodingSettings.encodingFormat = 3;
        platform.encodingSettings.quality = 37;
        platform.encodingSettings.sampleRateMode = 0;
        platform.encodingSettings.sampleRate = 48000;
        platform.encodingSettings.loadingMode = 0;
        break;
    case "Mobile":
        platform.name = "Mobile";
        platform.subDirectory = "Mobile";
        platform.hardwareType = 1;
        platform.speakerFormat = 1;
        platform.encodingSettings.encodingFormat = 1;
        platform.encodingSettings.quality = 80;
        platform.encodingSettings.sampleRateMode = 0;
        platform.encodingSettings.sampleRate = 24000;
        platform.encodingSettings.loadingMode = 0;
        break;
    case "Xbox One":
        platform.name = "Xbox One";
        platform.subDirectory = "XboxOne";
        platform.hardwareType = 3;
        platform.speakerFormat = 6;
        platform.encodingSettings.encodingFormat = 2;
        platform.encodingSettings.quality = 60;
        platform.encodingSettings.sampleRateMode = 0;
        platform.encodingSettings.sampleRate = 48000;
        platform.encodingSettings.loadingMode = 0;
        break;
    case "Xbox Series X|S":
        platform.name = "Xbox Series X|S";
        platform.subDirectory = "Scarlett";
        platform.hardwareType = 11;
        platform.speakerFormat = 6;
        platform.encodingSettings.encodingFormat = 5;
        platform.encodingSettings.quality = 63;
        platform.encodingSettings.sampleRateMode = 0;
        platform.encodingSettings.sampleRate = 48000;
        platform.encodingSettings.loadingMode = 0;
        break;
    case "PlayStation 4":
        platform.name = "PlayStation 4";
        platform.subDirectory = "PS4";
        platform.hardwareType = 5;
        platform.speakerFormat = 6;
        platform.encodingSettings.encodingFormat = 4;
        platform.encodingSettings.quality = 50;
        platform.encodingSettings.sampleRateMode = 0;
        platform.encodingSettings.sampleRate = 48000;
        platform.encodingSettings.loadingMode = 0;
        break;
    case "PlayStation 5":
        platform.name = "PlayStation 5";
        platform.subDirectory = "PS5";
        platform.hardwareType = 10;
        platform.speakerFormat = 6;
        platform.encodingSettings.encodingFormat = 5;
        platform.encodingSettings.quality = 63;
        platform.encodingSettings.sampleRateMode = 0;
        platform.encodingSettings.sampleRate = 48000;
        platform.encodingSettings.loadingMode = 0;
        break;
    case "Switch":
        platform.name = "Switch";
        platform.subDirectory = "Switch";
        platform.hardwareType = 8;
        platform.speakerFormat = 5;
        platform.encodingSettings.encodingFormat = 1;
        platform.encodingSettings.quality = 80;
        platform.encodingSettings.sampleRateMode = 0;
        platform.encodingSettings.sampleRate = 48000;
        platform.encodingSettings.loadingMode = 0;
        break;
    case "Custom":
    default:
        platform.name = "Custom";
        platform.subDirectory = "Custom";
        platform.hardwareType = 9;
        platform.speakerFormat = 6;
        platform.encodingSettings.encodingFormat = 3;
        platform.encodingSettings.quality = 37;
        platform.encodingSettings.sampleRateMode = 0;
        platform.encodingSettings.sampleRate = 48000;
        platform.encodingSettings.loadingMode = 0;
        break;
}

In the end, they just need to be wrapped a little bit to get the platform instances created based on the preset parameters:

function createDefaultPresetPlatform(defaultPresetName) {
    if (defaultPresetName == null || defaultPresetName == "") {
        return;
    }
    var platform = studio.project.create("Platform");
    platform.encodingSettings.platform = platform;
    switch (defaultPresetName) {
        case "Desktop":
            platform.name = "Desktop";
            platform.subDirectory = "Desktop";
            platform.hardwareType = 0;
            platform.speakerFormat = 5;
            platform.encodingSettings.encodingFormat = 3;
            platform.encodingSettings.quality = 37;
            platform.encodingSettings.sampleRateMode = 0;
            platform.encodingSettings.sampleRate = 48000;
            platform.encodingSettings.loadingMode = 0;
            break;
        case "Mobile":
            platform.name = "Mobile";
            platform.subDirectory = "Mobile";
            platform.hardwareType = 1;
            platform.speakerFormat = 1;
            platform.encodingSettings.encodingFormat = 1;
            platform.encodingSettings.quality = 80;
            platform.encodingSettings.sampleRateMode = 0;
            platform.encodingSettings.sampleRate = 24000;
            platform.encodingSettings.loadingMode = 0;
            break;
        case "Xbox One":
            platform.name = "Xbox One";
            platform.subDirectory = "XboxOne";
            platform.hardwareType = 3;
            platform.speakerFormat = 6;
            platform.encodingSettings.encodingFormat = 2;
            platform.encodingSettings.quality = 60;
            platform.encodingSettings.sampleRateMode = 0;
            platform.encodingSettings.sampleRate = 48000;
            platform.encodingSettings.loadingMode = 0;
            break;
        case "Xbox Series X|S":
            platform.name = "Xbox Series X|S";
            platform.subDirectory = "Scarlett";
            platform.hardwareType = 11;
            platform.speakerFormat = 6;
            platform.encodingSettings.encodingFormat = 5;
            platform.encodingSettings.quality = 63;
            platform.encodingSettings.sampleRateMode = 0;
            platform.encodingSettings.sampleRate = 48000;
            platform.encodingSettings.loadingMode = 0;
            break;
        case "PlayStation 4":
            platform.name = "PlayStation 4";
            platform.subDirectory = "PS4";
            platform.hardwareType = 5;
            platform.speakerFormat = 6;
            platform.encodingSettings.encodingFormat = 4;
            platform.encodingSettings.quality = 50;
            platform.encodingSettings.sampleRateMode = 0;
            platform.encodingSettings.sampleRate = 48000;
            platform.encodingSettings.loadingMode = 0;
            break;
        case "PlayStation 5":
            platform.name = "PlayStation 5";
            platform.subDirectory = "PS5";
            platform.hardwareType = 10;
            platform.speakerFormat = 6;
            platform.encodingSettings.encodingFormat = 5;
            platform.encodingSettings.quality = 63;
            platform.encodingSettings.sampleRateMode = 0;
            platform.encodingSettings.sampleRate = 48000;
            platform.encodingSettings.loadingMode = 0;
            break;
        case "Switch":
            platform.name = "Switch";
            platform.subDirectory = "Switch";
            platform.hardwareType = 8;
            platform.speakerFormat = 5;
            platform.encodingSettings.encodingFormat = 1;
            platform.encodingSettings.quality = 80;
            platform.encodingSettings.sampleRateMode = 0;
            platform.encodingSettings.sampleRate = 48000;
            platform.encodingSettings.loadingMode = 0;
            break;
        case "Custom":
        default:
            platform.name = "Custom";
            platform.subDirectory = "Custom";
            platform.hardwareType = 9;
            platform.speakerFormat = 6;
            platform.encodingSettings.encodingFormat = 3;
            platform.encodingSettings.quality = 37;
            platform.encodingSettings.sampleRateMode = 0;
            platform.encodingSettings.sampleRate = 48000;
            platform.encodingSettings.loadingMode = 0;
            break;
    }

    return platform;
}
1 Like

After testing, both functions work well, thanks for your professional answer.


I would also like to ask what is the meaning of the line of code platform.encodingSettings.platform = platform;?

If I don’t execute it, I see a “Validation Required” warning in FMOD Studio. And it doesn’t appear in the Build list. But after executing it everything works fine.

Does this mean that object to object relationships need to be established in both directions?

1 Like

It depends on the object(s) in question, but in this case, yes. Creating a Platform also creates an associated EncodingSetting, but doesn’t connect the EncodingSetting to the Platform since EncodingSetting can also be associated with Assets, Asset Folders, etc. That line of code explicitly establishes the relationship and also automatically adds the EncodingSetting to Platform.associatedSettings, which resolves the validation issue.

1 Like

Thank you very much for providing simple and clear answers!

1 Like