Skip to content

WIP: Enable drawing of dialogue text over audio display #333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 55 additions & 28 deletions src/audio_display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -911,34 +911,61 @@ void AudioDisplay::PaintFoot(wxDC &dc, int marker_x, int dir)

void AudioDisplay::PaintLabels(wxDC &dc, TimeRange updtime)
{
std::vector<AudioLabelProvider::AudioLabel> labels;
controller->GetTimingController()->GetLabels(updtime, labels);
if (labels.empty()) return;

wxDCFontChanger fc(dc);
wxFont font = dc.GetFont();
font.SetWeight(wxFONTWEIGHT_BOLD);
fc.Set(font);
dc.SetTextForeground(*wxWHITE);
for (auto const& label : labels)
{
wxSize extent = dc.GetTextExtent(label.text);
int left = RelativeXFromTime(label.range.begin());
int width = AbsoluteXFromTime(label.range.length());

// If it doesn't fit, truncate
if (width < extent.GetWidth())
{
dc.SetClippingRegion(left, audio_top + 4, width, extent.GetHeight());
dc.DrawText(label.text, left, audio_top + 4);
dc.DestroyClippingRegion();
}
// Otherwise center in the range
else
{
dc.DrawText(label.text, left + (width - extent.GetWidth()) / 2, audio_top + 4);
}
}
std::vector<AudioLabelProvider::AudioLabel> labels;
controller->GetTimingController()->GetLabels(updtime, labels);
if (labels.empty()) return;

wxDCFontChanger fc(dc);
wxFont font = dc.GetFont();
font.SetWeight(wxFONTWEIGHT_BOLD);
fc.Set(font);
dc.SetTextForeground(*wxWHITE);

for (auto const& label : labels)
{
wxString text = label.text;
wxArrayString lines;

// Split the text into lines based on \n and \N
wxString current_line;
for (size_t i = 0; i < text.length(); ++i) {
if (text[i] == '\\' && (i + 1 < text.length()) && (text[i + 1] == 'n' || text[i + 1] == 'N')) {
lines.Add(current_line);
current_line.Clear();
i++; // Skip the 'n' or 'N'
} else {
current_line += text[i];
}
}
lines.Add(current_line);

int left = RelativeXFromTime(label.range.begin());
int width = AbsoluteXFromTime(label.range.length());
int current_y = audio_top + 4;
int line_height = dc.GetTextExtent("A").GetHeight(); // Approximate line height

for (size_t i = 0; i < lines.Count(); ++i) {
wxString line = lines[i];
wxSize line_extent = dc.GetTextExtent(line);

// Truncate if it doesn't fit
if (width < line_extent.GetWidth())
{
wxString truncated_line = line;
while (width < dc.GetTextExtent(truncated_line + "...").GetWidth() && truncated_line.length() > 0) {
truncated_line = truncated_line.Left(truncated_line.length() - 1);
}
truncated_line += "...";
dc.DrawText(truncated_line, left, current_y);
}
else
{
// Center the line
dc.DrawText(line, left + (width - line_extent.GetWidth()) / 2, current_y);
}
current_y += line_height;
}
}
}

void AudioDisplay::PaintTrackCursor(wxDC &dc) {
Expand Down
41 changes: 40 additions & 1 deletion src/audio_timing_dialogue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ class AudioTimingControllerDialogue final : public AudioTimingController {
/// All audio markers for active and inactive lines, sorted by position
std::vector<DialogueTimingMarker*> markers;

// All audio labels for active and inactive lines
std::vector<AudioLabel> labels;

/// Marker provider for video keyframes
AudioMarkerProviderKeyframes keyframes_provider;

Expand Down Expand Up @@ -389,7 +392,7 @@ class AudioTimingControllerDialogue final : public AudioTimingController {

// AudioTimingController interface
void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const override;
void GetLabels(TimeRange const& range, std::vector<AudioLabel> &out) const override { }
void GetLabels(TimeRange const& range, std::vector<AudioLabel>& out) const override;
void Next(NextMode mode) override;
void Prev() override;
void Revert() override;
Expand Down Expand Up @@ -471,6 +474,42 @@ void AudioTimingControllerDialogue::GetRenderingStyles(AudioRenderingStyleRanges
line.GetStyleRange(&ranges);
}

void AudioTimingControllerDialogue::GetLabels(TimeRange const& range, std::vector<AudioLabel>& out) const {
// Add label for the active line
AssDialogue* activeLine = context->selectionController->GetActiveLine();
if (activeLine && !activeLine->Comment) {
TimeRange lineRange(activeLine->Start, activeLine->End);
if (range.overlaps(lineRange)) {
AudioLabel activeLabel{activeLine->GetStrippedText().c_str(), lineRange};
out.push_back(activeLabel);
}
}

// Add labels for selected lines
for (auto& line : selected_lines) {
AssDialogue* selectedLine = line.GetLine();
if (selectedLine && !selectedLine->Comment) {
TimeRange lineRange(selectedLine->Start, selectedLine->End);
if (range.overlaps(lineRange)) {
AudioLabel selectedLabel{selectedLine->GetStrippedText().c_str(), lineRange};
out.push_back(selectedLabel);
}
}
}

// Add labels for inactive lines
for (auto& line : inactive_lines) {
AssDialogue* inactiveLine = line.GetLine();
if (inactiveLine && !inactiveLine->Comment) {
TimeRange lineRange(inactiveLine->Start, inactiveLine->End);
if (range.overlaps(lineRange)) {
AudioLabel inactiveLabel{inactiveLine->GetStrippedText().c_str(), lineRange};
out.push_back(inactiveLabel);
}
}
}
}

void AudioTimingControllerDialogue::Next(NextMode mode)
{
if (mode == TIMING_UNIT)
Expand Down