Skip to content
Merged
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
164 changes: 150 additions & 14 deletions ARCHITECTURE.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ target_sources(
src/plugin-main.cpp
src/source/CreditsSource.cpp
src/source/CreditsSource.hpp
src/ui/CollapsibleGroup.cpp
src/ui/CollapsibleGroup.hpp
src/ui/CsvImportDialog.cpp
src/ui/CsvImportDialog.hpp
src/ui/DesignerDialog.cpp
Expand Down
56 changes: 40 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ fires once the roll clears the screen.
## What it does

Add a **Credits Marquee** source to a scene, open **Credits Designer**, and build the roll
out of sections:
out of sections. The designer asks for a kind of section and then a couple of plain questions
about it — a heading, with a subtitle, with a logo; a list of lines, pairs or images over so many
columns — which between them cover every shape in the table below:

| Section type | What it is |
|---|---|
Expand All @@ -26,8 +28,9 @@ out of sections:
| Multi-List of Text | Names across a configurable number of columns |
| Title and Subtitle Multi-List | The same stacked pairs, across a configurable number of columns |
| Multi-List of Logos | Sponsor logos across a configurable number of columns |
| Section Divider | An ornamental rule between sections, composed from end caps, a rule and a centrepiece |
| Section Divider | An ornamental rule between sections, composed from its two ends, the rule between them, and whatever sits in the middle |
| Spacer | A blank run, for pacing |
| Sticky Ending Block | Sections that hold still on the frame while the rest of the roll scrolls past behind them — a closing card that stays up, and can be the end of the roll |

A **title and subtitle** list is the other way to set what a bridged row sets on one line: the
position on top and the name under it, each with its own font, size, weight, colour and
Expand All @@ -46,13 +49,18 @@ beside the whole pair — centred against both lines together, not just the titl
it, sit against the section edge, or bridge across to it, with the leader running along the
baseline of whichever line ends up on top.

Either side of a bridged row can carry a **subtitle** of its own — a note under the role on the
left, a company under the name on the right — each in a style of its own, and drawn only where you
put something. The leader stays on the top line of the row, so adding one leaves it where it was.

In a bridged row the **bridge** joining the two texts is drawn from artwork rather than from
characters, so a leader is a real shape at a thickness you set instead of whatever full stops
your font happens to draw: pick dots, dashes, diamonds, a line or a double rule, or point it at
an SVG of your own. It picks up the section's own colour, gradient, outline and shadow, so it
belongs to the row rather than sitting on it, and it can be lifted off the baseline to run a
rule through the middle of the text. Plain text is still one of the styles, for when a word —
`and`, `with` — is what belongs in the gap.
`and`, `with` — is what belongs in the gap, and so is nothing at all, for two columns held apart
by a plain gap you set the width of.

Bridged rows are fully placeable on top of that: the bridge can be drawn once, repeated, or
spread to span whatever gap the two texts leave; the columns can be fixed (so the leader starts
Expand All @@ -61,19 +69,21 @@ row can hug either edge or sit centred; and a row with only one side filled in c
leader out to the far edge, for a heading inside an otherwise bridged list.

A **section divider** is the ornamental rule that separates one part of a roll from the next,
and it is *composed* rather than picked from a list of finished pictures: an end cap, a rule
running inward from it, and a centre — then the same again mirrored, so the two ends of a rule
cannot drift apart while you work on it. Each of the three is drawn from a small library of
vector shapes — arrowheads, spearpoints, teardrops, scrolled ends and deco steps for the ends;
plain, double, tapered, dotted, dashed, diamond-chained and ticked rules; diamonds, nested
diamonds, four- and five-point stars, hearts, scrolls, filigree curls and deco interlocks for
the middle — and any of the three can instead be an SVG of your own. Two dozen shapes across
three slots is a great many more dividers than there are shapes.

The middle is a *list* rather than a single choice, because the figures that turn up there are
compounds: a diamond with a dot either side of it, `PART II` between two curls, a monogram
between a pair of scrolls. Pieces can be ornaments, a word set in the section's own font, or an
image, in whatever order you put them; leave the list empty and you get an unbroken rule. Two
and it is *composed* rather than picked from a list of finished pictures: an end, a rule
running inward from it, and a middle — then the same again mirrored, so the two ends of a rule
cannot drift apart while you work on it. The ends and the middle are the same kind of thing and
draw on the same library of vector shapes — arrowheads, spearpoints, teardrops, scrolled ends,
deco steps and chevrons; diamonds, nested diamonds, four- and five-point stars, dots, hearts,
scrolls, filigree curls and deco interlocks — so an arrowhead can break a rule as readily as it
caps one, and any of them can instead be an SVG of your own. The rule between them has a library
of its own: plain, double, tapered, dotted, dashed, diamond-chained and ticked.

Each end, and the middle, is a *list* rather than a single choice, because the figures that turn
up there are compounds: a diamond with a dot either side of it, `PART II` between two curls, a
monogram between a pair of scrolls, `MMXXVI` set against the end of the rule. Pieces can be
ornaments, a word set in the section's own font, or an image, each at a size of its own and in
whatever order you put them; leave a list empty and you get an end with nothing on it, or an
unbroken rule. Two
or three rules can run in parallel with a single ornament breaking all of them, and they can be
tapered so the stack forms a wedge. One thickness sizes the whole thing — every shape knows its
own proportion to the rule it belongs to, so an arrowhead stays an arrowhead when a divider is
Expand Down Expand Up @@ -127,6 +137,20 @@ preview shows the first frame until you press **Play animations**, so the pane h
a roll is being written. Artwork is decoded whole and up front, which puts a ceiling on it: past
30 seconds a logo plays only its first 30, and the designer says so.

A **sticky ending block** is a run of sections that stops scrolling. It travels up the frame like
any other part of the roll, and when it reaches the place you pinned it to, it stays there while
the rest of the credits carries on past behind it. You pick which part of the block is pinned —
its top edge, its middle, its bottom — and where down the frame that lands, so "centred in the
frame" and "top edge a third of the way down" are both one setting rather than a number to work
out. It can hold for a set time or until something else stops the roll, and when the hold ends it
either stays put and ends the roll, carries on up and off the top, or does both at once. Turn on
its panel and the credits running past underneath will not read through its lettering.

It holds whole sections, so a closing card is a title, a divider and a logo the way anything else
is; drag them under the block in the section list and they are inside it. Nothing above or below
moves for it, and you can have as many as you like — the same mechanism gives you a chapter
heading that holds while the section under it scrolls by.

The source properties cover canvas size, background colour, scroll speed, lead-in and
lead-out padding, start behaviour, looping, and the ending action.

Expand Down
84 changes: 78 additions & 6 deletions data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,51 @@ Designer.Fonts.Tip="What this roll does about its fonts on a machine that does n
Designer.Add="Add"
Designer.Duplicate="Duplicate"
Designer.Remove="Remove"
Designer.RemoveSection.Title="Remove Section"
Designer.RemoveSection.Confirm="Remove “%1” from the roll?"
Designer.RemoveSection.DontAsk="Don't ask again while this window is open"
Designer.MoveUp="Move Up"
Designer.MoveDown="Move Down"
Designer.ImportJson="Import JSON..."
Designer.ExportJson="Export JSON..."

Designer.SectionType="Section Type"
Designer.TypeSubtitle="With a subtitle under it"
Designer.TypeSubtitle.Tip="Adds a second line under the heading, styled separately. Leave it empty and nothing is drawn."
Designer.TypeLogo="With a logo beside it"
Designer.TypeLogo.Tip="Puts an image next to the words. Which side it sits on, and how close, are below."
Designer.TypeLogoOnly="A logo instead of words"
Designer.TypeLogoOnly.Tip="For a wordmark used as the heading itself, with no text beside it."
Designer.BaseType.text_list="List"
Designer.ListContent="This List Holds"
Designer.ListContent.Text="One line each"
Designer.ListContent.Pairs="A line and a smaller one under it"
Designer.ListContent.Logos="Images"
Designer.ShowAdvanced="Show every setting"
Designer.ShowAdvanced.Tip="Reveals the settings that are rarely needed — where the section sits on the canvas, the fine spacing of a divider, the ordering of a pair. Nothing is switched off while they are hidden."
Designer.Group.Content="What This Section Says"
Designer.Group.TypeSettings="%1 Settings"
Designer.Group.Placement="Where It Sits"
Designer.TypeHelp.title="The largest heading. One line, on its own."
Designer.TypeHelp.title_with_subtitle="A large heading with a second, smaller line under it."
Designer.TypeHelp.title_with_logo="A large heading with an image beside it."
Designer.TypeHelp.title_with_subtitle_logo="A large heading and its subtitle, with an image beside the pair."
Designer.TypeHelp.logo_title="An image used as the heading itself — a wordmark, with no text."
Designer.TypeHelp.header="A smaller heading, for naming the run of credits under it."
Designer.TypeHelp.header_with_subtitle="A heading with a second, smaller line under it."
Designer.TypeHelp.header_with_logo="A heading with an image beside it."
Designer.TypeHelp.header_with_subtitle_logo="A heading and its subtitle, with an image beside the pair."
Designer.TypeHelp.logo_header="An image used as the heading itself, at a heading's size."
Designer.TypeHelp.bridged="Two columns of text joined across the gap — Director . . . . . . Jane Doe."
Designer.TypeHelp.text_list="A run of single lines, one credit each."
Designer.TypeHelp.title_subtitle_list="A run of pairs: a line with a smaller one under it, such as a role over the name that holds it."
Designer.TypeHelp.logo_list="A run of images, one under the next."
Designer.TypeHelp.multi_text_list="A run of single lines, spread over several columns."
Designer.TypeHelp.multi_title_subtitle_list="A run of pairs, spread over several columns."
Designer.TypeHelp.multi_logo_list="A grid of images — a wall of sponsor marks."
Designer.TypeHelp.section_divider="An ornamental rule, composed from its two ends, the rule between them, and whatever sits in the middle."
Designer.TypeHelp.spacer="A measured run of blank space."
Designer.TypeHelp.sticky_block="Holds the sections inside it still on the frame while the rest of the roll scrolls past behind them — a closing card that stays up, and can be the end of the roll."
Designer.Label="List Label"
Designer.LabelPlaceholder="Optional name shown in the section list"
Designer.Visible="Include this section in the roll"
Expand Down Expand Up @@ -97,6 +136,7 @@ Designer.LogoAnimatedShadow="Shadow follows the animation"
Designer.LogoAnimatedShadow.Tip="Recompute the drop shadow for every frame instead of casting the first frame's. Only worth it for artwork that changes shape as it plays; it costs a blur per frame when the roll is built."
Designer.LogoTruncated="Animated artwork longer than %1 seconds plays only its first %1 seconds."
Designer.BridgeType="Bridge Type"
Designer.BridgeType.none="Nothing — just a gap"
Designer.BridgeType.text="Text you type"
Designer.BridgeType.dots="Dots"
Designer.BridgeType.dashes="Dashes"
Expand All @@ -114,6 +154,8 @@ Designer.BridgeOffset="Bridge Height"
Designer.BridgeOffset.Tip="How far above the text's baseline the artwork sits. At 0 it rests on the baseline, like a run of leader dots."
Designer.BridgeGap="Bridge End Gap"
Designer.BridgeGap.Tip="Space left clear at each end of the artwork, so it does not run into the words it joins."
Designer.BridgeMinGap="Gap Width"
Designer.BridgeMinGap.Tip="The least space kept between the two texts when the bridge draws nothing. Anything the columns leave over past it belongs to the gap as well."
Designer.BridgeTint="Draw the artwork in the text's own colour"
Designer.BridgeFill="Bridge Fill"
Designer.BridgeFill.Fixed="Draw it once, at its own width"
Expand All @@ -126,6 +168,8 @@ Designer.BridgeSplit="Bridge Starts At"
Designer.BridgeSplit.Tip="How much of the width goes to the left-hand text before the bridge begins."
Designer.BridgeRowAlign="Row Placement"
Designer.BridgeSpanEmpty="Run the bridge to the edge when one side is empty"
Designer.RowSubtitles="Give each side a subtitle"
Designer.RowSubtitles.Tip="Adds a second line under each side of every row, from the Left Subtitle and Right Subtitle columns. A row that leaves one empty draws nothing there and takes up no more room for it."
Designer.Columns="Columns"
Designer.ColumnGap="Column Gap"
Designer.FillOrder="Fill Order"
Expand All @@ -138,12 +182,8 @@ Designer.SubtitleOrder="Stacking Order"
Designer.SubtitleOrder.Tip="Which of the two lines is drawn on top. The fields you type into keep their meaning either way."
Designer.SubtitleOrder.TitleFirst="Title above subtitle"
Designer.SubtitleOrder.SubtitleFirst="Subtitle above title"
Designer.DividerCap="End Shape"
Designer.DividerCapSvg="End Artwork"
Designer.DividerMirrorEnds="Draw both ends the same way"
Designer.DividerMirrorEnds.Tip="The right-hand end is the left one flipped over, which is what keeps the two ends of a rule from drifting apart as you work on it. Turn it off to set them separately — for an arrow that flies one way."
Designer.DividerEndCap="Right-Hand End"
Designer.DividerEndCapSvg="Right-Hand End Artwork"
Designer.DividerArm="Rule"
Designer.DividerArmSvg="Rule Artwork"
Designer.DividerThickness="Thickness"
Expand Down Expand Up @@ -183,6 +223,31 @@ Designer.DividerShape.filigree="Filigree curls"
Designer.DividerShape.deco_stack="Deco interlock"
Designer.DividerShape.custom="Your own SVG file"
Designer.SpacerHeight="Spacer Height"
Designer.Seconds=" s"
Designer.StickyAnchor="Pin This Part Of The Block"
Designer.StickyAnchor.Top="Its top edge"
Designer.StickyAnchor.Center="Its middle"
Designer.StickyAnchor.Bottom="Its bottom edge"
Designer.StickyAnchor.Tip="Which part of the block lands on the position below. Its middle at 50% is a block centred in the frame; its top edge at 0% is a block that stops with its first line at the top of the frame."
Designer.StickyCanvasPosition="Down The Frame"
Designer.StickyCanvasPosition.Tip="How far down the frame the pinned part lands — 0% is the top edge, 100% the bottom. A share of the height rather than a pixel count, so the roll still pins where it was meant to if the canvas is resized."
Designer.StickyOffset="Nudge"
Designer.StickyOffset.Tip="Moves the pinned block up or down by a few pixels, for when the share above is nearly right."
Designer.StickyHold="Hold For"
Designer.StickyHold.Tip="How long the block stays pinned before its release takes over. The rest of the roll goes on scrolling behind it the whole time."
Designer.StickyHoldForever="Hold until something else stops the roll"
Designer.StickyHoldForever.Tip="Keeps the block pinned indefinitely — for a card that stays up until a hotkey, a scene change or the stream ending takes it away."
Designer.StickyHoldForever.Warning="This block holds for ever and is set to end the roll when its hold runs out, so the roll never ends on its own and the ending action never fires."
Designer.StickyRelease="When The Hold Ends"
Designer.StickyRelease.EndAtHold="That is the end — stay put and fire the ending action"
Designer.StickyRelease.ResumeThenEnd="Carry on up and off, then end the roll as usual"
Designer.StickyRelease.ResumeEndAtHold="Carry on up and off, but fire the ending action now"
Designer.StickyRelease.Tip="What the block does when its hold runs out, and what counts as the end of the roll. Whichever is chosen, the rest of the roll keeps scrolling behind the block while it is pinned."
Designer.StickyBackdrop="Draw a panel behind the block"
Designer.StickyBackdrop.Tip="Fills the frame behind the block while it is pinned, so the credits still scrolling past underneath do not read through its lettering."
Designer.StickyBackdropColor="Panel Colour"
Designer.StickyBackdropPadding="Panel Padding"
Designer.StickyBackdropPadding.Tip="How far the panel reaches past the block, above and below."
Designer.PaddingTop="Padding Above"
Designer.PaddingBottom="Padding Below"
Designer.MarginX="Side Margins"
Expand All @@ -200,6 +265,8 @@ Designer.StylePreset.NamePrompt="Name this style preset. Sections that follow it
Designer.StylePreset.DeleteConfirm="Delete the style preset '%1'? Sections following it fall back to their own style."
Designer.SecondaryStyle="Separate Style For The Right Column"
Designer.SubtitleStyle="Separate Style For The Subtitle"
Designer.RowSubtitleStyle="Style For The Left Subtitle"
Designer.RowSecondarySubtitleStyle="Style For The Right Subtitle"
Designer.BridgeStyle="Separate Colour For The Bridge"
Designer.DividerArtStyle="Separate Colour For The Artwork"
Designer.BridgeStyle.Tip="Colours the bridge on its own instead of drawing it in the section's text style — yellow dots under white names, or a gradient across a run of diamonds. Only the fill, outline and shadow come from here: the bridge keeps the row's own font and size, so nothing in the row moves when this is switched on."
Expand Down Expand Up @@ -242,13 +309,18 @@ Designer.SetLogo="Set Logo..."
Designer.ImportCsv="Import CSV..."
Designer.Column.Text="Text"
Designer.Column.Left="Left"
Designer.Column.LeftSubtitle="Left Subtitle"
Designer.Column.RightSubtitle="Right Subtitle"
Designer.Column.Right="Right"
Designer.Column.EntryTitle="Title"
Designer.Column.Subtitle="Subtitle"
Designer.Column.Logo="Logo Path"
Designer.Column.Height="Height"
Designer.DividerCentre="Middle Of The Divider"
Designer.DividerCentre.Tip="What sits between the two halves of the rule, in order, left to right. Leave it empty for an unbroken rule. Pieces can be ornaments, a word, or an image — a diamond with a dot either side of it, or MMXXVI between two curls."
Designer.DividerPieces="Parts Of The Divider"
Designer.DividerPieces.Tip="What sits at each end of the rule and in the middle of it, in order, left to right. Every tab holds the same kind of piece — an ornament, a word or an image — so a shape offered at an end is offered in the middle too. Leave a tab empty for an end with nothing on it, or an unbroken rule."
Designer.DividerLeftEnd="Left End"
Designer.DividerRightEnd="Right End"
Designer.DividerCentre="Middle"
Designer.AddPiece="Add"
Designer.RemovePiece="Remove"
Designer.SetPieceFile="Set File..."
Expand Down
14 changes: 13 additions & 1 deletion src/model/BridgeArt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ namespace {
* either side of it.
*/
const BridgeTypeInfo kBridgeTypes[] = {
/*
* Nothing drawn: the row is two texts with a gap between them. Listed first because it is
* the plainest thing the picker can offer, not because it is the fallback -- that is still
* Text, so a document written before this existed keeps the leader it was built against.
*/
{BridgeType::None, "none", "None", "", 0.0, BridgeStretch::Spread},

{BridgeType::Text, "text", "Text", "", 0.0, BridgeStretch::Spread},

{BridgeType::Dots, "dots", "Dots", R"(<circle cx="1" cy="0.5" r="0.5" fill="#ffffff"/>)", 2.0,
Expand Down Expand Up @@ -117,7 +124,12 @@ const QVector<BridgeType> &allBridgeTypes()

bool bridgeTypeUsesArt(BridgeType type)
{
return type != BridgeType::Text;
return type != BridgeType::Text && type != BridgeType::None;
}

bool bridgeTypeIsEmpty(BridgeType type)
{
return type == BridgeType::None;
}

bool bridgeTypeUsesFile(BridgeType type)
Expand Down
Loading
Loading