swf2ass/src/DisplayEntry.php

166 lines
7.5 KiB
PHP

<?php
namespace swf2ass;
class DisplayEntry {
public $object;
public $currentColorTransform = null;
public $currentTransform = null;
/** @var FrameInformation[] */
public $frames = [];
public $startFrame;
public $depth;
public $clipDepth = 0;
public function getLines(CurrentState $currentState) {
if ($this->clipDepth > 0) {
return [];
}
if ($this->depth != 2) {
//return [];
}
if($currentState->frameOffset === null){
return [];
}
$dialogue = [];
$startFrame = $this->startFrame - $currentState->frameOffset;
$frameList = [];
foreach ($this->frames as $frame => $info){
$fn = $frame - $currentState->frameOffset;
if($fn < 0){
continue;
}
$frameList[$fn] = clone $info;
$frameList[$fn]->frame = $fn;
}
if(count($frameList) === 0){
return [];
}
$startTime = $startFrame * (1 / $currentState->frameRate);
$endTime = ($startFrame + 1) * (1 / $currentState->frameRate);
if ($this->object instanceof ObjectDefinition) {
$shapeDef = $this->object;
foreach ($shapeDef->getShapeList()->commands as $path){
$currentFrameStyles = [new StyleContainer()];
if($path->style instanceof LineStyleRecord){ //Stroke
$currentFrameStyles[0]->original_color3 = $currentFrameStyles[0]->color3 = $path->style->color;
$currentFrameStyles[0]->bord = round($path->style->width / TWIP_SIZE, 1);
}else if($path->style instanceof FillStyleRecord){ //Fill
$currentFrameStyles[0]->original_color1 = $currentFrameStyles[0]->color1 = $path->style->fill instanceof Gradient ? $path->style->fill->getItems()[0]->color : $path->style->fill; //TODO: gradient?
}
$currentFrameStyles[0]->shad = 0;
$assLine = "{\\an7\\shad0\\p1}";
foreach ($path->commands->edges as $edge) {
if ($edge instanceof MoveRecord) {
$coords = $edge->coord->toPixel();
$assLine .= "m " . round($coords->x, 2) . " " . round($coords->y, 2) . " ";
} else if ($edge instanceof LineRecord) {
$coords = $edge->coord->toPixel();
$assLine .= "l " . round($coords->x, 2) . " " . round($coords->y, 2) . " ";
} else if ($edge instanceof QuadraticCurveRecord) {
$edge = CubicCurveRecord::fromQuadraticRecord($edge);
$control1 = $edge->control1->toPixel();
$control2 = $edge->control2->toPixel();
$anchor = $edge->anchor->toPixel();
$assLine .= "b " . round($control1->x, 2) . " " . round($control1->y, 2) . " " . round($control2->x, 2) . " " . round($control2->y, 2) . " " . round($anchor->x, 2) . " " . round($anchor->y, 2) . " ";
} else if ($edge instanceof CubicCurveRecord) {
$control1 = $edge->control1->toPixel();
$control2 = $edge->control2->toPixel();
$anchor = $edge->anchor->toPixel();
$assLine .= "b " . round($control1->x, 2) . " " . round($control1->y, 2) . " " . round($control2->x, 2) . " " . round($control2->y, 2) . " " . round($anchor->x, 2) . " " . round($anchor->y, 2) . " ";
}
}
$assLine .= "{\\p0}";
$lastLineStart = $startTime;
$lastFrameStart = $startFrame;
$debugInfo = "oid:".$shapeDef->getId();
$savedFrameStyles = $currentFrameStyles;
$af = 0;
$frames = 0;
foreach ($frameList as $frame => $frameInformation) {
$currentTime = $frame * (1 / $currentState->frameRate);
$endCurrentTime = $currentTime + (1 / $currentState->frameRate);
if ($endCurrentTime > $endTime) {
$endTime = $endCurrentTime;
}
$lastStyle = end($currentFrameStyles);
$frameStyle = clone $lastStyle;
$frameStyle->resetTransformedStyles();
if ($frameInformation->transform instanceof MatrixTransform) {
$frameInformation->transform->applyToStyleContainer($frameStyle);
}
if ($frameInformation->colorTransform instanceof ColorTransform) {
$frameInformation->colorTransform->applyToStyleContainer($frameStyle);
}
$lastSavedStyle = end($savedFrameStyles);
$savedStyle = clone $lastSavedStyle;
$savedStyle->resetTransformedStyles();
if ($frameInformation->transform instanceof MatrixTransform) {
$frameInformation->transform->applyToStyleContainer($savedStyle);
}
if ($frameInformation->colorTransform instanceof ColorTransform) {
$frameInformation->colorTransform->applyToStyleContainer($savedStyle);
}
if ($frames === 0) {
$currentFrameStyles[array_key_last($currentFrameStyles)] = $frameStyle;
} else if (!$lastStyle->isEqualish($frameStyle)) {
if (ADVANCED_MOTION_INTERPOLATION) {
$transition = $lastStyle->doTransitionTo($frameStyle, $frame, $frame, max(0, $frame - 1), $frame);
} else {
$transition = $lastStyle->doTransitionTo($frameStyle, $frame, $frame, $frame, $frame);
}
if ($transition === false) {
$assHeader = "Dialogue: {$this->depth}," . Utils::timeToStamp($lastLineStart) . "," . Utils::timeToStamp($currentTime) . ",f,$debugInfo,0,0,0,af:" . ($af++) . ",";
foreach ($currentFrameStyles as $i => $style) {
$assHeader .= "{" . $style->toString($lastFrameStart, (1 / $currentState->frameRate), $currentFrameStyles[$i - 1] ?? null, $i === 0) . "}";
}
$dialogue[] = $assHeader . $assLine;
$lastLineStart = $currentTime;
$lastFrameStart = $frame;
$currentFrameStyles = [$savedStyle];
} else if ($transition instanceof StyleContainer) {
$currentFrameStyles[] = $transition;
$savedFrameStyles[] = $savedStyle;
}
}
++$frames;
}
$assHeader = "Dialogue: {$this->depth}," . Utils::timeToStamp($lastLineStart) . "," . Utils::timeToStamp($endTime) . ",f,$debugInfo,0,0,0,af:" . ($af++) . ",";
foreach ($currentFrameStyles as $i => $style) {
$assHeader .= "{" . $style->toString($lastFrameStart, (1 / $currentState->frameRate), $currentFrameStyles[$i - 1] ?? null, $i === 0) . "}";
}
$dialogue[] = $assHeader . $assLine;
}
}
return $dialogue;
}
}