public function render(Job $job) { $format = $this->configuration->getString('format', 'png'); $defaultColor = $format == 'png' ? 0x0 : 0xffffffff; $backgroundColor = $this->configuration->getColor('background', $defaultColor); foreach ($job->spritesheets as $spritesheet) { /** @var Spritesheet $spritesheet */ $image = ImageTools::createImage($spritesheet->width, $spritesheet->height, $backgroundColor); foreach ($spritesheet->sprites as $sprite) { $repeatY = $sprite->repeatY; while ($repeatY--) { $repeatX = $sprite->repeatX; while ($repeatX--) { imagecopy($image, $sprite->image, $sprite->spriteX + $sprite->paddingLeft + $repeatX * $sprite->width, $sprite->spriteY + $sprite->paddingTop + $repeatY * $sprite->height, 0, 0, $sprite->width, $sprite->height); } } } $output = $this->mosaic->getPath($this->configuration->getString('outputFolder', Configuration::VALUE_REQUIRED)); $encodedSpritesheetPath = Tools::encodeFilePath($output . '/' . $spritesheet->name . '.' . $format); FileTools::createDirectory(dirname($encodedSpritesheetPath)); if ($format == 'png') { imagepng($image, $encodedSpritesheetPath, 9, E_ALL); } elseif ($format == 'jpg') { imagejpeg($image, $encodedSpritesheetPath, $this->configuration->getInt('quality', 90)); } imagedestroy($image); $encodedSpritesheetPath = realpath($encodedSpritesheetPath); if (!$encodedSpritesheetPath) { throw new \Exception('Could not verify rendered spritesheet path.'); } // Normalize output path $spritesheet->path = Tools::decodeFilePath($encodedSpritesheetPath); } }
public function onRendered(Event $e) { $json = ['images' => [], 'frames' => [], 'animations' => []]; if ($framerate = $this->configuration->getFloat('framerate')) { $json['framerate'] = $framerate; } $spritesheetIndex = -1; $spriteIndex = -1; foreach ($this->job->spritesheets as $spritesheet) { $spritesheetIndex++; $animations = []; // $animationPrefix = $this->_configuration->getString('animationPrefix', $this->_job->configuration->getString('name')); $json['images'][] = $this->configuration->getString('spritesheetFolder', Configuration::VALUE_REQUIRED) . basename($spritesheet->path); foreach ($spritesheet->sprites as $sprite) { $spriteIndex++; $configuration = $this->getSpriteConfiguration($sprite); if (preg_match('!(.+)\\{animation(@([0-9.]+))?(@([^@\\}]+))?}!', $sprite->originalName, $animationData)) { if (!isset($animations[$animationData[1]])) { $animations[$animationData[1]] = ['speed' => isset($animationData[3]) ? floatval($animationData[3]) : null, 'sprites' => [$spriteIndex], 'next' => isset($animationData[5]) ? $animationData[5] : null]; if (!$animations[$animationData[1]]['speed']) { $animations[$animationData[1]]['speed'] = $configuration->getFloat('speed', 0); } } else { $animations[$animationData[1]]['sprites'][] = $spriteIndex; } } $frameConfiguration = [$sprite->spriteX, $sprite->spriteY, $sprite->spriteWidth, $sprite->spriteHeight, $spritesheetIndex]; if ($configuration->getBool('center')) { $frameConfiguration[] = round($sprite->spriteWidth / 2); $frameConfiguration[] = round($sprite->spriteHeight / 2); } $json['frames'][] = $frameConfiguration; $json['animations'][$sprite->name] = [$spriteIndex]; } foreach ($animations as $name => $animation) { $ani = ['frames' => $animation['sprites']]; if ($animation['speed']) { $ani['speed'] = $animation['speed']; } if ($next = $animation['next']) { if ($next == 'loop') { $next = $name; } $ani['next'] = $next; } $json['animations'][$name] = $ani; } } $outputFolder = $this->mosaic->getPath($this->configuration->getString('outputFolder', Configuration::VALUE_REQUIRED)); $outputFileBasename = $this->configuration->getString('outputFile', $this->job->configuration->getString('name', Configuration::VALUE_REQUIRED)); $outputPath = $outputFolder . $outputFileBasename . '.json'; $jsonFiles = [$outputPath => $json]; foreach ($jsonFiles as $path => $content) { $path = Tools::encodeFilePath($path); FileTools::createDirectory(dirname($path)); file_put_contents($path, json_encode($content, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); } }
public function onRendered(Event $e) { $scssContent = ''; $scssVariablesContent = ''; foreach ($this->job->spritesheets as $spritesheet) { $spritesheetName = $spritesheet->name; $spritePrefix = $this->configuration->getString('classPrefix', $this->job->configuration->getString('name') . '-'); $scssPrefix = $this->configuration->getString('scssPrefix', $spritePrefix); $image = $this->configuration->getString('spritesheetFolder') . basename($spritesheet->path); if ($this->configuration->getBool('refreshCache')) { $image .= '?_' . sha1_file($spritesheet->path); } $retinaFactor = $this->configuration->getInt('retinaFactor', 1); $retinaThreshold = $retinaFactor - 0.75; $retinaThresholdPx = round($retinaThreshold * 96); $retinaEnabled = $retinaFactor > 1; $indent = str_repeat(' ', 4); $scssContent .= <<<SCSS @mixin spritesheet-{$spritesheetName}() { display: inline-block; overflow: hidden; background-repeat: no-repeat; background-image: url({$image}); SCSS; $mixinsContent = ''; if ($retinaEnabled) { $scssContent .= $indent . 'background-size: ' . self::cssFormatPx($spritesheet->width / $retinaFactor) . ' auto;' . chr(10); } else { $scssContent .= $indent . 'background-size: auto;' . chr(10); } $scssContent .= '}' . chr(10) . chr(10); if ($retinaEnabled) { $scssContent .= <<<SCSS @media (min-device-pixel-ratio: {$retinaThreshold}), (min-resolution: {$retinaThresholdPx}dpi) { SCSS; } foreach ($spritesheet->sprites as $sprite) { $configuration = $this->getSpriteConfiguration($sprite); $spriteName = $spritePrefix . $sprite->name; $scssName = $scssPrefix . $sprite->name; $realSpriteWidth = $sprite->spriteWidth; $realSpriteHeight = $sprite->spriteHeight; $realSpriteX = $sprite->spriteX; $realSpriteY = $sprite->spriteY; if ($retinaEnabled) { $realSpriteWidth = $realSpriteWidth / $retinaFactor; $realSpriteHeight = $realSpriteHeight / $retinaFactor; $realSpriteX = $realSpriteX / $retinaFactor; $realSpriteY = $realSpriteY / $retinaFactor; } $spriteContent = $indent . $indent . '@include spritesheet-' . $spritesheetName . '();' . chr(10); if ($configuration->getBool('center')) { $spriteContent .= $indent . $indent . 'margin-left: ' . self::cssFormatPx(-$realSpriteWidth / $retinaFactor) . ';' . chr(10); $spriteContent .= $indent . $indent . 'margin-top: ' . self::cssFormatPx(-$realSpriteHeight / $retinaFactor) . ';' . chr(10); } $spriteContent .= $indent . $indent . 'width: ' . self::cssFormatPx($realSpriteWidth) . ';' . chr(10); $spriteContent .= $indent . $indent . 'height: ' . self::cssFormatPx($realSpriteHeight) . ';' . chr(10); $spriteContent .= $indent . $indent . 'background-position: ' . self::cssFormatPx(-$realSpriteX) . ' ' . self::cssFormatPx(-$realSpriteY) . ';' . chr(10); foreach ($configuration->getNode('styles') as $styleName => $styleValue) { $spriteContent .= $indent . $indent . $styleName . ': ' . $styleValue . ';' . chr(10); } if ($configuration->getBool('createClass', true)) { // Write class $scssContent .= $indent . '.' . $spriteName . ' {' . chr(10) . $spriteContent . $indent . '}' . chr(10) . chr(10); } if ($configuration->getBool('createMixin', true)) { // Write mixin $mixinsContent .= chr(10) . $indent . '@mixin ' . $scssName . ' {' . chr(10) . $spriteContent . $indent . '}' . chr(10); } if ($configuration->getBool('createVariables', true)) { $scssVariablesContent .= '$' . $scssName . '-width: ' . self::cssFormatPx($sprite->spriteWidth) . ';' . chr(10); $scssVariablesContent .= '$' . $scssName . '-height: ' . self::cssFormatPx($sprite->spriteHeight) . ';' . chr(10); $scssVariablesContent .= '$' . $scssName . '-x: ' . self::cssFormatPx(-$sprite->spriteX) . ';' . chr(10); $scssVariablesContent .= '$' . $scssName . '-y: ' . self::cssFormatPx(-$sprite->spriteY) . ';' . chr(10); $scssVariablesContent .= "\${$scssName}-image: '{$image}';" . chr(10); $scssVariablesContent .= "\${$scssName}-retina-factor: {$retinaFactor};" . chr(10); $scssVariablesContent .= chr(10); } } if ($retinaEnabled) { $scssContent .= ' }' . chr(10); } if ($mixinsContent) { $scssContent .= chr(10) . $mixinsContent; } } $outputFolder = $this->mosaic->getPath($this->configuration->getString('outputFolder')); $outputFileBasename = $this->configuration->getString('outputFile', '_' . $this->job->configuration->getString('name')); $outputPath = $outputFolder . $outputFileBasename . '.scss'; $outputPathVariables = $outputFolder . $outputFileBasename . '_variables.scss'; $scssFiles = [$outputPath => $scssContent, $outputPathVariables => $scssVariablesContent]; foreach ($scssFiles as $path => $content) { $path = Tools::encodeFilePath($path); FileTools::createDirectory(dirname($path)); file_put_contents($path, $content); } }
/** @return TwoSide */ public function getTwoSide($key, $defaultValue = null) { $value = $this->getSoft($key, $defaultValue); if ($value === null || $value === Configuration::VALUE_UNSET) { $value = $defaultValue; } return Tools::decodeTwoSide($value); }
private function processConfigurationTemplates($node) { if (!isset($node->templates)) { return $node; } $nodeCopy = Tools::deepCloneObject($node); $templates = Tools::singleOrMultipleValuesToArray($node->templates); foreach ($templates as $template) { $templateData = null; if (preg_match('!\\.yml$!', $template)) { $templateData = Configuration::createFromFile($this->getPath($template))->configuration; } else { $subConfig = $this->configuration->getSubConfiguration('templates'); if ($subConfig->has($template)) { $templateData = $subConfig->getNode($template); } else { $templateFile = $this->getApplicationPath('templates/' . $template . '.yml'); $templateData = Configuration::createFromFile($templateFile)->configuration; } } if ($templateData) { $this->processConfigurationTemplates($templateData); Tools::extendObject($node, $templateData); } } Tools::extendObject($node, $nodeCopy); return $node; }
private function extendSpriteSettings(Job $job, Sprite $sprite) { $spriteSettings = $job->configuration->getNode('sprites'); foreach ($spriteSettings as $spriteSetting) { if ($spriteSetting === null) { // Empty node continue; } if (isset($spriteSetting->filters)) { $matches = Tools::matches($spriteSetting->filters, $sprite->name) || Tools::matches($spriteSetting->filters, $sprite->originalName); } else { $matches = true; } if (!$matches) { continue; } $attributes = new \stdClass(); $passAttributes = ['name']; $passAttributes = array_flip($passAttributes); $excludeAttributes = ['filter']; $excludeAttributes = array_flip($excludeAttributes); foreach ($spriteSetting as $atbName => $atbValue) { if (array_key_exists($atbName, $excludeAttributes)) { continue; } elseif (array_key_exists($atbName, $passAttributes)) { $sprite->{$atbName} = $atbValue; } elseif ($atbName == 'margin') { $s = Tools::decodeFourSide($atbValue); if ($s) { $sprite->marginTop = $s->top; $sprite->marginRight = $s->right; $sprite->marginBottom = $s->bottom; $sprite->marginLeft = $s->left; } } elseif ($atbName == 'padding') { $s = Tools::decodeFourSide($atbValue); if ($s) { $sprite->paddingTop = $s->top; $sprite->paddingRight = $s->right; $sprite->paddingBottom = $s->bottom; $sprite->paddingLeft = $s->left; } } else { $attributes->{$atbName} = $atbValue; } } $sprite->configuration->extend($attributes); } }