diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 06fe77588..c7cb36dc6 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -56,18 +56,19 @@ void CMapLayers::EnvelopeUpdate() } } -void CMapLayers::EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Channels, void *pUser) +void CMapLayers::EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Result, size_t Channels, void *pUser) { CMapLayers *pThis = (CMapLayers *)pUser; - Channels = ColorRGBA(); int EnvStart, EnvNum; pThis->m_pLayers->Map()->GetType(MAPITEMTYPE_ENVELOPE, &EnvStart, &EnvNum); - if(Env < 0 || Env >= EnvNum) return; const CMapItemEnvelope *pItem = (CMapItemEnvelope *)pThis->m_pLayers->Map()->GetItem(EnvStart + Env); + if(pItem->m_Channels <= 0) + return; + Channels = minimum(Channels, pItem->m_Channels, CEnvPoint::MAX_CHANNELS); CMapBasedEnvelopePointAccess EnvelopePoints(pThis->m_pLayers->Map()); EnvelopePoints.SetPointsRange(pItem->m_StartPoint, pItem->m_NumPoints); @@ -114,7 +115,7 @@ void CMapLayers::EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Channels MinTick * TickToNanoSeconds; } } - CRenderTools::RenderEvalEnvelope(&EnvelopePoints, 4, s_Time + (int64_t)TimeOffsetMillis * std::chrono::nanoseconds(1ms), Channels); + CRenderTools::RenderEvalEnvelope(&EnvelopePoints, s_Time + (int64_t)TimeOffsetMillis * std::chrono::nanoseconds(1ms), Result, Channels); } else { @@ -139,7 +140,7 @@ void CMapLayers::EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Channels s_Time += CurTime - s_LastLocalTime; s_LastLocalTime = CurTime; } - CRenderTools::RenderEvalEnvelope(&EnvelopePoints, 4, s_Time + std::chrono::nanoseconds(std::chrono::milliseconds(TimeOffsetMillis)), Channels); + CRenderTools::RenderEvalEnvelope(&EnvelopePoints, s_Time + std::chrono::nanoseconds(std::chrono::milliseconds(TimeOffsetMillis)), Result, Channels); } } @@ -901,7 +902,7 @@ void CMapLayers::OnMapLoad() } } -void CMapLayers::RenderTileLayer(int LayerIndex, ColorRGBA &Color, CMapItemLayerTilemap *pTileLayer, CMapItemGroup *pGroup) +void CMapLayers::RenderTileLayer(int LayerIndex, const ColorRGBA &Color, CMapItemLayerTilemap *pTileLayer, CMapItemGroup *pGroup) { STileLayerVisuals &Visuals = *m_vpTileLayerVisuals[LayerIndex]; if(Visuals.m_BufferContainerIndex == -1) @@ -910,12 +911,6 @@ void CMapLayers::RenderTileLayer(int LayerIndex, ColorRGBA &Color, CMapItemLayer float ScreenX0, ScreenY0, ScreenX1, ScreenY1; Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); - ColorRGBA Channels(1.f, 1.f, 1.f, 1.f); - if(pTileLayer->m_ColorEnv >= 0) - { - EnvelopeEval(pTileLayer->m_ColorEnvOffset, pTileLayer->m_ColorEnv, Channels, this); - } - int BorderX0, BorderY0, BorderX1, BorderY1; bool DrawBorder = false; @@ -985,11 +980,6 @@ void CMapLayers::RenderTileLayer(int LayerIndex, ColorRGBA &Color, CMapItemLayer } } - Color.x *= Channels.r; - Color.y *= Channels.g; - Color.z *= Channels.b; - Color.w *= Channels.a; - int DrawCount = s_vpIndexOffsets.size(); if(DrawCount != 0) { @@ -1277,27 +1267,11 @@ void CMapLayers::RenderQuadLayer(int LayerIndex, CMapItemLayerQuads *pQuadLayer, { CQuad *pQuad = &pQuads[i]; - ColorRGBA Color(1.f, 1.f, 1.f, 1.f); - if(pQuad->m_ColorEnv >= 0) - { - EnvelopeEval(pQuad->m_ColorEnvOffset, pQuad->m_ColorEnv, Color, this); - } + ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); + EnvelopeEval(pQuad->m_ColorEnvOffset, pQuad->m_ColorEnv, Color, 4, this); - float OffsetX = 0; - float OffsetY = 0; - float Rot = 0; - - if(pQuad->m_PosEnv >= 0) - { - ColorRGBA Channels; - EnvelopeEval(pQuad->m_PosEnvOffset, pQuad->m_PosEnv, Channels, this); - OffsetX = Channels.r; - OffsetY = Channels.g; - Rot = Channels.b / 180.0f * pi; - } - - const bool IsFullyTransparent = Color.a <= 0; - bool NeedsFlush = QuadsRenderCount == gs_GraphicsMaxQuadsRenderCount || IsFullyTransparent; + const bool IsFullyTransparent = Color.a <= 0.0f; + const bool NeedsFlush = QuadsRenderCount == gs_GraphicsMaxQuadsRenderCount || IsFullyTransparent; if(NeedsFlush) { @@ -1314,11 +1288,14 @@ void CMapLayers::RenderQuadLayer(int LayerIndex, CMapItemLayerQuads *pQuadLayer, if(!IsFullyTransparent) { + ColorRGBA Position = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); + EnvelopeEval(pQuad->m_PosEnvOffset, pQuad->m_PosEnv, Position, 3, this); + SQuadRenderInfo &QInfo = s_vQuadRenderInfo[QuadsRenderCount++]; QInfo.m_Color = Color; - QInfo.m_Offsets.x = OffsetX; - QInfo.m_Offsets.y = OffsetY; - QInfo.m_Rotation = Rot; + QInfo.m_Offsets.x = Position.r; + QInfo.m_Offsets.y = Position.g; + QInfo.m_Rotation = Position.b / 180.0f * pi; } } Graphics()->RenderQuadLayer(Visuals.m_BufferContainerIndex, s_vQuadRenderInfo.data(), QuadsRenderCount, CurQuadOffset); @@ -1638,17 +1615,23 @@ void CMapLayers::OnRender() if(Size >= (size_t)pTMap->m_Width * pTMap->m_Height * sizeof(CTile)) { - ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f); + ColorRGBA Color = IsGameLayer ? ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f) : ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f); if(IsGameLayer && EntityOverlayVal) - Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f); - else if(!IsGameLayer && EntityOverlayVal && !(m_Type == TYPE_BACKGROUND_FORCE)) - Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * (100 - EntityOverlayVal) / 100.0f); + Color.a *= EntityOverlayVal / 100.0f; + else if(!IsGameLayer && EntityOverlayVal && m_Type != TYPE_BACKGROUND_FORCE) + Color.a *= (100 - EntityOverlayVal) / 100.0f; + + if(!IsGameLayer) + { + ColorRGBA ColorEnv = ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); + EnvelopeEval(pTMap->m_ColorEnvOffset, pTMap->m_ColorEnv, ColorEnv, 4, this); + Color = Color.Multiply(ColorEnv); + } + if(!Graphics()->IsTileBufferingEnabled()) { Graphics()->BlendNone(); - RenderTools()->RenderTilemap(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_OPAQUE, - EnvelopeEval, this, pTMap->m_ColorEnv, pTMap->m_ColorEnvOffset); - + RenderTools()->RenderTilemap(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_OPAQUE); Graphics()->BlendNormal(); // draw kill tiles outside the entity clipping rectangle @@ -1657,15 +1640,12 @@ void CMapLayers::OnRender() // slow blinking to hint that it's not a part of the map double Seconds = time_get() / (double)time_freq(); ColorRGBA ColorHint = ColorRGBA(1.0f, 1.0f, 1.0f, 0.3 + 0.7 * (1 + std::sin(2 * (double)pi * Seconds / 3)) / 2); - RenderTools()->RenderTileRectangle(-201, -201, pTMap->m_Width + 402, pTMap->m_Height + 402, 0, TILE_DEATH, // display air inside, death outside - 32.0f, Color.v4() * ColorHint.v4(), TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_TRANSPARENT, - EnvelopeEval, this, pTMap->m_ColorEnv, pTMap->m_ColorEnvOffset); + 32.0f, Color.Multiply(ColorHint), TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_TRANSPARENT); } - RenderTools()->RenderTilemap(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_TRANSPARENT, - EnvelopeEval, this, pTMap->m_ColorEnv, pTMap->m_ColorEnvOffset); + RenderTools()->RenderTilemap(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_TRANSPARENT); } else { @@ -1676,9 +1656,7 @@ void CMapLayers::OnRender() // slow blinking to hint that it's not a part of the map double Seconds = time_get() / (double)time_freq(); ColorRGBA ColorHint = ColorRGBA(1.0f, 1.0f, 1.0f, 0.3 + 0.7 * (1.0 + std::sin(2 * (double)pi * Seconds / 3)) / 2); - - ColorRGBA ColorKill(Color.x * ColorHint.x, Color.y * ColorHint.y, Color.z * ColorHint.z, Color.w * ColorHint.w); - RenderKillTileBorder(TileLayerCounter - 1, ColorKill, pTMap, pGroup); + RenderKillTileBorder(TileLayerCounter - 1, Color.Multiply(ColorHint), pTMap, pGroup); } RenderTileLayer(TileLayerCounter - 1, Color, pTMap, pGroup); } @@ -1732,15 +1710,13 @@ void CMapLayers::OnRender() if(Size >= (size_t)pTMap->m_Width * pTMap->m_Height * sizeof(CTile)) { - ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f); + const ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, EntityOverlayVal / 100.0f); if(!Graphics()->IsTileBufferingEnabled()) { Graphics()->BlendNone(); - RenderTools()->RenderTilemap(pFrontTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_OPAQUE, - EnvelopeEval, this, pTMap->m_ColorEnv, pTMap->m_ColorEnvOffset); + RenderTools()->RenderTilemap(pFrontTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_OPAQUE); Graphics()->BlendNormal(); - RenderTools()->RenderTilemap(pFrontTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_TRANSPARENT, - EnvelopeEval, this, pTMap->m_ColorEnv, pTMap->m_ColorEnvOffset); + RenderTools()->RenderTilemap(pFrontTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND | LAYERRENDERFLAG_TRANSPARENT); } else { @@ -1759,7 +1735,7 @@ void CMapLayers::OnRender() if(Size >= (size_t)pTMap->m_Width * pTMap->m_Height * sizeof(CSwitchTile)) { - ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f); + const ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, EntityOverlayVal / 100.0f); if(!Graphics()->IsTileBufferingEnabled()) { Graphics()->BlendNone(); @@ -1792,7 +1768,7 @@ void CMapLayers::OnRender() if(Size >= (size_t)pTMap->m_Width * pTMap->m_Height * sizeof(CTeleTile)) { - ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f); + const ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, EntityOverlayVal / 100.0f); if(!Graphics()->IsTileBufferingEnabled()) { Graphics()->BlendNone(); @@ -1823,7 +1799,7 @@ void CMapLayers::OnRender() if(Size >= (size_t)pTMap->m_Width * pTMap->m_Height * sizeof(CSpeedupTile)) { - ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f); + const ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, EntityOverlayVal / 100.0f); if(!Graphics()->IsTileBufferingEnabled()) { Graphics()->BlendNone(); @@ -1862,7 +1838,7 @@ void CMapLayers::OnRender() if(Size >= (size_t)pTMap->m_Width * pTMap->m_Height * sizeof(CTuneTile)) { - ColorRGBA Color = ColorRGBA(pTMap->m_Color.r / 255.0f, pTMap->m_Color.g / 255.0f, pTMap->m_Color.b / 255.0f, pTMap->m_Color.a / 255.0f * EntityOverlayVal / 100.0f); + const ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, EntityOverlayVal / 100.0f); if(!Graphics()->IsTileBufferingEnabled()) { Graphics()->BlendNone(); diff --git a/src/game/client/components/maplayers.h b/src/game/client/components/maplayers.h index 6f273976e..7e1d47ce9 100644 --- a/src/game/client/components/maplayers.h +++ b/src/game/client/components/maplayers.h @@ -152,14 +152,14 @@ public: virtual void OnRender() override; virtual void OnMapLoad() override; - void RenderTileLayer(int LayerIndex, ColorRGBA &Color, CMapItemLayerTilemap *pTileLayer, CMapItemGroup *pGroup); + void RenderTileLayer(int LayerIndex, const ColorRGBA &Color, CMapItemLayerTilemap *pTileLayer, CMapItemGroup *pGroup); void RenderTileBorder(int LayerIndex, const ColorRGBA &Color, CMapItemLayerTilemap *pTileLayer, CMapItemGroup *pGroup, int BorderX0, int BorderY0, int BorderX1, int BorderY1); void RenderKillTileBorder(int LayerIndex, const ColorRGBA &Color, CMapItemLayerTilemap *pTileLayer, CMapItemGroup *pGroup); void RenderQuadLayer(int LayerIndex, CMapItemLayerQuads *pQuadLayer, CMapItemGroup *pGroup, bool ForceRender = false); void EnvelopeUpdate(); - static void EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Channels, void *pUser); + static void EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Result, size_t Channels, void *pUser); }; #endif diff --git a/src/game/client/components/mapsounds.cpp b/src/game/client/components/mapsounds.cpp index e72b6c098..dca22a37e 100644 --- a/src/game/client/components/mapsounds.cpp +++ b/src/game/client/components/mapsounds.cpp @@ -209,18 +209,11 @@ void CMapSounds::OnRender() if(!Voice.m_Voice.IsValid()) continue; - float OffsetX = 0, OffsetY = 0; + ColorRGBA Position = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); + CMapLayers::EnvelopeEval(Voice.m_pSource->m_PosEnvOffset, Voice.m_pSource->m_PosEnv, Position, 2, &m_pClient->m_MapLayersBackground); - if(Voice.m_pSource->m_PosEnv >= 0) - { - ColorRGBA Channels; - CMapLayers::EnvelopeEval(Voice.m_pSource->m_PosEnvOffset, Voice.m_pSource->m_PosEnv, Channels, &m_pClient->m_MapLayersBackground); - OffsetX = Channels.r; - OffsetY = Channels.g; - } - - float x = fx2f(Voice.m_pSource->m_Position.x) + OffsetX; - float y = fx2f(Voice.m_pSource->m_Position.y) + OffsetY; + float x = fx2f(Voice.m_pSource->m_Position.x) + Position.r; + float y = fx2f(Voice.m_pSource->m_Position.y) + Position.g; x += Center.x * (1.0f - pGroup->m_ParallaxX / 100.0f); y += Center.y * (1.0f - pGroup->m_ParallaxY / 100.0f); @@ -230,13 +223,11 @@ void CMapSounds::OnRender() Sound()->SetVoiceLocation(Voice.m_Voice, x, y); - if(Voice.m_pSource->m_SoundEnv >= 0) + ColorRGBA Volume = ColorRGBA(1.0f, 0.0f, 0.0f, 0.0f); + CMapLayers::EnvelopeEval(Voice.m_pSource->m_SoundEnvOffset, Voice.m_pSource->m_SoundEnv, Volume, 1, &m_pClient->m_MapLayersBackground); + if(Volume.r < 1.0f) { - ColorRGBA Channels; - CMapLayers::EnvelopeEval(Voice.m_pSource->m_SoundEnvOffset, Voice.m_pSource->m_SoundEnv, Channels, &m_pClient->m_MapLayersBackground); - float Volume = clamp(Channels.r, 0.0f, 1.0f); - - Sound()->SetVoiceVolume(Voice.m_Voice, Volume); + Sound()->SetVoiceVolume(Voice.m_Voice, Volume.r); } } } diff --git a/src/game/client/render.h b/src/game/client/render.h index 60ffc23d3..0bbbbbacb 100644 --- a/src/game/client/render.h +++ b/src/game/client/render.h @@ -117,7 +117,7 @@ public: const CEnvPointBezier *GetBezier(int Index) const override; }; -typedef void (*ENVELOPE_EVAL)(int TimeOffsetMillis, int Env, ColorRGBA &Channels, void *pUser); +typedef void (*ENVELOPE_EVAL)(int TimeOffsetMillis, int Env, ColorRGBA &Result, size_t Channels, void *pUser); class CRenderTools { @@ -162,14 +162,14 @@ public: void RenderTee(const CAnimState *pAnim, const CTeeRenderInfo *pInfo, int Emote, vec2 Dir, vec2 Pos, float Alpha = 1.0f) const; // map render methods (render_map.cpp) - static void RenderEvalEnvelope(const IEnvelopePointAccess *pPoints, int Channels, std::chrono::nanoseconds TimeNanos, ColorRGBA &Result); + static void RenderEvalEnvelope(const IEnvelopePointAccess *pPoints, std::chrono::nanoseconds TimeNanos, ColorRGBA &Result, size_t Channels); void RenderQuads(CQuad *pQuads, int NumQuads, int Flags, ENVELOPE_EVAL pfnEval, void *pUser) const; void ForceRenderQuads(CQuad *pQuads, int NumQuads, int Flags, ENVELOPE_EVAL pfnEval, void *pUser, float Alpha = 1.0f) const; - void RenderTilemap(CTile *pTiles, int w, int h, float Scale, ColorRGBA Color, int RenderFlags, ENVELOPE_EVAL pfnEval, void *pUser, int ColorEnv, int ColorEnvOffset) const; + void RenderTilemap(CTile *pTiles, int w, int h, float Scale, ColorRGBA Color, int RenderFlags) const; // render a rectangle made of IndexIn tiles, over a background made of IndexOut tiles // the rectangle include all tiles in [RectX, RectX+RectW-1] x [RectY, RectY+RectH-1] - void RenderTileRectangle(int RectX, int RectY, int RectW, int RectH, unsigned char IndexIn, unsigned char IndexOut, float Scale, ColorRGBA Color, int RenderFlags, ENVELOPE_EVAL pfnEval, void *pUser, int ColorEnv, int ColorEnvOffset) const; + void RenderTileRectangle(int RectX, int RectY, int RectW, int RectH, unsigned char IndexIn, unsigned char IndexOut, float Scale, ColorRGBA Color, int RenderFlags) const; // helpers void CalcScreenParams(float Aspect, float Zoom, float *pWidth, float *pHeight); diff --git a/src/game/client/render_map.cpp b/src/game/client/render_map.cpp index f7454f5b0..ee3952ca2 100644 --- a/src/game/client/render_map.cpp +++ b/src/game/client/render_map.cpp @@ -237,22 +237,21 @@ static float SolveBezier(float x, float p0, float p1, float p2, float p3) } } -void CRenderTools::RenderEvalEnvelope(const IEnvelopePointAccess *pPoints, int Channels, std::chrono::nanoseconds TimeNanos, ColorRGBA &Result) +void CRenderTools::RenderEvalEnvelope(const IEnvelopePointAccess *pPoints, std::chrono::nanoseconds TimeNanos, ColorRGBA &Result, size_t Channels) { const int NumPoints = pPoints->NumPoints(); if(NumPoints == 0) { - Result = ColorRGBA(); return; } if(NumPoints == 1) { const CEnvPoint *pFirstPoint = pPoints->GetPoint(0); - Result.r = fx2f(pFirstPoint->m_aValues[0]); - Result.g = fx2f(pFirstPoint->m_aValues[1]); - Result.b = fx2f(pFirstPoint->m_aValues[2]); - Result.a = fx2f(pFirstPoint->m_aValues[3]); + for(size_t c = 0; c < Channels; c++) + { + Result[c] = fx2f(pFirstPoint->m_aValues[c]); + } return; } @@ -298,7 +297,7 @@ void CRenderTools::RenderEvalEnvelope(const IEnvelopePointAccess *pPoints, int C const CEnvPointBezier *pNextPointBezier = pPoints->GetBezier(i + 1); if(pCurrentPointBezier == nullptr || pNextPointBezier == nullptr) break; // fallback to linear - for(int c = 0; c < Channels; c++) + for(size_t c = 0; c < Channels; c++) { // monotonic 2d cubic bezier curve const vec2 p0 = vec2(pCurrentPoint->m_Time / 1000.0f, fx2f(pCurrentPoint->m_aValues[c])); @@ -326,7 +325,7 @@ void CRenderTools::RenderEvalEnvelope(const IEnvelopePointAccess *pPoints, int C break; } - for(int c = 0; c < Channels; c++) + for(size_t c = 0; c < Channels; c++) { const float v0 = fx2f(pCurrentPoint->m_aValues[c]); const float v1 = fx2f(pNextPoint->m_aValues[c]); @@ -337,13 +336,13 @@ void CRenderTools::RenderEvalEnvelope(const IEnvelopePointAccess *pPoints, int C } } - Result.r = fx2f(pLastPoint->m_aValues[0]); - Result.g = fx2f(pLastPoint->m_aValues[1]); - Result.b = fx2f(pLastPoint->m_aValues[2]); - Result.a = fx2f(pLastPoint->m_aValues[3]); + for(size_t c = 0; c < Channels; c++) + { + Result[c] = fx2f(pLastPoint->m_aValues[c]); + } } -static void Rotate(CPoint *pCenter, CPoint *pPoint, float Rotation) +static void Rotate(const CPoint *pCenter, CPoint *pPoint, float Rotation) { int x = pPoint->x - pCenter->x; int y = pPoint->y - pCenter->y; @@ -367,13 +366,10 @@ void CRenderTools::ForceRenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags { CQuad *pQuad = &pQuads[i]; - ColorRGBA Color(1.f, 1.f, 1.f, 1.f); - if(pQuad->m_ColorEnv >= 0) - { - pfnEval(pQuad->m_ColorEnvOffset, pQuad->m_ColorEnv, Color, pUser); - } + ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); + pfnEval(pQuad->m_ColorEnvOffset, pQuad->m_ColorEnv, Color, 4, pUser); - if(Color.a <= 0) + if(Color.a <= 0.0f) continue; bool Opaque = false; @@ -392,19 +388,10 @@ void CRenderTools::ForceRenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags fx2f(pQuad->m_aTexcoords[2].x), fx2f(pQuad->m_aTexcoords[2].y), fx2f(pQuad->m_aTexcoords[3].x), fx2f(pQuad->m_aTexcoords[3].y)); - float OffsetX = 0; - float OffsetY = 0; - float Rot = 0; - - // TODO: fix this - if(pQuad->m_PosEnv >= 0) - { - ColorRGBA Channels; - pfnEval(pQuad->m_PosEnvOffset, pQuad->m_PosEnv, Channels, pUser); - OffsetX = Channels.r; - OffsetY = Channels.g; - Rot = Channels.b / 360.0f * pi * 2; - } + ColorRGBA Position = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); + pfnEval(pQuad->m_PosEnvOffset, pQuad->m_PosEnv, Position, 3, pUser); + const vec2 Offset = vec2(Position.r, Position.g); + const float Rotation = Position.b / 180.0f * pi; IGraphics::CColorVertex Array[4] = { IGraphics::CColorVertex(0, pQuad->m_aColors[0].r * Conv * Color.r, pQuad->m_aColors[0].g * Conv * Color.g, pQuad->m_aColors[0].b * Conv * Color.b, pQuad->m_aColors[0].a * Conv * Color.a * Alpha), @@ -415,26 +402,22 @@ void CRenderTools::ForceRenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags CPoint *pPoints = pQuad->m_aPoints; - if(Rot != 0) + CPoint aRotated[4]; + if(Rotation != 0.0f) { - static CPoint aRotated[4]; - aRotated[0] = pQuad->m_aPoints[0]; - aRotated[1] = pQuad->m_aPoints[1]; - aRotated[2] = pQuad->m_aPoints[2]; - aRotated[3] = pQuad->m_aPoints[3]; + for(size_t p = 0; p < std::size(aRotated); ++p) + { + aRotated[p] = pQuad->m_aPoints[p]; + Rotate(&pQuad->m_aPoints[4], &aRotated[p], Rotation); + } pPoints = aRotated; - - Rotate(&pQuad->m_aPoints[4], &aRotated[0], Rot); - Rotate(&pQuad->m_aPoints[4], &aRotated[1], Rot); - Rotate(&pQuad->m_aPoints[4], &aRotated[2], Rot); - Rotate(&pQuad->m_aPoints[4], &aRotated[3], Rot); } IGraphics::CFreeformItem Freeform( - fx2f(pPoints[0].x) + OffsetX, fx2f(pPoints[0].y) + OffsetY, - fx2f(pPoints[1].x) + OffsetX, fx2f(pPoints[1].y) + OffsetY, - fx2f(pPoints[2].x) + OffsetX, fx2f(pPoints[2].y) + OffsetY, - fx2f(pPoints[3].x) + OffsetX, fx2f(pPoints[3].y) + OffsetY); + fx2f(pPoints[0].x) + Offset.x, fx2f(pPoints[0].y) + Offset.y, + fx2f(pPoints[1].x) + Offset.x, fx2f(pPoints[1].y) + Offset.y, + fx2f(pPoints[2].x) + Offset.x, fx2f(pPoints[2].y) + Offset.y, + fx2f(pPoints[3].x) + Offset.x, fx2f(pPoints[3].y) + Offset.y); Graphics()->QuadsDrawFreeform(&Freeform, 1); } Graphics()->TrianglesEnd(); @@ -442,8 +425,7 @@ void CRenderTools::ForceRenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags void CRenderTools::RenderTileRectangle(int RectX, int RectY, int RectW, int RectH, unsigned char IndexIn, unsigned char IndexOut, - float Scale, ColorRGBA Color, int RenderFlags, - ENVELOPE_EVAL pfnEval, void *pUser, int ColorEnv, int ColorEnvOffset) const + float Scale, ColorRGBA Color, int RenderFlags) const { float ScreenX0, ScreenY0, ScreenX1, ScreenY1; Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); @@ -453,17 +435,11 @@ void CRenderTools::RenderTileRectangle(int RectX, int RectY, int RectW, int Rect float FinalTileSize = Scale / (ScreenX1 - ScreenX0) * Graphics()->ScreenWidth(); float FinalTilesetScale = FinalTileSize / TilePixelSize; - ColorRGBA Channels(1.f, 1.f, 1.f, 1.f); - if(ColorEnv >= 0) - { - pfnEval(ColorEnvOffset, ColorEnv, Channels, pUser); - } - if(Graphics()->HasTextureArraysSupport()) Graphics()->QuadsTex3DBegin(); else Graphics()->QuadsBegin(); - Graphics()->SetColor(Color.r * Channels.r, Color.g * Channels.g, Color.b * Channels.b, Color.a * Channels.a); + Graphics()->SetColor(Color); int StartY = (int)(ScreenY0 / Scale) - 1; int StartX = (int)(ScreenX0 / Scale) - 1; @@ -540,8 +516,7 @@ void CRenderTools::RenderTileRectangle(int RectX, int RectY, int RectW, int Rect Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } -void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, ColorRGBA Color, int RenderFlags, - ENVELOPE_EVAL pfnEval, void *pUser, int ColorEnv, int ColorEnvOffset) const +void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, ColorRGBA Color, int RenderFlags) const { float ScreenX0, ScreenY0, ScreenX1, ScreenY1; Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); @@ -551,17 +526,12 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, Color float FinalTileSize = Scale / (ScreenX1 - ScreenX0) * Graphics()->ScreenWidth(); float FinalTilesetScale = FinalTileSize / TilePixelSize; - ColorRGBA Channels(1.f, 1.f, 1.f, 1.f); - if(ColorEnv >= 0) - { - pfnEval(ColorEnvOffset, ColorEnv, Channels, pUser); - } - if(Graphics()->HasTextureArraysSupport()) Graphics()->QuadsTex3DBegin(); else Graphics()->QuadsBegin(); - Graphics()->SetColor(Color.r * Channels.r, Color.g * Channels.g, Color.b * Channels.b, Color.a * Channels.a); + Graphics()->SetColor(Color); + const bool ColorOpaque = Color.a > 254.0f / 255.0f; int StartY = (int)(ScreenY0 / Scale) - 1; int StartX = (int)(ScreenX0 / Scale) - 1; @@ -611,7 +581,7 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, Color unsigned char Flags = pTiles[c].m_Flags; bool Render = false; - if(Flags & TILEFLAG_OPAQUE && Color.a * Channels.a > 254.0f / 255.0f) + if(ColorOpaque && Flags & TILEFLAG_OPAQUE) { if(RenderFlags & LAYERRENDERFLAG_OPAQUE) Render = true; diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 3105223da..1a1f64ac5 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -94,20 +94,17 @@ enum BUTTON_CONTEXT = 1, }; -void CEditor::EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Channels, void *pUser) +void CEditor::EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Result, size_t Channels, void *pUser) { CEditor *pThis = (CEditor *)pUser; if(Env < 0 || Env >= (int)pThis->m_Map.m_vpEnvelopes.size()) - { - Channels = ColorRGBA(); return; - } std::shared_ptr pEnv = pThis->m_Map.m_vpEnvelopes[Env]; - float t = pThis->m_AnimateTime; - t *= pThis->m_AnimateSpeed; - t += (TimeOffsetMillis / 1000.0f); - pEnv->Eval(t, Channels); + float Time = pThis->m_AnimateTime; + Time *= pThis->m_AnimateSpeed; + Time += (TimeOffsetMillis / 1000.0f); + pEnv->Eval(Time, Result, Channels); } /******************************************************** @@ -2791,15 +2788,16 @@ void CEditor::DoQuadEnvelopes(const std::vector &vQuads, IGraphics::CText const CPoint *pPivotPoint = &vQuads[j].m_aPoints[4]; for(size_t i = 0; i < apEnvelope[j]->m_vPoints.size() - 1; i++) { - ColorRGBA Result; - apEnvelope[j]->Eval(apEnvelope[j]->m_vPoints[i].m_Time / 1000.0f + 0.000001f, Result); + ColorRGBA Result = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); + apEnvelope[j]->Eval(apEnvelope[j]->m_vPoints[i].m_Time / 1000.0f + 0.000001f, Result, 2); vec2 Pos0 = vec2(fx2f(pPivotPoint->x) + Result.r, fx2f(pPivotPoint->y) + Result.g); const int Steps = 15; for(int n = 1; n <= Steps; n++) { const float Time = mix(apEnvelope[j]->m_vPoints[i].m_Time, apEnvelope[j]->m_vPoints[i + 1].m_Time, (float)n / Steps); - apEnvelope[j]->Eval(Time / 1000.0f - 0.000001f, Result); + Result = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); + apEnvelope[j]->Eval(Time / 1000.0f - 0.000001f, Result, 2); vec2 Pos1 = vec2(fx2f(pPivotPoint->x) + Result.r, fx2f(pPivotPoint->y) + Result.g); @@ -6445,11 +6443,9 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) { // add point float Time = ScreenToEnvelopeX(View, UI()->MouseX()); - ColorRGBA Channels; + ColorRGBA Channels = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); if(in_range(Time, 0.0f, pEnvelope->EndTime())) - pEnvelope->Eval(Time, Channels); - else - Channels = {0, 0, 0, 0}; + pEnvelope->Eval(Time, Channels, 4); int FixedTime = std::round(Time * 1000.0f); bool TimeFound = false; @@ -6642,12 +6638,13 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) float StepTime = (EndTime - StartTime) / static_cast(Steps); float StepSize = (EndX - StartX) / static_cast(Steps); - ColorRGBA Channels; - pEnvelope->Eval(StartTime + StepTime, Channels); + ColorRGBA Channels = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); + pEnvelope->Eval(StartTime + StepTime, Channels, c + 1); float PrevY = EnvelopeToScreenY(View, Channels[c]); for(int i = 2; i < Steps; i++) { - pEnvelope->Eval(StartTime + i * StepTime, Channels); + Channels = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); + pEnvelope->Eval(StartTime + i * StepTime, Channels, c + 1); float CurrentY = EnvelopeToScreenY(View, Channels[c]); IGraphics::CLineItem LineItem( diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index d88f07ca4..ea66adf53 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -809,7 +809,7 @@ public: int m_ShiftBy; - static void EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Channels, void *pUser); + static void EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Result, size_t Channels, void *pUser); CLineInputBuffered<256> m_SettingsCommandInput; CMapSettingsBackend m_MapSettingsBackend; diff --git a/src/game/editor/mapitems/envelope.cpp b/src/game/editor/mapitems/envelope.cpp index 5f0524eb2..174ee96cc 100644 --- a/src/game/editor/mapitems/envelope.cpp +++ b/src/game/editor/mapitems/envelope.cpp @@ -98,10 +98,10 @@ std::pair CEnvelope::GetValueRange(int ChannelMask) return {Bottom, Top}; } -int CEnvelope::Eval(float Time, ColorRGBA &Color) +void CEnvelope::Eval(float Time, ColorRGBA &Result, size_t Channels) { - CRenderTools::RenderEvalEnvelope(&m_PointsAccess, GetChannels(), std::chrono::nanoseconds((int64_t)((double)Time * (double)std::chrono::nanoseconds(1s).count())), Color); - return GetChannels(); + Channels = minimum(Channels, GetChannels(), CEnvPoint::MAX_CHANNELS); + CRenderTools::RenderEvalEnvelope(&m_PointsAccess, std::chrono::nanoseconds((int64_t)((double)Time * (double)std::chrono::nanoseconds(1s).count())), Result, Channels); } void CEnvelope::AddPoint(int Time, int v0, int v1, int v2, int v3) diff --git a/src/game/editor/mapitems/envelope.h b/src/game/editor/mapitems/envelope.h index 2b25c9f36..b3a00a258 100644 --- a/src/game/editor/mapitems/envelope.h +++ b/src/game/editor/mapitems/envelope.h @@ -21,7 +21,7 @@ public: explicit CEnvelope(int NumChannels); std::pair GetValueRange(int ChannelMask); - int Eval(float Time, ColorRGBA &Color); + void Eval(float Time, ColorRGBA &Result, size_t Channels); void AddPoint(int Time, int v0, int v1 = 0, int v2 = 0, int v3 = 0); float EndTime() const; int GetChannels() const; diff --git a/src/game/editor/mapitems/layer_sounds.cpp b/src/game/editor/mapitems/layer_sounds.cpp index ff8250617..fd3567b33 100644 --- a/src/game/editor/mapitems/layer_sounds.cpp +++ b/src/game/editor/mapitems/layer_sounds.cpp @@ -34,41 +34,31 @@ void CLayerSounds::Render(bool Tileset) Graphics()->SetColor(0.6f, 0.8f, 1.0f, 0.4f); for(const auto &Source : m_vSources) { - float OffsetX = 0; - float OffsetY = 0; - - if(Source.m_PosEnv >= 0) - { - ColorRGBA Channels; - CEditor::EnvelopeEval(Source.m_PosEnvOffset, Source.m_PosEnv, Channels, m_pEditor); - OffsetX = Channels.r; - OffsetY = Channels.g; - } + ColorRGBA Offset = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); + CEditor::EnvelopeEval(Source.m_PosEnvOffset, Source.m_PosEnv, Offset, 2, m_pEditor); + const vec2 Position = vec2(fx2f(Source.m_Position.x) + Offset.r, fx2f(Source.m_Position.y) + Offset.g); + const float Falloff = Source.m_Falloff / 255.0f; switch(Source.m_Shape.m_Type) { case CSoundShape::SHAPE_CIRCLE: { - m_pEditor->Graphics()->DrawCircle(fx2f(Source.m_Position.x) + OffsetX, fx2f(Source.m_Position.y) + OffsetY, - Source.m_Shape.m_Circle.m_Radius, 32); - - float Falloff = ((float)Source.m_Falloff / 255.0f); + m_pEditor->Graphics()->DrawCircle(Position.x, Position.y, Source.m_Shape.m_Circle.m_Radius, 32); if(Falloff > 0.0f) - m_pEditor->Graphics()->DrawCircle(fx2f(Source.m_Position.x) + OffsetX, fx2f(Source.m_Position.y) + OffsetY, - Source.m_Shape.m_Circle.m_Radius * Falloff, 32); + { + m_pEditor->Graphics()->DrawCircle(Position.x, Position.y, Source.m_Shape.m_Circle.m_Radius * Falloff, 32); + } break; } case CSoundShape::SHAPE_RECTANGLE: { - float Width = fx2f(Source.m_Shape.m_Rectangle.m_Width); - float Height = fx2f(Source.m_Shape.m_Rectangle.m_Height); - m_pEditor->Graphics()->DrawRectExt(fx2f(Source.m_Position.x) + OffsetX - Width / 2, fx2f(Source.m_Position.y) + OffsetY - Height / 2, - Width, Height, 0.0f, IGraphics::CORNER_NONE); - - float Falloff = ((float)Source.m_Falloff / 255.0f); + const float Width = fx2f(Source.m_Shape.m_Rectangle.m_Width); + const float Height = fx2f(Source.m_Shape.m_Rectangle.m_Height); + m_pEditor->Graphics()->DrawRectExt(Position.x - Width / 2, Position.y - Height / 2, Width, Height, 0.0f, IGraphics::CORNER_NONE); if(Falloff > 0.0f) - m_pEditor->Graphics()->DrawRectExt(fx2f(Source.m_Position.x) + OffsetX - Falloff * Width / 2, fx2f(Source.m_Position.y) + OffsetY - Falloff * Height / 2, - Width * Falloff, Height * Falloff, 0.0f, IGraphics::CORNER_NONE); + { + m_pEditor->Graphics()->DrawRectExt(Position.x - Falloff * Width / 2, Position.y - Falloff * Height / 2, Width * Falloff, Height * Falloff, 0.0f, IGraphics::CORNER_NONE); + } break; } } @@ -84,18 +74,10 @@ void CLayerSounds::Render(bool Tileset) m_pEditor->RenderTools()->SelectSprite(SPRITE_AUDIO_SOURCE); for(const auto &Source : m_vSources) { - float OffsetX = 0; - float OffsetY = 0; - - if(Source.m_PosEnv >= 0) - { - ColorRGBA Channels; - CEditor::EnvelopeEval(Source.m_PosEnvOffset, Source.m_PosEnv, Channels, m_pEditor); - OffsetX = Channels.r; - OffsetY = Channels.g; - } - - m_pEditor->RenderTools()->DrawSprite(fx2f(Source.m_Position.x) + OffsetX, fx2f(Source.m_Position.y) + OffsetY, m_pEditor->MapView()->ScaleLength(s_SourceVisualSize)); + ColorRGBA Offset = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); + CEditor::EnvelopeEval(Source.m_PosEnvOffset, Source.m_PosEnv, Offset, 2, m_pEditor); + const vec2 Position = vec2(fx2f(Source.m_Position.x) + Offset.r, fx2f(Source.m_Position.y) + Offset.g); + m_pEditor->RenderTools()->DrawSprite(Position.x, Position.y, m_pEditor->MapView()->ScaleLength(s_SourceVisualSize)); } Graphics()->QuadsEnd(); diff --git a/src/game/editor/mapitems/layer_tiles.cpp b/src/game/editor/mapitems/layer_tiles.cpp index ba51d29ae..6cf910c8b 100644 --- a/src/game/editor/mapitems/layer_tiles.cpp +++ b/src/game/editor/mapitems/layer_tiles.cpp @@ -146,13 +146,14 @@ void CLayerTiles::Render(bool Tileset) Texture = m_pEditor->GetTuneTexture(); Graphics()->TextureSet(Texture); - ColorRGBA Color = ColorRGBA(m_Color.r / 255.0f, m_Color.g / 255.0f, m_Color.b / 255.0f, m_Color.a / 255.0f); + ColorRGBA ColorEnv = ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); + CEditor::EnvelopeEval(m_ColorEnvOffset, m_ColorEnv, ColorEnv, 4, m_pEditor); + const ColorRGBA Color = ColorRGBA(m_Color.r / 255.0f, m_Color.g / 255.0f, m_Color.b / 255.0f, m_Color.a / 255.0f).Multiply(ColorEnv); + Graphics()->BlendNone(); - m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_OPAQUE, - CEditor::EnvelopeEval, m_pEditor, m_ColorEnv, m_ColorEnvOffset); + m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_OPAQUE); Graphics()->BlendNormal(); - m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_TRANSPARENT, - CEditor::EnvelopeEval, m_pEditor, m_ColorEnv, m_ColorEnvOffset); + m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_TRANSPARENT); // Render DDRace Layers if(!Tileset) diff --git a/src/game/editor/mapitems/map_io.cpp b/src/game/editor/mapitems/map_io.cpp index a5bc4e659..fa3c71dad 100644 --- a/src/game/editor/mapitems/map_io.cpp +++ b/src/game/editor/mapitems/map_io.cpp @@ -916,7 +916,20 @@ bool CEditorMap::Load(const char *pFileName, int StorageType, const std::functio for(int e = 0; e < EnvNum; e++) { CMapItemEnvelope *pItem = (CMapItemEnvelope *)DataFile.GetItem(EnvStart + e); - std::shared_ptr pEnv = std::make_shared(pItem->m_Channels); + int Channels = pItem->m_Channels; + if(Channels <= 0 || Channels == 2 || Channels > CEnvPoint::MAX_CHANNELS) + { + // Fall back to showing all channels if the number of channels is unsupported + Channels = CEnvPoint::MAX_CHANNELS; + } + if(Channels != pItem->m_Channels) + { + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), "Error: Envelope %d had an invalid number of channels, %d, which was changed to %d.", e, pItem->m_Channels, Channels); + ErrorHandler(aBuf); + } + + std::shared_ptr pEnv = std::make_shared(Channels); pEnv->m_vPoints.resize(pItem->m_NumPoints); for(int p = 0; p < pItem->m_NumPoints; p++) { diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index eebdf52a6..80c36a53a 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -1610,8 +1610,8 @@ CUI::EPopupMenuFunctionResult CEditor::PopupEnvPointCurveType(void *pContext, CU if(SelectedIndex != FirstSelectedIndex && SelectedIndex != LastSelectedIndex) { CEnvPoint &CurrentPoint = pEnvelope->m_vPoints[SelectedIndex]; - ColorRGBA Channels; - HelperEnvelope.Eval(CurrentPoint.m_Time / 1000.0f, Channels); + ColorRGBA Channels = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); + HelperEnvelope.Eval(CurrentPoint.m_Time / 1000.0f, Channels, 1); int PrevValue = CurrentPoint.m_aValues[c]; CurrentPoint.m_aValues[c] = f2fx(Channels.r); vpActions.push_back(std::make_shared(pEditor, pEditor->m_SelectedEnvelope, SelectedIndex, SelectedChannel, CEditorActionEnvelopeEditPoint::EEditType::VALUE, PrevValue, CurrentPoint.m_aValues[c]));