Skip to content

Commit e51aacb

Browse files
committed
add source exporters for FMOD, Unity and WWISE
1 parent 6dabe7d commit e51aacb

4 files changed

Lines changed: 248 additions & 1 deletion

File tree

‎Source/Heavy/FMODExporter.h‎

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
// Copyright (c) 2026 Timothy Schoen and Wasted Audio
3+
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
4+
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
5+
*/
6+
#pragma once
7+
8+
class FMODExporter final : public ExporterBase {
9+
public:
10+
FMODExporter(PluginEditor* editor, ExportingProgressView* exportingView)
11+
: ExporterBase(editor, exportingView)
12+
{
13+
}
14+
15+
void getState(DynamicObject::Ptr globalState) override
16+
{
17+
auto* state = new DynamicObject();
18+
state->setProperty("input_patch_value", getValue<String>(inputPatchValue));
19+
state->setProperty("project_name_value", getValue<String>(projectNameValue));
20+
state->setProperty("project_copyright_value", getValue<String>(projectCopyrightValue));
21+
globalState->setProperty("fmod", state);
22+
}
23+
24+
void setState(DynamicObject::Ptr globalState) override
25+
{
26+
auto const state = globalState->getProperty("fmod").getDynamicObject();
27+
if (!state)
28+
return;
29+
inputPatchValue = state->getProperty("input_patch_value");
30+
projectNameValue = state->getProperty("project_name_value");
31+
projectCopyrightValue = state->getProperty("project_copyright_value");
32+
}
33+
34+
bool performExport(String const& pdPatch, String const& outdir, String const& name, String const& copyright, StringArray const& searchPaths) override
35+
{
36+
exportingView->showState(ExportingProgressView::Exporting);
37+
38+
auto const heavyPath = pathToString(heavyExecutable);
39+
40+
StringArray args = { heavyPath.quoted(), pdPatch.quoted(), "-o", outdir.quoted() };
41+
42+
args.add("-n" + name);
43+
44+
if (copyright.isNotEmpty()) {
45+
args.add("--copyright");
46+
args.add(copyright.quoted());
47+
}
48+
49+
args.add("-v");
50+
args.add("-gfmod");
51+
52+
args.add("-p");
53+
for (auto& path : searchPaths) {
54+
args.add(path);
55+
}
56+
57+
if (shouldQuit)
58+
return true;
59+
60+
auto const command = args.joinIntoString(" ");
61+
startShellScript(command);
62+
63+
waitForProcessToFinish(-1);
64+
exportingView->flushConsole();
65+
66+
if (shouldQuit)
67+
return true;
68+
69+
auto const outputFile = File(outdir);
70+
outputFile.getChildFile("ir").deleteRecursively();
71+
outputFile.getChildFile("hv").deleteRecursively();
72+
73+
// Delay to get correct exit code
74+
Time::waitForMillisecondCounter(Time::getMillisecondCounter() + 300);
75+
76+
return getExitCode();
77+
}
78+
};

‎Source/Heavy/HeavyExportDialog.cpp‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
#include "OWLExporter.h"
2525
#include "PdExporter.h"
2626
#include "WASMExporter.h"
27+
#include "FMODExporter.h"
28+
#include "UnityExporter.h"
29+
#include "WWISEExporter.h"
30+
2731

2832
class ExporterSettingsPanel final : public Component
2933
, private ListBoxModel {
@@ -43,7 +47,10 @@ class ExporterSettingsPanel final : public Component
4347
"DPF Audio Plugin",
4448
"OWL Platform",
4549
"Pd External",
46-
"WebAssembly"
50+
"WebAssembly",
51+
"FMOD Plugin",
52+
"Unity Plugin",
53+
"WWISE Plugin"
4754
};
4855

4956
ExporterSettingsPanel(PluginEditor* editor, ExportingProgressView* exportingView)
@@ -54,6 +61,9 @@ class ExporterSettingsPanel final : public Component
5461
addChildComponent(views.add(new OWLExporter(editor, exportingView)));
5562
addChildComponent(views.add(new PdExporter(editor, exportingView)));
5663
addChildComponent(views.add(new WASMExporter(editor, exportingView)));
64+
addChildComponent(views.add(new FMODExporter(editor, exportingView)));
65+
addChildComponent(views.add(new UnityExporter(editor, exportingView)));
66+
addChildComponent(views.add(new WWISEExporter(editor, exportingView)));
5767

5868
addAndMakeVisible(listBox);
5969

@@ -94,6 +104,9 @@ class ExporterSettingsPanel final : public Component
94104
views[3]->getState(state);
95105
views[4]->getState(state);
96106
views[5]->getState(state);
107+
views[6]->getState(state);
108+
views[7]->getState(state);
109+
views[8]->getState(state);
97110
SettingsFile::getInstance()->setProperty("heavy_state", var(state.get()));
98111
}
99112

