storybrew

repository·master·Indexed 41 days ago

https://github.com/damnae/storybrew

An osu! storyboard editor that provides real-time visual feedback by automatically updating the view when code or sprite textures are saved. It includes a comprehensive command system for animating storyboard elements, featuring commands for color (C), fading (F), movement (M, MX, MY), rotation (R), scaling (S, V), parameters (P), loops (L), and triggers (T).

Tokens
4.2K
Snippets
19
Records
21
Agent score
52%

What's inside storybrew

  1. Overview of storybrew

    master
    storybrew is an editor for osu! storyboards designed to provide a real-time feedback loop. Unlike traditional editors that require manual reloading (typically via the Ctrl-L shortcut), storybrew automatically detects and displays changes to code or sprite textures as soon as they are saved.
  2. Understand the Command abstraction for storyboarding

    master

    In Storybrew, a Command<TValue> represents a time-based transition or state change within an osu! storyboard. Commands are defined by a start time, an end time, an easing function, and a transition between a StartValue and an EndValue.

    Key Properties

    • Identifier: A unique string identifying the type of command (e.g., for specific OSB command types).
    • Easing: An OsbEasing value determining how the transition progresses over time.
    • StartTime / EndTime: The temporal bounds of the command.
    • StartValue / EndValue: The values at the beginning and end of the command, where TValue must implement CommandValue.
    • Duration: Calculated as EndTime - StartTime.
    • MaintainValue: A boolean determining if the value should persist after the command ends. If true, the value at EndTime is held; if false, it returns default.
    • ExportEndValue: A boolean determining if the end value should be explicitly written to the OSB file.

    Core Methods

    • ValueAtTime(double time): Calculates the interpolated value at a specific timestamp, accounting for easing and the MaintainValue logic.
    • Offset(double offset): Shifts both StartTime and EndTime by the specified amount.
    • ToOsbString(...): Generates the comma-separated string format required for .osb files.
    • WriteOsb(...): Writes the command's OSB string to a TextWriter with specified indentation.
    // Example conceptual usage of a Command's properties
    // Note: Command is abstract; implementation would be a specific type like PositionCommand
    command.StartTime = 1000.0;
    command.EndTime = 2000.0;
    command.Easing = OsbEasing.Linear;
    command.StartValue = new PositionValue(0, 0);
    command.EndValue = new PositionValue(100, 100);
    
    double valueAtMidpoint = command.ValueAtTime(1500.0);
    command.Offset(500.0); // Moves command to 1500.0 - 2500.0
  3. How CommandGroup works to group storyboard commands

    master

    A CommandGroup is an abstract container used to group multiple ICommand objects together. It acts as a single logical unit that tracks the collective timing and cost of its constituent commands.

    Key behaviors:

    • Timing: The group automatically calculates its CommandsStartTime, CommandsEndTime, and CommandsDuration based on the minimum and maximum timestamps of the commands it contains.
    • Cost: The total Cost of the group is the sum of the costs of all individual commands within it.
    • Lifecycle: Commands are added using the Add(ICommand command) method. Once EndGroup() is called, the group is marked as ended, and no further commands can be added.
    • Serialization: When calling WriteOsb, the group writes a header (defined by its implementation) and then recursively writes each command with increased indentation to maintain the hierarchy in the .osb file.
    // Conceptual usage of a CommandGroup implementation
    var group = new MyCustomCommandGroup();
    group.Add(new MoveCommand(startTime: 1.0, endTime: 2.0));
    group.Add(new FadeCommand(startTime: 1.5, endTime: 2.5));
    group.EndGroup();
    
    // The group now represents the span from 1.0 to 2.5
    Console.WriteLine($"Group Duration: {group.CommandsDuration}");
  4. Structure of a Storyboard Command

    master

    In Storybrew, a command represents an action or an element within a storyboard. Commands are defined by their temporal range (StartTime and EndTime) and a Cost value. Commands can be fragmented at specific points in time using IsFragmentableAt(double time), which is useful for splitting operations that span across different time segments. Commands are serialized to the .osb format via the WriteOsb method, which respects ExportSettings, StoryboardTransform, and indentation levels.

    // Conceptual representation of an ICommand implementation
    public interface ICommand : IComparable<ICommand>
    {
        double StartTime { get; }
        double EndTime { get; }
        int Cost { get; }
    
        bool IsFragmentableAt(double time);
        void WriteOsb(TextWriter writer, ExportSettings exportSettings, StoryboardTransform transform, int indentation);
    }
  5. Use CommandGroup to manage command collections

    master

    To build a collection of storyboard commands that behave as a single unit, inherit from CommandGroup and use the following methods:

    • Add(ICommand command): Adds a command to the group. Throws InvalidOperationException if called after EndGroup().
    • EndGroup(): Finalizes the group, preventing further additions.
    • WriteOsb(TextWriter writer, ExportSettings exportSettings, StoryboardTransform transform, int indentation): Writes the group and its children to an .osb file format.
    • IsFragmentableAt(double time): An abstract method that must be implemented to determine if the group can be split at a specific timestamp.
  6. Move an element along the X axis with MoveXCommand

    master

    The MoveXCommand is used to animate an element's position along the X axis over a specified time interval. It uses an easing function to interpolate between a startValue and an endValue (both of type CommandDecimal).

    Constructor Parameters

    • easing: An OsbEasing value defining the interpolation curve.
    • startTime: The timestamp when the movement begins.
    • endTime: The timestamp when the movement ends.
    • startValue: The initial X position (CommandDecimal).
    • endValue: The final X position (CommandDecimal).

    Key Methods

    • ValueAtProgress(double progress): Calculates the X position at a specific point in the command's lifecycle (where progress is 0.0 to 1.0).
    • GetTransformedStartValue(StoryboardTransform transform): Returns the start value after applying a spatial transformation.
    • GetTransformedEndValue(StoryboardTransform transform): Returns the end value after applying a spatial transformation.
    // Example instantiation of a MoveXCommand
    // Moving from X=100 to X=500 using Linear easing over 2 seconds
    var moveX = new MoveXCommand(
        OsbEasing.Linear, 
        0.0, 
        2.0, 
        new CommandDecimal(100.0), 
        new CommandDecimal(500.0)
    );
  7. Use the VScaleCommand for vertical scaling

    master

    The VScaleCommand is used to scale elements vertically within an osu! storyboard. It is identified by the short command V. This command operates on CommandScale values, allowing for interpolation of scale over a specified time range with an easing function.

    // Conceptual usage of VScaleCommand
    // Identifier: "V"
    // Parameters: OsbEasing, startTime, endTime, startValue (CommandScale), endValue (CommandScale)
    
    var vScale = new VScaleCommand(
        OsbEasing.Linear,
        0.0,
        1000.0,
        new CommandScale(1.0, 1.0), 
        new CommandScale(1.0, 2.0)
    );
  8. Use the Scale command (S)

    master

    The ScaleCommand (identified by the shortcut S) is used to animate the scale of an element over a specific time interval. It transitions a scale value from a startValue to an endValue using a specified easing function.

    Key constraints:

    • Scale values cannot be negative. The command ensures the scale never drops below 0 using Math.Max(0, ...).
    • The command is only fragmentable at a specific time if both the StartValue and EndValue are non-negative.
    // Conceptual usage of ScaleCommand
    new ScaleCommand(
        easing: OsbEasing.Linear,
        startTime: 0.0,
        endTime: 1.0,
        startValue: new CommandDecimal(1.0),
        endValue: new CommandDecimal(2.0)
    );
  9. Use the Move command (M)

    master

    The MoveCommand (identified by the shortcut M) is used to animate the position of elements in a storyboard. It interpolates between a StartValue and an EndValue using a specified easing function over a given time range.

    When applying transformations (like scaling or rotation) to the storyboard, the command's start and end positions are automatically adjusted via GetTransformedStartValue and GetTransformedEndValue using the StoryboardTransform logic.

    // Note: This is a conceptual representation of the MoveCommand constructor usage
    // based on the implementation signature.
    new MoveCommand(
        easing: OsbEasing.Linear, 
        startTime: 1000.0, 
        endTime: 2000.0, 
        startValue: new CommandPosition(0, 0), 
        endValue: new CommandPosition(100, 100)
    );
  10. Use the Fade command (F)

    master

    The Fade command (identifier F) creates a transition for a decimal value (such as opacity or scale) between a startValue and an endValue over a specified time interval. It uses an OsbEasing function to determine the interpolation curve between the two values.

    // Conceptual usage of the FadeCommand constructor
    // Parameters: OsbEasing easing, double startTime, double endTime, CommandDecimal startValue, CommandDecimal endValue
    new FadeCommand(OsbEasing.Linear, 1000.0, 2000.0, startValue, endValue);
  11. Use the MoveYCommand to move elements along the Y axis

    master

    The MoveYCommand is used to animate an element's position along the Y axis over a specified duration. It requires an easing function, a start time, an end time, and the starting and ending Y-axis values.

    When applying transformations to the storyboard, the command uses StoryboardTransform.ApplyToPositionY to adjust the start and end values accordingly.

    // Example instantiation of a MoveYCommand
    // Parameters: OsbEasing easing, double startTime, double endTime, CommandDecimal startValue, CommandDecimal endValue
    var moveY = new MoveYCommand(OsbEasing.Linear, 1000.0, 2000.0, new CommandDecimal(100.0), new CommandDecimal(500.0));