1#include "envelope_state.h"
2
3#include <game/client/gameclient.h>
4#include <game/localization.h>
5
6#include <chrono>
7
8using namespace std::chrono_literals;
9
10CEnvelopeState::CEnvelopeState(IMap *pMap, bool OnlineOnly) :
11 m_pMap(pMap)
12{
13 m_pEnvelopePoints = std::make_shared<CMapBasedEnvelopePointAccess>(args&: m_pMap);
14 m_OnlineOnly = OnlineOnly;
15}
16
17void CEnvelopeState::EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Result, size_t Channels)
18{
19 using namespace std::chrono;
20
21 if(!m_pMap)
22 return;
23
24 int EnvStart, EnvNum;
25 m_pMap->GetType(Type: MAPITEMTYPE_ENVELOPE, pStart: &EnvStart, pNum: &EnvNum);
26 if(Env < 0 || Env >= EnvNum)
27 return;
28
29 const CMapItemEnvelope *pItem = (CMapItemEnvelope *)m_pMap->GetItem(Index: EnvStart + Env);
30 if(pItem->m_Channels <= 0)
31 return;
32 Channels = minimum<size_t>(a: Channels, b: pItem->m_Channels, c: CEnvPoint::MAX_CHANNELS);
33
34 m_pEnvelopePoints->SetPointsRange(StartPoint: pItem->m_StartPoint, NumPoints: pItem->m_NumPoints);
35 if(m_pEnvelopePoints->NumPoints() == 0)
36 return;
37
38 nanoseconds Time;
39
40 // offline rendering (like menu background) relies on local time
41 if(!m_OnlineOnly)
42 {
43 Time = time_get_nanoseconds();
44 }
45 else
46 {
47 // online rendering
48 if(GameClient()->m_Snap.m_pGameInfoObj)
49 {
50 static const nanoseconds s_NanosPerTick = nanoseconds(1s) / static_cast<int64_t>(Client()->GameTickSpeed());
51
52 // get the lerp of the current tick and prev
53 const int MinTick = Client()->PrevGameTick(Conn: g_Config.m_ClDummy) - GameClient()->m_Snap.m_pGameInfoObj->m_RoundStartTick;
54 const int CurTick = Client()->GameTick(Conn: g_Config.m_ClDummy) - GameClient()->m_Snap.m_pGameInfoObj->m_RoundStartTick;
55
56 double TickRatio = mix<double>(a: 0, b: CurTick - MinTick, amount: (double)Client()->IntraGameTick(Conn: g_Config.m_ClDummy));
57 Time = duration_cast<nanoseconds>(d: TickRatio * s_NanosPerTick) + MinTick * s_NanosPerTick;
58 }
59 else
60 {
61 Time = nanoseconds::zero();
62 }
63 }
64
65 CRenderMap::RenderEvalEnvelope(pPoints: m_pEnvelopePoints.get(), TimeNanos: Time + milliseconds(TimeOffsetMillis), Result, Channels);
66}
67