‎Source/Heavy/UnityExporter.h‎

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
// Copyright (c) 2026 Timothy Schoen and Wasted Audio
3+
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
4+
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
5+
*/
6+
#pragma once
7+
8+
class UnityExporter final : public ExporterBase {
9+
public:
10+
UnityExporter(PluginEditor* editor, ExportingProgressView* exportingView)
11+
: ExporterBase(editor, exportingView)
12+
{
13+
}
14+
15+
void getState(DynamicObject::Ptr globalState) override
16+
{
17+
auto* state = new DynamicObject();
18+
state->setProperty("input_patch_value", getValue<String>(inputPatchValue));
19+
state->setProperty("project_name_value", getValue<String>(projectNameValue));
20+
state->setProperty("project_copyright_value", getValue<String>(projectCopyrightValue));
21+
globalState->setProperty("unity", state);
22+
}
23+
24+
void setState(DynamicObject::Ptr globalState) override
25+
{
26+
auto const state = globalState->getProperty("unity").getDynamicObject();
27+
if (!state)
28+
return;
29+
inputPatchValue = state->getProperty("input_patch_value");
30+
projectNameValue = state->getProperty("project_name_value");
31+
projectCopyrightValue = state->getProperty("project_copyright_value");
32+
}
33+
34+
bool performExport(String const& pdPatch, String const& outdir, String const& name, String const& copyright, StringArray const& searchPaths) override
35+
{
36+
exportingView->showState(ExportingProgressView::Exporting);
37+
38+
auto const heavyPath = pathToString(heavyExecutable);
39+
40+
StringArray args = { heavyPath.quoted(), pdPatch.quoted(), "-o", outdir.quoted() };
41+
42+
args.add("-n" + name);
43+
44+
if (copyright.isNotEmpty()) {
45+
args.add("--copyright");
46+
args.add(copyright.quoted());
47+
}
48+
49+
args.add("-v");
50+
args.add("-gunity");
51+
52+
args.add("-p");
53+
for (auto& path : searchPaths) {
54+
args.add(path);
55+
}
56+
57+
if (shouldQuit)
58+
return true;
59+
60+
auto const command = args.joinIntoString(" ");
61+
startShellScript(command);
62+
63+
waitForProcessToFinish(-1);
64+
exportingView->flushConsole();
65+
66+
if (shouldQuit)
67+
return true;
68+
69+
auto const outputFile = File(outdir);
70+
outputFile.getChildFile("ir").deleteRecursively();
71+
outputFile.getChildFile("hv").deleteRecursively();
72+
73+
// Delay to get correct exit code
74+
Time::waitForMillisecondCounter(Time::getMillisecondCounter() + 300);
75+
76+
return getExitCode();
77+
}
78+
};

‎Source/Heavy/WWISEExporter.h‎

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
// Copyright (c) 2026 Timothy Schoen and Wasted Audio
3+
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
4+
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
5+
*/
6+
#pragma once
7+
8+
class WWISEExporter final : public ExporterBase {
9+
public:
10+
WWISEExporter(PluginEditor* editor, ExportingProgressView* exportingView)
11+
: ExporterBase(editor, exportingView)
12+
{
13+
}
14+
15+
void getState(DynamicObject::Ptr globalState) override
16+
{
17+
auto* state = new DynamicObject();
18+
state->setProperty("input_patch_value", getValue<String>(inputPatchValue));
19+
state->setProperty("project_name_value", getValue<String>(projectNameValue));
20+
state->setProperty("project_copyright_value", getValue<String>(projectCopyrightValue));
21+
globalState->setProperty("wwise", state);
22+
}
23+
24+
void setState(DynamicObject::Ptr globalState) override
25+
{
26+
auto const state = globalState->getProperty("wwise").getDynamicObject();
27+
if (!state)
28+
return;
29+
inputPatchValue = state->getProperty("input_patch_value");
30+
projectNameValue = state->getProperty("project_name_value");
31+
projectCopyrightValue = state->getProperty("project_copyright_value");
32+
}
33+
34+
bool performExport(String const& pdPatch, String const& outdir, String const& name, String const& copyright, StringArray const& searchPaths) override
35+
{
36+
exportingView->showState(ExportingProgressView::Exporting);
37+
38+
auto const heavyPath = pathToString(heavyExecutable);
39+
40+
StringArray args = { heavyPath.quoted(), pdPatch.quoted(), "-o", outdir.quoted() };
41+
42+
args.add("-n" + name);
43+
44+
if (copyright.isNotEmpty()) {
45+
args.add("--copyright");
46+
args.add(copyright.quoted());
47+
}
48+
49+
args.add("-v");
50+
args.add("-gwwise");
51+
52+
args.add("-p");
53+
for (auto& path : searchPaths) {
54+
args.add(path);
55+
}
56+
57+
if (shouldQuit)
58+
return true;
59+
60+
auto const command = args.joinIntoString(" ");
61+
startShellScript(command);
62+
63+
waitForProcessToFinish(-1);
64+
exportingView->flushConsole();
65+
66+
if (shouldQuit)
67+
return true;
68+
69+
auto const outputFile = File(outdir);
70+
outputFile.getChildFile("ir").deleteRecursively();
71+
outputFile.getChildFile("hv").deleteRecursively();
72+
73+
// Delay to get correct exit code
74+
Time::waitForMillisecondCounter(Time::getMillisecondCounter() + 300);
75+
76+
return getExitCode();
77+
}
78+
};

0 commit comments

Comments
 (0)