Split triggers and cutscenes and allow cutscenes to reference other cutscenes

This commit is contained in:
James Lambert 2022-06-25 14:10:18 -06:00
parent 5d25fb2cfb
commit 3d7f85f25d
10 changed files with 139 additions and 44 deletions

View file

@ -0,0 +1 @@
-c 1 -r 22050

View file

@ -0,0 +1 @@
-c 1 -r 22050

View file

@ -193,18 +193,29 @@ void generateBoundingBoxesDefinition(const aiScene* scene, CFileDefinition& file
void generateTriggerDefinition(const aiScene* scene, CFileDefinition& fileDefinition, StructureDataChunk& levelDef, const TriggerGeneratorOutput& triggerOutput) { void generateTriggerDefinition(const aiScene* scene, CFileDefinition& fileDefinition, StructureDataChunk& levelDef, const TriggerGeneratorOutput& triggerOutput) {
std::unique_ptr<StructureDataChunk> triggers(new StructureDataChunk()); std::unique_ptr<StructureDataChunk> triggers(new StructureDataChunk());
int triggerCount = 0;
for (auto& trigger : triggerOutput.triggers) { for (auto& trigger : triggerOutput.triggers) {
int cutsceneForTrigger = 0;
for (auto& cutscene : triggerOutput.cutscenes) {
if (cutscene->name == trigger->cutsceneName) {
break;
}
++cutsceneForTrigger;
}
if (cutsceneForTrigger == (int)triggerOutput.cutscenes.size()) {
continue;
}
std::unique_ptr<StructureDataChunk> triggerData(new StructureDataChunk()); std::unique_ptr<StructureDataChunk> triggerData(new StructureDataChunk());
std::unique_ptr<StructureDataChunk> cutsceneDef(new StructureDataChunk());
cutsceneDef->AddPrimitive((trigger->stepsName == "") ? std::string("NULL") : trigger->stepsName);
cutsceneDef->AddPrimitive(trigger->stepsCount);
triggerData->Add(std::move(cutsceneDef));
triggerData->Add(std::unique_ptr<StructureDataChunk>(new StructureDataChunk(trigger->bb))); triggerData->Add(std::unique_ptr<StructureDataChunk>(new StructureDataChunk(trigger->bb)));
triggerData->AddPrimitive(cutsceneForTrigger);
triggers->Add(std::move(triggerData)); triggers->Add(std::move(triggerData));
++triggerCount;
} }
std::string triggersName = fileDefinition.GetUniqueName("triggers"); std::string triggersName = fileDefinition.GetUniqueName("triggers");
@ -212,7 +223,23 @@ void generateTriggerDefinition(const aiScene* scene, CFileDefinition& fileDefini
fileDefinition.AddDefinition(std::move(triggersDef)); fileDefinition.AddDefinition(std::move(triggersDef));
levelDef.AddPrimitive("triggers", triggersName); levelDef.AddPrimitive("triggers", triggersName);
levelDef.AddPrimitive("triggerCount", triggerOutput.triggers.size()); levelDef.AddPrimitive("triggerCount", triggerCount);
std::unique_ptr<StructureDataChunk> cutscenes(new StructureDataChunk());
for (auto& cutscene : triggerOutput.cutscenes) {
std::unique_ptr<StructureDataChunk> cutsceneDef(new StructureDataChunk());
cutsceneDef->AddPrimitive((cutscene->stepsDefName == "") ? std::string("NULL") : cutscene->stepsDefName);
cutsceneDef->AddPrimitive(cutscene->steps.size());
cutscenes->Add(std::move(cutsceneDef));
}
std::string cutscenesName = fileDefinition.AddDataDefinition("cutscenes", "struct Cutscene", true, "_geo", std::move(cutscenes));
levelDef.AddPrimitive("cutscenes", cutscenesName);
levelDef.AddPrimitive("cutsceneCount", triggerOutput.cutscenes.size());
} }
void generateLocationDefinition(const aiScene* scene, CFileDefinition& fileDefinition, StructureDataChunk& levelDef, const RoomGeneratorOutput& roomOutput, const DisplayListSettings& settings) { void generateLocationDefinition(const aiScene* scene, CFileDefinition& fileDefinition, StructureDataChunk& levelDef, const RoomGeneratorOutput& roomOutput, const DisplayListSettings& settings) {

View file

@ -34,7 +34,17 @@ float distanceFromStart(const CutsceneStep& startStep, const CutsceneStep& other
return relativeOffset.y; return relativeOffset.y;
} }
std::unique_ptr<StructureDataChunk> generateCutsceneStep(CutsceneStep& step, int stepIndex, std::map<std::string, int>& labels, const RoomGeneratorOutput& roomOutput, Signals& signals) { int findCutsceneIndex(const std::vector<std::shared_ptr<Cutscene>>& cutscenes, const std::string& name) {
for (int i = 0; i < (int)cutscenes.size(); ++i) {
if (cutscenes[i]->name == name) {
return i;
}
}
return -1;
}
std::unique_ptr<StructureDataChunk> generateCutsceneStep(CutsceneStep& step, int stepIndex, std::map<std::string, int>& labels, const std::vector<std::shared_ptr<Cutscene>>& cutscenes, const RoomGeneratorOutput& roomOutput, Signals& signals) {
std::unique_ptr<StructureDataChunk> result(new StructureDataChunk()); std::unique_ptr<StructureDataChunk> result(new StructureDataChunk());
if ((step.command == "play_sound" || step.command == "start_sound") && step.args.size() >= 1) { if ((step.command == "play_sound" || step.command == "start_sound") && step.args.size() >= 1) {
@ -106,6 +116,39 @@ std::unique_ptr<StructureDataChunk> generateCutsceneStep(CutsceneStep& step, int
gotoStep->AddPrimitive(gotoLabel->second - stepIndex - 1); gotoStep->AddPrimitive(gotoLabel->second - stepIndex - 1);
result->Add("gotoStep", std::move(gotoStep)); result->Add("gotoStep", std::move(gotoStep));
return result;
}
} else if (step.command == "start_cutscene" && step.args.size() >= 1) {
int cutsceneIndex = findCutsceneIndex(cutscenes, step.args[0]);
if (cutsceneIndex != -1) {
result->AddPrimitive<const char*>("CutsceneStepTypeStartCutscene");
std::unique_ptr<StructureDataChunk> cutscene(new StructureDataChunk());
cutscene->AddPrimitive(cutsceneIndex);
result->Add("cutscene", std::move(cutscene));
return result;
}
} else if (step.command == "stop_cutscene" && step.args.size() >= 1) {
int cutsceneIndex = findCutsceneIndex(cutscenes, step.args[0]);
if (cutsceneIndex != -1) {
result->AddPrimitive<const char*>("CutsceneStepTypeStopCutscene");
std::unique_ptr<StructureDataChunk> cutscene(new StructureDataChunk());
cutscene->AddPrimitive(cutsceneIndex);
result->Add("cutscene", std::move(cutscene));
return result;
}
} else if (step.command == "wait_for_cutscene" && step.args.size() >= 1) {
int cutsceneIndex = findCutsceneIndex(cutscenes, step.args[0]);
if (cutsceneIndex != -1) {
result->AddPrimitive<const char*>("CutsceneStepTypeWaitForCutscene");
std::unique_ptr<StructureDataChunk> cutscene(new StructureDataChunk());
cutscene->AddPrimitive(cutsceneIndex);
result->Add("cutscene", std::move(cutscene));
return result; return result;
} }
} }
@ -131,7 +174,7 @@ void findLabelLocations(std::vector<std::shared_ptr<CutsceneStep>>& stepNodes, s
} }
} }
void generateCutscenes(std::map<std::string, std::shared_ptr<Cutscene>>& output, CFileDefinition& fileDefinition, const RoomGeneratorOutput& roomOutput, Signals& signals, NodeGroups& nodeGroups) { void generateCutscenes(std::vector<std::shared_ptr<Cutscene>>& output, CFileDefinition& fileDefinition, const RoomGeneratorOutput& roomOutput, Signals& signals, NodeGroups& nodeGroups) {
std::vector<std::shared_ptr<CutsceneStep>> steps; std::vector<std::shared_ptr<CutsceneStep>> steps;
std::vector<NodeWithArguments> stepNodes = nodeGroups.NodesForType(CUTSCENE_PREFIX); std::vector<NodeWithArguments> stepNodes = nodeGroups.NodesForType(CUTSCENE_PREFIX);
@ -157,7 +200,7 @@ void generateCutscenes(std::map<std::string, std::shared_ptr<Cutscene>>& output,
std::shared_ptr<Cutscene> cutscene(new Cutscene()); std::shared_ptr<Cutscene> cutscene(new Cutscene());
cutscene->name = step->args[0]; cutscene->name = step->args[0];
cutscene->steps.push_back(step); cutscene->steps.push_back(step);
output[step->args[0]] = cutscene; output.push_back(cutscene);
} else { } else {
steps.push_back(step); steps.push_back(step);
} }
@ -165,15 +208,15 @@ void generateCutscenes(std::map<std::string, std::shared_ptr<Cutscene>>& output,
for (auto& cutscene : output) { for (auto& cutscene : output) {
for (auto& step : steps) { for (auto& step : steps) {
if (doesBelongToCutscene(*cutscene.second->steps[0], *step)) { if (doesBelongToCutscene(*cutscene->steps[0], *step)) {
cutscene.second->steps.push_back(step); cutscene->steps.push_back(step);
} }
} }
} }
for (auto& cutsceneEntry : output) { for (auto& cutsceneEntry : output) {
Cutscene& cutscene = *cutsceneEntry.second; Cutscene& cutscene = *cutsceneEntry;
std::shared_ptr<CutsceneStep> firstStep = cutscene.steps[0]; std::shared_ptr<CutsceneStep> firstStep = cutscene.steps[0];
cutscene.steps.erase(cutscene.steps.begin()); cutscene.steps.erase(cutscene.steps.begin());
@ -191,7 +234,7 @@ void generateCutscenes(std::map<std::string, std::shared_ptr<Cutscene>>& output,
int currStepIndex = 0; int currStepIndex = 0;
for (auto& step : cutscene.steps) { for (auto& step : cutscene.steps) {
steps->Add(std::move(generateCutsceneStep(*step, currStepIndex, labelLocations, roomOutput, signals))); steps->Add(std::move(generateCutsceneStep(*step, currStepIndex, labelLocations, output, roomOutput, signals)));
++currStepIndex; ++currStepIndex;
} }
@ -199,16 +242,14 @@ void generateCutscenes(std::map<std::string, std::shared_ptr<Cutscene>>& output,
std::unique_ptr<FileDefinition> stepsDef(new DataFileDefinition("struct CutsceneStep", stepsName, true, "_geo", std::move(steps))); std::unique_ptr<FileDefinition> stepsDef(new DataFileDefinition("struct CutsceneStep", stepsName, true, "_geo", std::move(steps)));
stepsDef->AddTypeHeader("\"../build/src/audio/clips.h\""); stepsDef->AddTypeHeader("\"../build/src/audio/clips.h\"");
fileDefinition.AddDefinition(std::move(stepsDef)); fileDefinition.AddDefinition(std::move(stepsDef));
cutscene.defName = stepsName; cutscene.stepsDefName = stepsName;
} }
} }
std::shared_ptr<TriggerGeneratorOutput> generateTriggers(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput, Signals& signals, NodeGroups& nodeGroups) { std::shared_ptr<TriggerGeneratorOutput> generateTriggers(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput, Signals& signals, NodeGroups& nodeGroups) {
std::shared_ptr<TriggerGeneratorOutput> output(new TriggerGeneratorOutput()); std::shared_ptr<TriggerGeneratorOutput> output(new TriggerGeneratorOutput());
std::map<std::string, std::shared_ptr<Cutscene>> cutscenes; generateCutscenes(output->cutscenes, fileDefinition, roomOutput, signals, nodeGroups);
generateCutscenes(cutscenes, fileDefinition, roomOutput, signals, nodeGroups);
for (auto& nodeInfo : nodeGroups.NodesForType(TRIGGER_PREFIX)) { for (auto& nodeInfo : nodeGroups.NodesForType(TRIGGER_PREFIX)) {
auto mesh = fileDefinition.GetExtendedMesh(scene->mMeshes[nodeInfo.node->mMeshes[0]]); auto mesh = fileDefinition.GetExtendedMesh(scene->mMeshes[nodeInfo.node->mMeshes[0]]);
@ -217,15 +258,7 @@ std::shared_ptr<TriggerGeneratorOutput> generateTriggers(const aiScene* scene, C
std::string nodeName = nodeInfo.node->mName.C_Str(); std::string nodeName = nodeInfo.node->mName.C_Str();
auto cutscene = cutscenes.find(nodeInfo.arguments.size() ? nodeInfo.arguments[0] : std::string("")); trigger->cutsceneName = nodeInfo.arguments.size() ? nodeInfo.arguments[0] : std::string("");
if (cutscene == cutscenes.end()) {
trigger->stepsName = "";
trigger->stepsCount = 0;
} else {
trigger->stepsName = cutscene->second->defName;
trigger->stepsCount = cutscene->second->steps.size();
}
aiVector3D minTransformed = nodeInfo.node->mTransformation * mesh->bbMin * settings.mModelScale; aiVector3D minTransformed = nodeInfo.node->mTransformation * mesh->bbMin * settings.mModelScale;
aiVector3D maxTransformed = nodeInfo.node->mTransformation * mesh->bbMax * settings.mModelScale; aiVector3D maxTransformed = nodeInfo.node->mTransformation * mesh->bbMax * settings.mModelScale;

View file

@ -8,23 +8,10 @@
#include <map> #include <map>
struct Trigger { struct Trigger {
std::string stepsName; std::string cutsceneName;
int stepsCount;
aiAABB bb; aiAABB bb;
}; };
struct Button {
aiVector3D position;
int roomIndex;
int signalIndex;
int cubeSignalIndex;
};
struct TriggerGeneratorOutput {
std::vector<std::shared_ptr<Trigger>> triggers;
std::vector<Button> buttons;
};
struct CutsceneStep { struct CutsceneStep {
CutsceneStep(const std::string& command, const std::vector<std::string>& args, const aiVector3D& location, const aiQuaternion& direction); CutsceneStep(const std::string& command, const std::vector<std::string>& args, const aiVector3D& location, const aiQuaternion& direction);
@ -36,10 +23,23 @@ struct CutsceneStep {
struct Cutscene { struct Cutscene {
std::string name; std::string name;
std::string defName; std::string stepsDefName;
std::vector<std::shared_ptr<CutsceneStep>> steps; std::vector<std::shared_ptr<CutsceneStep>> steps;
}; };
struct Button {
aiVector3D position;
int roomIndex;
int signalIndex;
int cubeSignalIndex;
};
struct TriggerGeneratorOutput {
std::vector<std::shared_ptr<Trigger>> triggers;
std::vector<std::shared_ptr<Cutscene>> cutscenes;
std::vector<Button> buttons;
};
std::shared_ptr<TriggerGeneratorOutput> generateTriggers(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput, Signals& signals, NodeGroups& nodeGroups); std::shared_ptr<TriggerGeneratorOutput> generateTriggers(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput, Signals& signals, NodeGroups& nodeGroups);
void generateButtonsDefinition(CFileDefinition& fileDefinition, StructureDataChunk& levelDefinitionChunk, const std::vector<Button>& buttons); void generateButtonsDefinition(CFileDefinition& fileDefinition, StructureDataChunk& levelDefinitionChunk, const std::vector<Button>& buttons);

View file

@ -79,6 +79,12 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
case CutsceneStepTypeGoto: case CutsceneStepTypeGoto:
runner->currentStep += step->gotoStep.relativeInstructionIndex; runner->currentStep += step->gotoStep.relativeInstructionIndex;
break; break;
case CutsceneStepTypeStartCutscene:
cutsceneStart(&gCurrentLevel->cutscenes[step->cutscene.cutsceneIndex]);
break;
case CutsceneStepTypeStopCutscene:
cutsceneStop(&gCurrentLevel->cutscenes[step->cutscene.cutsceneIndex]);
break;
default: default:
} }
} }
@ -93,6 +99,8 @@ int cutsceneRunnerUpdateCurrentStep(struct CutsceneRunner* runner) {
return runner->state.delay <= 0.0f; return runner->state.delay <= 0.0f;
case CutsceneStepTypeWaitForSignal: case CutsceneStepTypeWaitForSignal:
return signalsRead(step->waitForSignal.signalIndex); return signalsRead(step->waitForSignal.signalIndex);
case CutsceneStepTypeWaitForCutscene:
return !cutsceneIsRunning(&gCurrentLevel->cutscenes[step->cutscene.cutsceneIndex]);
default: default:
return 1; return 1;
} }
@ -151,6 +159,22 @@ void cutsceneStop(struct Cutscene* cutscene) {
} }
} }
int cutsceneIsRunning(struct Cutscene* cutscene) {
struct CutsceneRunner* current = gRunningCutscenes;
while (current) {
if (current->currentCutscene == cutscene) {
return 1;
}
current = current->nextRunner;
}
return 0;
}
void cutscenesUpdate() { void cutscenesUpdate() {
struct CutsceneRunner* previousCutscene = NULL; struct CutsceneRunner* previousCutscene = NULL;
struct CutsceneRunner* current = gRunningCutscenes; struct CutsceneRunner* current = gRunningCutscenes;

View file

@ -21,6 +21,7 @@ struct CutsceneRunner {
void cutsceneStart(struct Cutscene* cutscene); void cutsceneStart(struct Cutscene* cutscene);
void cutsceneStop(struct Cutscene* cutscene); void cutsceneStop(struct Cutscene* cutscene);
int cutsceneIsRunning(struct Cutscene* cutscene);
void cutscenesUpdate(); void cutscenesUpdate();
#endif #endif

View file

@ -33,6 +33,9 @@ enum CutsceneStepType {
CutsceneStepTypeTeleportPlayer, CutsceneStepTypeTeleportPlayer,
CutsceneStepTypeLoadLevel, CutsceneStepTypeLoadLevel,
CutsceneStepTypeGoto, CutsceneStepTypeGoto,
CutsceneStepTypeStartCutscene,
CutsceneStepTypeStopCutscene,
CutsceneStepTypeWaitForCutscene,
}; };
struct CutsceneStep { struct CutsceneStep {
@ -67,6 +70,9 @@ struct CutsceneStep {
struct { struct {
s16 relativeInstructionIndex; s16 relativeInstructionIndex;
} gotoStep; } gotoStep;
struct {
u16 cutsceneIndex;
} cutscene;
int noop; int noop;
}; };
}; };
@ -77,8 +83,8 @@ struct Cutscene {
}; };
struct Trigger { struct Trigger {
struct Cutscene cutscene;
struct Box3D box; struct Box3D box;
short cutsceneIndex;
}; };
struct Location { struct Location {
@ -132,6 +138,7 @@ struct LevelDefinition {
// maps index of a collisionQuads to indices in portalSurfaces // maps index of a collisionQuads to indices in portalSurfaces
struct PortalSurfaceMapping* portalSurfaceMapping; struct PortalSurfaceMapping* portalSurfaceMapping;
struct Trigger* triggers; struct Trigger* triggers;
struct Cutscene* cutscenes;
struct Location* locations; struct Location* locations;
struct World world; struct World world;
struct DoorDefinition* doors; struct DoorDefinition* doors;
@ -144,6 +151,7 @@ struct LevelDefinition {
short staticContentCount; short staticContentCount;
short portalSurfaceCount; short portalSurfaceCount;
short triggerCount; short triggerCount;
short cutsceneCount;
short locationCount; short locationCount;
short doorCount; short doorCount;
short buttonCount; short buttonCount;

View file

@ -66,7 +66,7 @@ void levelCheckTriggers(struct Vector3* playerPos) {
struct Trigger* trigger = &gCurrentLevel->triggers[i]; struct Trigger* trigger = &gCurrentLevel->triggers[i];
u64 cutsceneMask = 1LL << i; u64 cutsceneMask = 1LL << i;
if (!(gTriggeredCutscenes & cutsceneMask) && box3DContainsPoint(&trigger->box, playerPos)) { if (!(gTriggeredCutscenes & cutsceneMask) && box3DContainsPoint(&trigger->box, playerPos)) {
cutsceneStart(&trigger->cutscene); cutsceneStart(&gCurrentLevel->cutscenes[trigger->cutsceneIndex]);
// prevent the trigger from happening again // prevent the trigger from happening again
gTriggeredCutscenes |= cutsceneMask; gTriggeredCutscenes |= cutsceneMask;
} }