Skip to content

Commit b74e65a

Browse files
Add ghost
Signed-off-by: Éloïse Brosseau <[email protected]>
1 parent 71a8e9a commit b74e65a

File tree

3 files changed

+44
-22
lines changed

3 files changed

+44
-22
lines changed

src/lib/ip/IPBaseNodes/PaintIPNode.cpp

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,35 @@ namespace
1616
{
1717
using namespace IPCore;
1818

19-
float getGhostFactor(const int level, const int maxLevel)
19+
// Calculates the opacity based on the distance from the annotated frame to
20+
// make the ghosted annotation more visible closer to the frame and less
21+
// visible further away
22+
float getGhostOpacity(const int frame, const int startFrame,
23+
const int duration)
2024
{
21-
constexpr float maxFactor = 0.5;
22-
constexpr float minFactor = 0.1;
23-
constexpr float factorRange = maxFactor - minFactor;
24-
float visibility = 1.0;
25+
constexpr float minOpacity = 0.075;
26+
float ghostOpacity = 0.0;
2527

26-
if (level > 1 && maxLevel > 1)
28+
if (frame > startFrame) // Command starts before the current frame
29+
// (ghostBefore)
2730
{
28-
visibility = 1.0f
29-
- (static_cast<float>(level - 1)
30-
/ static_cast<float>(maxLevel - 1));
31+
ghostOpacity = static_cast<float>(duration)
32+
/ static_cast<float>(frame - startFrame)
33+
+ minOpacity;
34+
}
35+
else // Command starts after the current frame (ghostAfter)
36+
{
37+
ghostOpacity = static_cast<float>(duration)
38+
/ static_cast<float>(startFrame - frame)
39+
+ minOpacity;
3140
}
3241

33-
return minFactor + (visibility * factorRange);
42+
return ghostOpacity;
3443
}
3544

3645
PaintIPNode::LocalCommands
3746
generateVisibleCommands(const PaintIPNode::LocalCommands& commands,
38-
const int frame, const int eye)
47+
const int frame, const size_t eye)
3948
{
4049
PaintIPNode::LocalCommands
4150
allCommands; // visible commands, including hold and ghost
@@ -49,12 +58,13 @@ namespace
4958

5059
for (auto* localCommand : commands)
5160
{
61+
// Skip invisible annotations
5262
if (localCommand->eye != 2 && localCommand->eye != eye)
5363
{
5464
continue;
5565
}
5666

57-
// Don't add polyLines with 0 points
67+
// Don't add polylines with 0 points
5868
if (auto* localPolyLine =
5969
dynamic_cast<PaintIPNode::LocalPolyLine*>(localCommand))
6070
{
@@ -67,7 +77,8 @@ namespace
6777
const int startFrame = localCommand->startFrame;
6878
const int endFrame = startFrame + localCommand->duration - 1;
6979

70-
if (frame >= startFrame && frame <= endFrame) // Command is visible
80+
if (frame >= startFrame
81+
&& frame <= endFrame) // Command is visible on the current frame
7182
{
7283
CurrentFrameCommands.push_back(localCommand);
7384
}
@@ -90,19 +101,19 @@ namespace
90101

91102
{
92103
int levelIndex = 1;
93-
bool firstLevelContainsHoldeldCommands = false;
104+
bool isHoldedCommandsInFirstLevel = false;
94105

95106
for (const auto& beforeCommand : beforeCommands)
96107
{
97108
int ghostLevel =
98-
levelIndex - (firstLevelContainsHoldeldCommands ? 1 : 0);
109+
levelIndex - (isHoldedCommandsInFirstLevel ? 1 : 0);
99110

100111
for (auto* command : beforeCommand.second)
101112
{
102113
if (levelIndex == 1 && noCurrentFrameCommands
103114
&& command->hold != 0)
104115
{
105-
firstLevelContainsHoldeldCommands = true;
116+
isHoldedCommandsInFirstLevel = true;
106117
command->ghostOn = true;
107118

108119
if (auto* polyLine =
@@ -127,8 +138,8 @@ namespace
127138
command->ghostColor = PaintIPNode::Color(
128139
1.0, 0.0, 0.0, 1.0); // Ghosted "Before" commands
129140
// are drawn in green
130-
command->ghostColor[3] *=
131-
getGhostFactor(ghostLevel, command->ghostBefore);
141+
command->ghostColor[3] = getGhostOpacity(
142+
frame, command->startFrame, command->duration);
132143
allCommands.push_back(command);
133144
}
134145
}
@@ -150,8 +161,8 @@ namespace
150161
command->ghostColor = PaintIPNode::Color(
151162
0.0, 1.0, 0.0,
152163
1.0); // Ghosted "After" commands are drawn in red
153-
command->ghostColor[3] *=
154-
getGhostFactor(levelIndex, command->ghostAfter);
164+
command->ghostColor[3] = getGhostOpacity(
165+
frame, command->startFrame, command->duration);
155166
allCommands.push_back(command);
156167
}
157168
}
@@ -692,12 +703,16 @@ namespace IPCore
692703
if (auto* polyLine = dynamic_cast<PaintIPNode::LocalPolyLine*>(
693704
visibleCommand))
694705
{
706+
polyLine->ghostOn = visibleCommand->ghostOn;
707+
polyLine->ghostColor = visibleCommand->ghostColor;
695708
head->commands.push_back(polyLine);
696709
}
697710
else if (auto* localText =
698711
dynamic_cast<PaintIPNode::LocalText*>(
699712
visibleCommand))
700713
{
714+
localText->ghostOn = visibleCommand->ghostOn;
715+
localText->ghostColor = visibleCommand->ghostColor;
701716
head->commands.push_back(localText);
702717
}
703718
}

src/lib/ip/IPCore/PaintCommand.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// SPDX-License-Identifier: Apache-2.0
66
//
77
//
8+
#include "IPBaseNodes/PaintIPNode.h"
89
#include <IPCore/PaintCommand.h>
910
#include <TwkMath/Function.h>
1011
#include <TwkGLF/GL.h>
@@ -378,6 +379,12 @@ namespace IPCore
378379

379380
// set uniforms
380381
Color pcolor = color;
382+
const auto* localCommand =
383+
dynamic_cast<const PaintIPNode::LocalCommand*>(this);
384+
bool isGhostOn =
385+
(localCommand != nullptr) ? localCommand->ghostOn : false;
386+
pcolor = isGhostOn ? localCommand->ghostColor : color;
387+
381388
glPipeline->setUniformFloat("uniformColor", 4, &(pcolor[0]));
382389
float coffset[2] = {50, 50};
383390
if (mode == CloneMode)

src/plugins/rv-packages/otio_reader/annotation_hook.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ def hook_function(
9191
"duration": duration,
9292
"hold": is_hold,
9393
"ghost": is_ghost,
94-
"ghostBefore": 3,
95-
"ghostAfter": 3,
94+
"ghostBefore": 5,
95+
"ghostAfter": 5,
9696
},
9797
)
9898

0 commit comments

Comments
 (0)