diff --git a/src/system/hamobj/ClipPlayer.cpp b/src/system/hamobj/ClipPlayer.cpp index f236a3b0..d5cc91d5 100644 --- a/src/system/hamobj/ClipPlayer.cpp +++ b/src/system/hamobj/ClipPlayer.cpp @@ -92,7 +92,22 @@ void ClipPlayer::PlayAnims(HamCharacter *c, float f1, float f2, int x) { } namespace { - float ClipStart(CharClip *, float, float &, float &); + float ClipStart(CharClip *clip, float beat, float &start, float &end) { + if (fmodf(beat, 1.0) != 0.0f && ceilf(beat) - beat < 0.0001f) { + beat = ceil(beat); + } + float offset = 0.0f; + float period = (clip->PlayFlags() >> 12) & 0xF; + + if (period != 0.0f) { + offset = Mod(beat - clip->StartBeat(), period); + } + + start = beat - offset; + end = clip->EndBeat() - clip->StartBeat() + start; + + return clip->StartBeat() + offset; + } } void ClipPlayer::PlayClip(CharClip *clip, float f1, float f2, HamDriver::LayerArray *arr) { @@ -215,3 +230,28 @@ void ClipPlayer::PlayNormal(float f1, HamDriver::LayerArray *arr, const char *cc } } } + +float ClipPlayer::ClipLength(CharClip *clip) { + float end = floor(clip->EndBeat()); + float start = ceil(clip->StartBeat()); + return end - start; +} + +bool ClipPlayer::GetClipRange( + const char *c1, const char *c2, float f1, float &f2, float &f3, float &f4 +) { + auto clip = mClipDir->Find(c1, false); + if (clip) { + float clipStart = ClipStart(clip, f1, f2, f3); + f4 = 1e+30; + auto clip2 = mClipDir->Find(c2, false); + if (clip2 != nullptr) { + auto node = clip->FindLastNode(clip2, clipStart); + if (node != nullptr) { + f4 = (node->curBeat - clip->StartBeat()) + f2; + } + } + return true; + } + return false; +} \ No newline at end of file diff --git a/src/system/hamobj/ClipPlayer.h b/src/system/hamobj/ClipPlayer.h index b275c212..c9eb7a1f 100644 --- a/src/system/hamobj/ClipPlayer.h +++ b/src/system/hamobj/ClipPlayer.h @@ -37,6 +37,7 @@ class ClipPlayer { void GetRoutineCrossoverClips(float, const char *, CharClip **, CharClip **); bool PushRoutineBuilderClip(int, HamDriver::LayerArray *); void PushClip(int, HamDriver::LayerArray *); + bool GetClipRange(const char *, const char *, float, float &, float &, float &); Keys *mClipKeys; // 0x0 Keys *mClipCrossoverKeys; // 0x4 diff --git a/src/system/rndobj/PostProc_NG.cpp b/src/system/rndobj/PostProc_NG.cpp index 1175c67e..7bb1cc12 100644 --- a/src/system/rndobj/PostProc_NG.cpp +++ b/src/system/rndobj/PostProc_NG.cpp @@ -19,7 +19,11 @@ Hmx::Color NgPostProc::s_prevBloomColor(-1, -1, -1, -1); float NgPostProc::s_prevBloomIntensity = -1; NgPostProc::BloomTextures<3> NgPostProc::sBloom; -NgPostProc::BloomTextureSet::BloomTextureSet() : mBloomTexture() {} +NgPostProc::BloomTextureSet::BloomTextureSet() { + for (int i = 0; i < 2; i++) { + mBloomTexture[i] = nullptr; + } +} NgPostProc::BloomTextureSet::~BloomTextureSet() { FreeTextures(); } @@ -172,4 +176,44 @@ void NgPostProc::CheckNoise() { TheRenderState.SetTextureFilter(13, (RndRenderState::FilterMode)1, false); TheRenderState.SetTextureClamp(13, (RndRenderState::ClampMode)0); } +} + +void NgPostProc::CheckHallOfTime() { + if (HallOfTime() && !unk250) { + Vector4 c1(mHallOfTimeRate, mHallOfTimeMix, 0.0f, 0.0f); + TheShaderMgr.SetPConstant((PShaderConstant)0x73, c1); + + Vector4 c2( + mHallOfTimeColor.red, mHallOfTimeColor.green, mHallOfTimeColor.blue, 1.0f + ); + TheShaderMgr.SetPConstant((PShaderConstant)0x74, c2); + + TheShaderMgr.SetUnk34(mHallOfTimeType + 1); + } +} + +void NgPostProc::DoPost() { + RndPostProc::DoPost(); + DoVelocity(); + DoBloom(); + ModulateColorXfm(); + CheckNoise(); + CheckBlendPrevious(); + CheckHallOfTime(); + CheckMotionBlur(); + CheckGradientMap(); + CheckHueConverge(); + CheckRefract(); + CheckChromaticAberration(); + CheckPosterizeAndKaleidoscope(); + CheckVignette(); + TheShaderMgr.SetUnk29(ColorXfmEnabled()); + TheShaderMgr.SetUnk2f(BlendPrevious()); + mBlendAmount = 0.0f; +} + +void NgPostProc::QueueMotionBlurObject(RndDrawable *drawable) { + if (FindInList(unk23c, drawable) == unk23c.end()) { + unk23c.push_back(drawable); + } } \ No newline at end of file diff --git a/src/system/rndobj/PostProc_NG.h b/src/system/rndobj/PostProc_NG.h index 091dc6c5..f8a04edb 100644 --- a/src/system/rndobj/PostProc_NG.h +++ b/src/system/rndobj/PostProc_NG.h @@ -72,6 +72,23 @@ class NgPostProc : public RndPostProc { void CheckBlendPrevious(); void DoVelocity(); void CheckNoise(); + void CheckHueConverge(); + void CheckHallOfTime(); + void DoBloom(); + void ModulateColorXfm(); + void CheckRefract(); + void CheckChromaticAberration(); + void CheckPosterizeAndKaleidoscope(); + + ObjPtrList::iterator + FindInList(ObjPtrList &list, Object *o) { + FOREACH (it, list) { + if ((Object *)*it == o) { + return it; + } + } + return list.end(); + } float unk22c; // 0x22c float unk230; // 0x230 diff --git a/src/system/rndobj/ShaderMgr.h b/src/system/rndobj/ShaderMgr.h index 074f6ef7..8d9745fa 100644 --- a/src/system/rndobj/ShaderMgr.h +++ b/src/system/rndobj/ShaderMgr.h @@ -77,6 +77,9 @@ class RndShaderMgr { void SetUnk3e(bool b) { unk3e = b; } void SetUnk38(bool b) { unk38 = b; } void SetUnk39(bool b) { unk39 = b; } + void SetUnk34(int i) { unk34 = i; } + void SetUnk29(bool b) { unk29 = b; } + void SetUnk2f(bool b) { unk2f = b; } protected: virtual void LoadShaders(const char *); diff --git a/src/system/utl/DebugGraph.cpp b/src/system/utl/DebugGraph.cpp index 0f890ba2..10976294 100644 --- a/src/system/utl/DebugGraph.cpp +++ b/src/system/utl/DebugGraph.cpp @@ -1,6 +1,7 @@ #include "DebugGraph.h" +#include "rndobj/Graph.h" -void DebugGraph::AddData(float data, bool b) { +void DebugGraph::AddData(float data, bool b) { Sample sample; sample.data = data; sample.b = b; @@ -9,4 +10,92 @@ void DebugGraph::AddData(float data, bool b) { if (mSamples.size() == unk38 + 1) { mSamples.pop_back(); } +} + +inline float clamp(float val) { + float c = -val >= 0.0f ? 0.0f : val; + return c - 1.0f >= 0.0f ? 1.0f : c; +} + +void DebugGraph::Draw() { + RndGraph *rnd = RndGraph::GetOneFrame(); + + Hmx::Rect rect(mRect.x, mRect.y, mRect.w, mRect.h); + rnd->AddRectFilled2D(rect, mColorB); + + if (unk50) { + Vector2 minPos(mRect.x, mRect.y + mRect.h - 0.02f); + rnd->AddScreenString(MakeString("%.3f", unk3c), minPos, mColorA); + + Vector2 maxPos(mRect.x, mRect.y); + rnd->AddScreenString(MakeString("%.3f", unk40), maxPos, mColorA); + } + + if (unk44 != FLT_MAX) { + Hmx::Color color(1.0f, 1.0f, 1.0f, 1.0f); + + Vector2 p2( + mRect.w + mRect.x, + mRect.y + mRect.h * (1.0f - clamp((unk44 - unk3c) / (unk40 - unk3c))) + ); + + Vector2 p1( + mRect.x, mRect.y + mRect.h * (1.0f - clamp((unk44 - unk3c) / (unk40 - unk3c))) + ); + + rnd->AddScreenLine(p1, p2, color, false); + + Vector2 textPos( + mRect.x, mRect.y + mRect.h * (1.0f - clamp((unk44 - unk3c) / (unk40 - unk3c))) + ); + + rnd->AddScreenString( + MakeString("%.3f", unk44), textPos, Hmx::Color(1.0f, 1.0f, 1.0f, 1.0f) + ); + } + + Vector2 titlePos; + + titlePos.y = mRect.y; + Hmx::Color color(1.0f, 1.0f, 1.0f, 1.0f); + titlePos.x = mRect.x + 0.1f; + + rnd->AddScreenString(unk48.c_str(), titlePos, color); + + if (!mSamples.empty()) { + auto it = mSamples.begin(); + int idx = 1; + Vector2 prevPos( + mRect.x + mRect.w * (1.0f - clamp(0.0f / (float)(unk38 - 1))), + mRect.y + mRect.h * (1.0f - clamp((it->data - unk3c) / (unk40 - unk3c))) + ); + + ++it; + + for (; it != mSamples.end(); ++it) { + Vector2 curPos( + mRect.x + mRect.w * (1.0f - clamp((float)idx / (float)(unk38 - 1))), + mRect.y + mRect.h * (1.0f - clamp((it->data - unk3c) / (unk40 - unk3c))) + ); + + if (it->b) { + Vector2 hl_p1( + mRect.x + mRect.w * (1.0f - clamp((float)idx / (float)(unk38 - 1))), + mRect.y + mRect.h + ); + + Vector2 hl_p2( + mRect.x + mRect.w * (1.0f - clamp((float)idx / (float)(unk38 - 1))), + mRect.y + ); + + rnd->AddScreenLine( + hl_p2, hl_p1, Hmx::Color(1.0f, 1.0f, 1.0f, 1.0f), false + ); + } + rnd->AddScreenLine(curPos, prevPos, mColorA, false); + prevPos = curPos; + idx++; + } + } } \ No newline at end of file diff --git a/src/system/utl/Locale.cpp b/src/system/utl/Locale.cpp index ea809ad5..12c5cf5e 100644 --- a/src/system/utl/Locale.cpp +++ b/src/system/utl/Locale.cpp @@ -1,4 +1,6 @@ #include "utl/Locale.h" + +#include "DataPointMgr.h" #include "obj/DataFile.h" #include "obj/DataFunc.h" #include "os/Debug.h" @@ -8,22 +10,32 @@ #include "xdk/xbdm/xbdm.h" #include +char gLocaleBuffers[4][50]; // not sure if these 2 should be globals but i currently have +int gLocalBufIdx = 0; // no other ideas + +bool gShowTokensCheat; + DataNode DataSetLocaleVerboseNotify(DataArray *arr) { Locale::SetLocaleVerboseNotify(arr->Int(1)); return DataNode(0); } DataNode DataToggleShowTokensCheat(DataArray *arr) { + gShowTokensCheat = !gShowTokensCheat; return DataNode(0); } static int LocaleChunkSortFunc(const void *a, const void *b) { - const LocaleChunkSort::OrderedLocaleChunk *chunkA = (const LocaleChunkSort::OrderedLocaleChunk *)a; - const LocaleChunkSort::OrderedLocaleChunk *chunkB = (const LocaleChunkSort::OrderedLocaleChunk *)b; + const LocaleChunkSort::OrderedLocaleChunk *chunkA = + (const LocaleChunkSort::OrderedLocaleChunk *)a; + const LocaleChunkSort::OrderedLocaleChunk *chunkB = + (const LocaleChunkSort::OrderedLocaleChunk *)b; Symbol symA = chunkA->node1.LiteralSym(0); Symbol symB = chunkB->node1.LiteralSym(0); - if (symA < symB) return -1; - if (symA > symB) return 1; + if (symA < symB) + return -1; + if (symA > symB) + return 1; return chunkA->node2.Int(0) - chunkB->node2.Int(0); } @@ -66,7 +78,9 @@ void Locale::Init() { Symbol s60; // Check for alternate devkit locale file - String devkitPath(FileMakePath("devkit:\\locale", MakeString("%s\\locale_keep.dta", SystemLanguage()))); + String devkitPath(FileMakePath( + "devkit:\\locale", MakeString("%s\\locale_keep.dta", SystemLanguage()) + )); FileQualifiedFilename(devkitPath, devkitPath.c_str()); static Symbol locale("locale"); @@ -179,3 +193,110 @@ void Locale::Init() { DataRegisterFunc("set_locale_verbose_notify", DataSetLocaleVerboseNotify); DataRegisterFunc("toggle_show_tokens_cheat", DataToggleShowTokensCheat); } + +const char *Localize(Symbol sym, bool *found, Locale &loc) { + if (gShowTokensCheat) { + if (found) { + *found = true; + } + return sym.Str(); + } else { + const char *res = loc.Localize(sym, false); + bool is_found = (res != nullptr); + if (!is_found) { + res = sym.Str(); + Locale::sIgnoreMissingText = sym.Str(); + + if (Locale::GetLocaleVerboseNotify()) { + MILO_NOTIFY("\"%s\" needs localization", sym); + } + } + if (found) { + *found = is_found; + } + + return res; + } +} + +const char *LocalizeFloat(const char *fmt, float num) { + const char *str = MakeString(fmt, num); + static Symbol locale_decimal_separator("locale_decimal_separator"); + const char *sep = TheLocale.Localize(locale_decimal_separator, false); + + if (sep != nullptr && *sep != '.') { + char *dest = gLocaleBuffers[gLocalBufIdx]; + + strncpy(dest, str, 50); + dest[49] = '\0'; + + for (char *ptr = dest; *ptr != '\0'; ++ptr) { + if (*ptr == '.') { + *ptr = *sep; + break; + } + } + + gLocalBufIdx = (gLocalBufIdx + 1) % 4; + + return dest; + } + return str; +} + +const char *Locale::Localize(Symbol sym, bool param_2) const { + if (sym.Str() == gNullStr) { + return ""; + } + MILO_ASSERT(!mSymTable, 0x1d8); + + static Symbol eng("eng"); + + if (mMagnuStrings) { + if (SystemLanguage() == eng) { + DataArray *arr = mMagnuStrings->FindArray(sym, false); + if (arr) { + return arr->Node(1).Str(arr); + } + } + } + { // if we dont scope index it uses 0x54 instead of 0x50 lol + int index; + if (FindDataIndex(sym, index, param_2)) { + return mStrTable[index]; + } + } + + if (UsingCD()) { + SendDebugDataPoint( + "debug/locale/token", "token", sym, "success", false + ); + } + + return nullptr; +} + +bool Locale::FindDataIndex(Symbol sym, int &index, bool fail) const { + int low = 0; + int high = mSize - 1; + + while (high - low >= 0) { + int mid = (low + high) >> 1; + Symbol midSym = mSymTable[mid]; + + if (sym > midSym) { + low = mid + 1; + } else if ((int)sym < (int)midSym) { + high = mid - 1; + } else { + index = mid; + return true; + } + } + + if (fail) { + MILO_FAIL("Couldn't find '%s' in array (file %s)", sym.Str(), mFile.Str()); + } + + return false; +} \ No newline at end of file diff --git a/src/system/utl/Locale.h b/src/system/utl/Locale.h index 137786f9..e03c7c07 100644 --- a/src/system/utl/Locale.h +++ b/src/system/utl/Locale.h @@ -47,15 +47,18 @@ class Locale { void Init(); void Terminate(); - // static const char *sIgnoreMissingText; + static const char *sIgnoreMissingText; void SetMagnuStrings(DataArray *); // bool FindDataIndex(Symbol, int &, bool) const; - // const char *Localize(Symbol, bool) const; + const char *Localize(Symbol, bool) const; static void SetLocaleVerboseNotify(bool set) { Locale::sVerboseNotify = set; } + static bool GetLocaleVerboseNotify() { return sVerboseNotify; } protected: + bool FindDataIndex(Symbol sym, int &index, bool b) const; + static bool sVerboseNotify; }; diff --git a/src/system/world/DefaultPhysicsManager.cpp b/src/system/world/DefaultPhysicsManager.cpp index dea88042..22c82978 100644 --- a/src/system/world/DefaultPhysicsManager.cpp +++ b/src/system/world/DefaultPhysicsManager.cpp @@ -83,9 +83,11 @@ void DefaultPhysicsManager::Poll() { for (auto it = mActiveCollidables.begin(); it != mActiveCollidables.end();) { RndMesh *d = *it; if (!IsShowing(d)) { - mActiveCollidables.erase(it); + auto cur = it; + ++it; + mActiveCollidables.erase(cur); MILO_ASSERT(std::find( mInactiveCollidables.begin(), mInactiveCollidables.end(), d) == mInactiveCollidables.end(), 0x41); - mInactiveCollidables.push_back(d); + mInactiveCollidables.push_front(d); } else { ++it; } @@ -93,9 +95,11 @@ void DefaultPhysicsManager::Poll() { for (auto it = mInactiveCollidables.begin(); it != mInactiveCollidables.end();) { RndMesh *d = *it; if (IsShowing(d)) { - mActiveCollidables.erase(it); + auto cur = it; + ++it; + mInactiveCollidables.erase(cur); MILO_ASSERT(std::find( mActiveCollidables.begin(), mActiveCollidables.end(), d) == mActiveCollidables.end(), 0x55); - mInactiveCollidables.push_back(d); + mActiveCollidables.push_front(d); } else { ++it; } @@ -132,8 +136,18 @@ void DefaultPhysicsManager::CastRays( void DefaultPhysicsManager::ActivateCollidable(Hmx::Object *o) { auto it = std::find(mInactiveCollidables.begin(), mInactiveCollidables.end(), o); if (it != mInactiveCollidables.end()) { + RndMesh *mesh = *it; mInactiveCollidables.erase(it); - mActiveCollidables.push_back(*it); + mActiveCollidables.push_front(mesh); + } +} + +void DefaultPhysicsManager::DeactivateCollidable(Hmx::Object *o) { + auto it = std::find(mInactiveCollidables.begin(), mInactiveCollidables.end(), o); + if (it != mInactiveCollidables.end()) { + RndMesh *mesh = *it; + mActiveCollidables.erase(it); + mInactiveCollidables.push_front(mesh); } } @@ -143,3 +157,38 @@ void DefaultPhysicsManager::RemoveAll() { mInactiveCollidables.clear(); unk40.clear(); } + +void DefaultPhysicsManager::AddCollidable(Hmx::Object *o, ObjectDir *dir, bool isActive) { + RndMesh *mesh = dynamic_cast(o); + if (mesh) { + if (unk54.find(mesh) == unk54.end()) { + unk54[mesh] = dir; + if (isActive) { + mActiveCollidables.push_front(mesh); + } else { + mInactiveCollidables.push_front(mesh); + } + unk40.insert(unk40.begin(), o); + } + } +} + +void DefaultPhysicsManager::RemoveCollidable(Hmx::Object *o) { + auto mapIt = unk54.find(o); + if (mapIt != unk54.end()) { + auto activeIt = + std::find(mActiveCollidables.begin(), mActiveCollidables.end(), o); + + if (activeIt != mActiveCollidables.end()) { + mActiveCollidables.erase(activeIt); + } else { + auto inactiveIt = + std::find(mInactiveCollidables.begin(), mInactiveCollidables.end(), o); + if (inactiveIt != mInactiveCollidables.end()) { + mInactiveCollidables.erase(inactiveIt); + } + } + unk54.erase(mapIt); + unk40.remove(o); + } +} \ No newline at end of file diff --git a/src/system/world/DefaultPhysicsManager.h b/src/system/world/DefaultPhysicsManager.h index eb67fbf2..1797e9b5 100644 --- a/src/system/world/DefaultPhysicsManager.h +++ b/src/system/world/DefaultPhysicsManager.h @@ -25,14 +25,16 @@ class DefaultPhysicsManager : public PhysicsManager { virtual void RemoveCollidable(Hmx::Object *); ObjPtrList unk40; // 0x40 - std::map unk54; // 0x54 + std::map unk54; // 0x54 - mCollidableMap? std::list mActiveCollidables; // 0x6c std::list mInactiveCollidables; // 0x74 }; class RayCastDefaultContainer : public RayCastContainer { public: - RayCastDefaultContainer(const Box &, std::list, std::map &); + RayCastDefaultContainer( + const Box &, std::list, std::map & + ); virtual ~RayCastDefaultContainer() {} virtual Hmx::Object *FindNearest(const Segment &, float &, Vector3 &, Hmx::Object *&); virtual void SetFilter(int);