diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index c43e4dc9..f8ef1bab 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -503,6 +503,12 @@ MxBool RemoveFromCurrentWorld(const MxAtomId& p_atomId, MxS32 p_id) { LegoWorld* world = CurrentWorld(); + auto result = + Extension::Call(HandleRemove, SiLoader::StreamObject{p_atomId, p_id}, world).value_or(std::nullopt); + if (result) { + return result.value(); + } + if (world) { MxCore* object = world->Find(p_atomId, p_id); @@ -518,8 +524,6 @@ MxBool RemoveFromCurrentWorld(const MxAtomId& p_atomId, MxS32 p_id) } ((MxPresenter*) object)->EndAction(); - - Extension::Call(RemoveWith, SiLoader::StreamObject{p_atomId, p_id}, world); } return TRUE; @@ -539,6 +543,12 @@ MxBool RemoveFromWorld( { LegoWorld* world = FindWorld(p_worldAtom, p_worldEntityId); + auto result = Extension::Call(HandleRemove, SiLoader::StreamObject{p_entityAtom, p_entityId}, world) + .value_or(std::nullopt); + if (result) { + return result.value(); + } + if (world) { MxCore* object = world->Find(p_entityAtom, p_entityId); @@ -554,8 +564,6 @@ MxBool RemoveFromWorld( } ((MxPresenter*) object)->EndAction(); - - Extension::Call(RemoveWith, SiLoader::StreamObject{p_entityAtom, p_entityId}, world); } return TRUE; diff --git a/LEGO1/lego/legoomni/src/main/legomain.cpp b/LEGO1/lego/legoomni/src/main/legomain.cpp index 975933ff..abe922c5 100644 --- a/LEGO1/lego/legoomni/src/main/legomain.cpp +++ b/LEGO1/lego/legoomni/src/main/legomain.cpp @@ -663,6 +663,17 @@ void LegoOmni::CreateBackgroundAudio() // FUNCTION: BETA10 0x1008f7e0 MxResult LegoOmni::Start(MxDSAction* p_dsAction) { + { + auto result = Extension::Call( + HandleStart, + SiLoader::StreamObject{p_dsAction->GetAtomId(), p_dsAction->GetObjectId()} + ) + .value_or(std::nullopt); + if (result) { + return result.value(); + } + } + MxResult result = MxOmni::Start(p_dsAction); #ifdef BETA10 this->m_action = *p_dsAction; @@ -673,14 +684,6 @@ MxResult LegoOmni::Start(MxDSAction* p_dsAction) this->m_action.SetObjectId(p_dsAction->GetObjectId()); this->m_action.SetUnknown24(p_dsAction->GetUnknown24()); #endif - - if (result == SUCCESS) { - Extension::Call( - StartWith, - SiLoader::StreamObject{p_dsAction->GetAtomId(), p_dsAction->GetObjectId()} - ); - } - return result; } diff --git a/assets/main.cpp b/assets/main.cpp index e1189012..bbb033b6 100644 --- a/assets/main.cpp +++ b/assets/main.cpp @@ -12,32 +12,37 @@ uint32_t bufferCount = 8; std::string out; std::ofstream depfile; -si::MemoryBuffer mxHd; void CreateWidescreen() { si::Interleaf si; - std::string file = out + "/widescreen.si"; - mxHd.seek(0, si::MemoryBuffer::SeekStart); - si.Read(&mxHd); + si.Read("widescreen/GaraDoor.si"); - si::Object GaraDoor_Wide; - const char extra[] = - "World:current, StartWith:\\Lego\\Scripts\\Isle\\Isle;1160, RemoveWith:\\Lego\\Scripts\\Isle\\Isle;1161"; - GaraDoor_Wide.type_ = si::MxOb::Bitmap; - GaraDoor_Wide.flags_ = MxDSAction::c_enabled | MxDSAction::c_bit4; - GaraDoor_Wide.duration_ = -1; - GaraDoor_Wide.loops_ = 1; - GaraDoor_Wide.extra_ = si::bytearray(extra, sizeof(extra)); - GaraDoor_Wide.presenter_ = "MxStillPresenter"; - GaraDoor_Wide.name_ = "GaraDoor_Wide"; - GaraDoor_Wide.filetype_ = si::MxOb::STL; - GaraDoor_Wide.location_.x = -240.0; - GaraDoor_Wide.location_.z = -1.0; - GaraDoor_Wide.up_.y = 1.0; - GaraDoor_Wide.ReplaceWithFile("widescreen/garadoor.bmp"); - si.AppendChild(&GaraDoor_Wide); - depfile << file << ": " << (std::filesystem::current_path() / "widescreen/garadoor.bmp").string() << std::endl; + si::Object* garadoor = dynamic_cast(si.GetChildAt(0)); + const char append[] = "Replace:\\Lego\\Scripts\\Isle\\Isle;1160"; + garadoor->extra_.append(append, sizeof(append)); + + si::Object GaraDoor_Background_Wide; + const char extra[] = "World:current, RemoveWith:\\Lego\\Scripts\\Isle\\Isle;1161"; + GaraDoor_Background_Wide.id_ = 5001; + GaraDoor_Background_Wide.type_ = si::MxOb::Bitmap; + GaraDoor_Background_Wide.flags_ = MxDSAction::c_enabled | MxDSAction::c_bit4; + GaraDoor_Background_Wide.duration_ = -1; + GaraDoor_Background_Wide.loops_ = 1; + GaraDoor_Background_Wide.extra_ = si::bytearray(extra, sizeof(extra)); + GaraDoor_Background_Wide.presenter_ = "MxStillPresenter"; + GaraDoor_Background_Wide.name_ = "GaraDoor_Background_Wide"; + GaraDoor_Background_Wide.filetype_ = si::MxOb::STL; + GaraDoor_Background_Wide.location_ = si::Vector3(-240.0, 0.0, -1.0); + GaraDoor_Background_Wide.direction_ = si::Vector3(0, 0, 0); + GaraDoor_Background_Wide.up_ = si::Vector3(0, 1.0, 0); + GaraDoor_Background_Wide.up_.y = 1.0; + GaraDoor_Background_Wide.ReplaceWithFile("widescreen/GaraDoor_Background_Wide.bmp"); + garadoor->AppendChild(&GaraDoor_Background_Wide); + + std::string file = out + "/widescreen.si"; + depfile << file << ": " << (std::filesystem::current_path() / "widescreen/GaraDoor_Background_Wide.bmp").string() + << std::endl; si.Write(file.c_str()); } @@ -47,12 +52,6 @@ int main(int argc, char* argv[]) out = argv[1]; depfile = std::ofstream(argv[2]); - mxHd.WriteU32(si::RIFF::MxHd); - mxHd.WriteU32(3 * sizeof(uint32_t)); - mxHd.WriteU32(version); - mxHd.WriteU32(bufferSize); - mxHd.WriteU32(bufferCount); - CreateWidescreen(); return 0; } diff --git a/assets/widescreen/GaraDoor.si b/assets/widescreen/GaraDoor.si new file mode 100755 index 00000000..27b857c0 Binary files /dev/null and b/assets/widescreen/GaraDoor.si differ diff --git a/assets/widescreen/garadoor.bmp b/assets/widescreen/GaraDoor_Background_Wide.bmp similarity index 100% rename from assets/widescreen/garadoor.bmp rename to assets/widescreen/GaraDoor_Background_Wide.bmp diff --git a/extensions/include/extensions/siloader.h b/extensions/include/extensions/siloader.h index 3fc7ab0a..e4ed4d1e 100644 --- a/extensions/include/extensions/siloader.h +++ b/extensions/include/extensions/siloader.h @@ -4,6 +4,7 @@ #include "legoworld.h" #include "mxatom.h" +#include #include #include @@ -15,8 +16,8 @@ class SiLoader { static void Initialize(); static bool Load(); - static bool StartWith(StreamObject p_object); - static bool RemoveWith(StreamObject p_object, LegoWorld* world); + static std::optional HandleStart(StreamObject p_object); + static std::optional HandleRemove(StreamObject p_object, LegoWorld* world); static std::map options; static std::vector files; @@ -25,17 +26,23 @@ class SiLoader { private: static std::vector> startWith; static std::vector> removeWith; + static std::vector> replace; static bool LoadFile(const char* p_file); + static void ParseDirectives( + const MxAtomId& p_atom, + si::Core* p_core, + const MxAtomId* p_parentReplacedAtom = nullptr + ); }; #ifdef EXTENSIONS constexpr auto Load = &SiLoader::Load; -constexpr auto StartWith = &SiLoader::StartWith; -constexpr auto RemoveWith = &SiLoader::RemoveWith; +constexpr auto HandleStart = &SiLoader::HandleStart; +constexpr auto HandleRemove = &SiLoader::HandleRemove; #else constexpr decltype(&SiLoader::Load) Load = nullptr; -constexpr decltype(&SiLoader::StartWith) StartWith = nullptr; -constexpr decltype(&SiLoader::RemoveWith) RemoveWith = nullptr; +constexpr decltype(&SiLoader::HandleStart) HandleStart = nullptr; +constexpr decltype(&SiLoader::HandleRemove) HandleRemove = nullptr; #endif }; // namespace Extensions diff --git a/extensions/src/siloader.cpp b/extensions/src/siloader.cpp index bfbddd88..121f742c 100644 --- a/extensions/src/siloader.cpp +++ b/extensions/src/siloader.cpp @@ -5,7 +5,6 @@ #include "mxstreamer.h" #include -#include using namespace Extensions; @@ -13,6 +12,7 @@ std::map SiLoader::options; std::vector SiLoader::files; std::vector> SiLoader::startWith; std::vector> SiLoader::removeWith; +std::vector> SiLoader::replace; bool SiLoader::enabled = false; void SiLoader::Initialize() @@ -36,7 +36,7 @@ bool SiLoader::Load() return true; } -bool SiLoader::StartWith(StreamObject p_object) +std::optional SiLoader::HandleStart(StreamObject p_object) { for (const auto& key : startWith) { if (key.first == p_object) { @@ -47,10 +47,19 @@ bool SiLoader::StartWith(StreamObject p_object) } } - return true; + for (const auto& key : replace) { + if (key.first == p_object) { + MxDSAction action; + action.SetAtomId(key.second.first); + action.SetObjectId(key.second.second); + return Start(&action); + } + } + + return std::nullopt; } -bool SiLoader::RemoveWith(StreamObject p_object, LegoWorld* world) +std::optional SiLoader::HandleRemove(StreamObject p_object, LegoWorld* world) { for (const auto& key : removeWith) { if (key.first == p_object) { @@ -58,7 +67,13 @@ bool SiLoader::RemoveWith(StreamObject p_object, LegoWorld* world) } } - return true; + for (const auto& key : replace) { + if (key.first == p_object) { + return RemoveFromWorld(key.second.first, key.second.second, world->GetAtomId(), world->GetEntityId()); + } + } + + return std::nullopt; } bool SiLoader::LoadFile(const char* p_file) @@ -82,7 +97,13 @@ bool SiLoader::LoadFile(const char* p_file) return false; } - for (si::Core* child : si.GetChildren()) { + ParseDirectives(controller->GetAtom(), &si); + return true; +} + +void SiLoader::ParseDirectives(const MxAtomId& p_atom, si::Core* p_core, const MxAtomId* p_parentReplacedAtom) +{ + for (si::Core* child : p_core->GetChildren()) { if (si::Object* object = dynamic_cast(child)) { if (object->type() != si::MxOb::Null) { std::string extra(object->extra_.data(), object->extra_.size()); @@ -94,7 +115,7 @@ bool SiLoader::LoadFile(const char* p_file) if (SDL_sscanf(directive, "StartWith:%255[^;];%d", atom, &id) == 2) { startWith.emplace_back( StreamObject{MxAtomId{atom, e_lowerCase2}, id}, - StreamObject{controller->GetAtom(), object->id_} + StreamObject{p_atom, object->id_} ); } } @@ -103,13 +124,28 @@ bool SiLoader::LoadFile(const char* p_file) if (SDL_sscanf(directive, "RemoveWith:%255[^;];%d", atom, &id) == 2) { removeWith.emplace_back( StreamObject{MxAtomId{atom, e_lowerCase2}, id}, - StreamObject{controller->GetAtom(), object->id_} + StreamObject{p_atom, object->id_} ); } } + + if (p_parentReplacedAtom) { + replace.emplace_back(StreamObject{*p_parentReplacedAtom, id}, StreamObject{p_atom, object->id_}); + } + else { + if ((directive = SDL_strstr(extra.c_str(), "Replace:"))) { + if (SDL_sscanf(directive, "Replace:%255[^;];%d", atom, &id) == 2) { + replace.emplace_back( + StreamObject{MxAtomId{atom, e_lowerCase2}, id}, + StreamObject{p_atom, object->id_} + ); + p_parentReplacedAtom = &replace.back().first.first; + } + } + } } } - } - return true; + ParseDirectives(p_atom, child, p_parentReplacedAtom); + } }