Pagination - lmparppei/BeatPlugins GitHub Wiki

You can calculate page lengths for lines using a pagination object. It can return either a number of pages used, or page length in eights. By default, pagination uses page size (A4/US Letter) set in document settings.

If you want to find out how long the scenes in the current screenplay are, it's recommended to use the pagination instance tied to the document preview. It automatically has all the document settings, and is constantly updated. You can access it using Beat.currentPagination().

To catch updates to the pagination, use Beat.onPreviewFinished(callback)

Beat.currentPagination() — returns the pagination instance tied to current document
const pagination = Beat.pagination() — create a new pagination instance

Properties

  • pages: The pages (BeatPaginationPage) in finished pagination
  • maxPageHeight:Float — maximum height of a single page in the current pagination.
  • lengthInEights:[Int]: length of paginated content in eights, returns [fullPages, eights]
  • numberOfPages: The number of pages in the current pagination.
  • lastPageHeight:Float: The height of the last page in the current pagination.
  • finishedPagination: The finished pagination of the Beat document, if one has been generated.

NOTE: Page count is always the full number of pages it takes to print out the document (excluding title page).

Methods

  • pageNumberAt(location): returns the page number at given location in screenplay
  • sceneLengthInEights(scene): returns the height of a scene in eights ([fullPages, eights])
  • heightForScene(scene): returns RELATIVE (0...1) height of a scene on page
  • heightForRange(loc, len): returns RELATIVE (0...1) height of given range in paginated content
  • paginateLines(lines): Paginates given lines

Pages

The pagination.pages array contains BeatPaginationPage objects. Pages are made out of layout blocks, which in turn contain the lines.

  • page.maxHeight: maximum height of the page in points
  • page.remainingSpace: remaining space on page
  • page.lines: line objects contained by this page (these can be "fake" lines too, such as (MORE))
  • page.positionOfBlockForLine(line): returns a relative (0...1) y-axis position for the block which contains the given line
  • page.actualPositionOfBlockForLine(line): returns y-axis position (in points) for the block which contains the given line
  • page.representedRange(): returns the range of screenplay which this page contains

Notes

Never call paginateLines() on the current pagination (Beat.currentPagination()), because you could end up messing up the editor preview and page numbering. If you want to calculate page count outside the document, create a new pagination instance.

If you want to calculate length of the screenplay in both full pages and fractions, keep in mind that .lastPageHeight is 0.0 when the last page was full.

image

For example, if the paginated content only takes up half a page, .numberOfPages will be 1, and .lastPageHeight = 0.5. If the content takes up exactly one page, .lastPageHeight will be 0.0.

Example

Get all scene lengths from document:

const pagination = Beat.currentPagination()
function getLengths() {
	const lengths = []
	for (const scene of Beat.scenes()) {
	    let length = pagination.heightForScene(scene)
	    lengths.push(length)
	}
	Beat.log("Scene lengths: " + JSON.stringify(lengths))
}
// Get lengths at plugin start
getLengths()
// ... and also whenever the content is paginated
Beat.onPreviewFinished(() => {
	getLengths()
})

Calculate individual scene lengths in eights:

// Create a new pagination instance
const pagination = Beat.pagination() 
const scenes = Beat.scenes()

for (const scene of scenes) {
    const lines = Beat.linesForScene(scene)
    pagination.paginateLines(lines)
    
    let eights = pagination.lengthInEights() // Returns [pages, eights]
}

Notes on Concurrency

If you are accessing .currentPagination() from a background thread, you might run into concurrency issues. .finishedPagination might be changed while your background process is running. To avoid this, create a reference to .finishedPagination in main thread, preferably when preview has finished.

let finishedPagination
Beat.onPreviewFinished(() => {
    finishedPagination = Beat.currentPagination().finishedPagination
})