mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-25 01:43:36 +00:00
307 lines
8.7 KiB
C++
307 lines
8.7 KiB
C++
// Aseprite
|
|
// Copyright (C) 2018-2019 Igara Studio S.A.
|
|
// Copyright (C) 2001-2018 David Capello
|
|
//
|
|
// This program is distributed under the terms of
|
|
// the End-User License Agreement for Aseprite.
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "app/app.h"
|
|
#include "app/color.h"
|
|
#include "app/color_spaces.h"
|
|
#include "app/color_utils.h"
|
|
#include "app/commands/command.h"
|
|
#include "app/commands/new_params.h"
|
|
#include "app/console.h"
|
|
#include "app/doc.h"
|
|
#include "app/i18n/strings.h"
|
|
#include "app/modules/editors.h"
|
|
#include "app/modules/palettes.h"
|
|
#include "app/pref/preferences.h"
|
|
#include "app/ui/button_set.h"
|
|
#include "app/ui/workspace.h"
|
|
#include "app/ui_context.h"
|
|
#include "app/util/clipboard.h"
|
|
#include "app/util/clipboard.h"
|
|
#include "app/util/pixel_ratio.h"
|
|
#include "base/bind.h"
|
|
#include "base/clamp.h"
|
|
#include "doc/cel.h"
|
|
#include "doc/image.h"
|
|
#include "doc/layer.h"
|
|
#include "doc/palette.h"
|
|
#include "doc/primitives.h"
|
|
#include "doc/sprite.h"
|
|
#include "fmt/format.h"
|
|
#include "render/quantization.h"
|
|
#include "ui/ui.h"
|
|
|
|
#include "new_sprite.xml.h"
|
|
|
|
using namespace ui;
|
|
|
|
namespace app {
|
|
|
|
struct NewFileParams : public NewParams {
|
|
Param<bool> ui { this, true, "ui" };
|
|
Param<int> width { this, 0, "width" };
|
|
Param<int> height { this, 0, "height" };
|
|
Param<ColorMode> colorMode { this, ColorMode::RGB, "colorMode" };
|
|
Param<bool> fromClipboard { this, false, "fromClipboard" };
|
|
};
|
|
|
|
class NewFileCommand : public CommandWithNewParams<NewFileParams> {
|
|
public:
|
|
NewFileCommand();
|
|
|
|
protected:
|
|
bool onEnabled(Context* context) override;
|
|
void onExecute(Context* ctx) override;
|
|
std::string onGetFriendlyName() const override;
|
|
|
|
static int g_spriteCounter;
|
|
};
|
|
|
|
// static
|
|
int NewFileCommand::g_spriteCounter = 0;
|
|
|
|
NewFileCommand::NewFileCommand()
|
|
: CommandWithNewParams(CommandId::NewFile(), CmdRecordableFlag)
|
|
{
|
|
}
|
|
|
|
bool NewFileCommand::onEnabled(Context* context)
|
|
{
|
|
return
|
|
(!params().fromClipboard()
|
|
#ifdef ENABLE_UI
|
|
|| (clipboard::get_current_format() == clipboard::ClipboardImage)
|
|
#endif
|
|
);
|
|
}
|
|
|
|
void NewFileCommand::onExecute(Context* ctx)
|
|
{
|
|
int width = params().width();
|
|
int height = params().height();
|
|
doc::ColorMode colorMode = params().colorMode();
|
|
app::Color bgColor = app::Color::fromMask();
|
|
doc::PixelRatio pixelRatio(1, 1);
|
|
#ifdef ENABLE_UI
|
|
doc::ImageRef clipboardImage;
|
|
doc::Palette clipboardPalette(0, 256);
|
|
#endif
|
|
const int ncolors = get_default_palette()->size();
|
|
|
|
#ifdef ENABLE_UI
|
|
if (params().fromClipboard()) {
|
|
clipboardImage = clipboard::get_image(&clipboardPalette);
|
|
if (!clipboardImage)
|
|
return;
|
|
|
|
width = clipboardImage->width();
|
|
height = clipboardImage->height();
|
|
colorMode = clipboardImage->colorMode();
|
|
}
|
|
else if (ctx->isUIAvailable() && params().ui()) {
|
|
Preferences& pref = Preferences::instance();
|
|
app::Color bg_table[] = { app::Color::fromMask(),
|
|
app::Color::fromRgb(255, 255, 255),
|
|
app::Color::fromRgb(0, 0, 0) };
|
|
|
|
// Load the window widget
|
|
app::gen::NewSprite window;
|
|
|
|
// Default values: Indexed, 320x240, Background color
|
|
if (!params().colorMode.isSet()) {
|
|
colorMode = pref.newFile.colorMode();
|
|
// Invalid format in config file.
|
|
if (colorMode != ColorMode::RGB &&
|
|
colorMode != ColorMode::INDEXED &&
|
|
colorMode != ColorMode::GRAYSCALE) {
|
|
colorMode = ColorMode::INDEXED;
|
|
}
|
|
}
|
|
|
|
int w = pref.newFile.width();
|
|
int h = pref.newFile.height();
|
|
int bg = pref.newFile.backgroundColor();
|
|
bg = MID(0, bg, 2);
|
|
|
|
// If the clipboard contains an image, we can show the size of the
|
|
// clipboard as default image size.
|
|
gfx::Size clipboardSize;
|
|
if (clipboard::get_image_size(clipboardSize)) {
|
|
w = clipboardSize.w;
|
|
h = clipboardSize.h;
|
|
}
|
|
|
|
if (params().width.isSet()) w = width;
|
|
if (params().height.isSet()) h = height;
|
|
|
|
window.width()->setTextf("%d", std::max(1, w));
|
|
window.height()->setTextf("%d", std::max(1, h));
|
|
|
|
// Select image-type
|
|
window.colorMode()->setSelectedItem(int(colorMode));
|
|
|
|
// Select background color
|
|
window.bgColor()->setSelectedItem(bg);
|
|
|
|
// Advance options
|
|
bool advanced = pref.newFile.advanced();
|
|
window.advancedCheck()->setSelected(advanced);
|
|
window.advancedCheck()->Click.connect(
|
|
base::Bind<void>(
|
|
[&]{
|
|
gfx::Rect bounds = window.bounds();
|
|
window.advanced()->setVisible(window.advancedCheck()->isSelected());
|
|
window.setBounds(gfx::Rect(window.bounds().origin(),
|
|
window.sizeHint()));
|
|
window.layout();
|
|
|
|
window.manager()->invalidateRect(bounds);
|
|
}));
|
|
window.advanced()->setVisible(advanced);
|
|
if (advanced)
|
|
window.pixelRatio()->setValue(pref.newFile.pixelRatio());
|
|
else
|
|
window.pixelRatio()->setValue("1:1");
|
|
|
|
// Open the window
|
|
window.openWindowInForeground();
|
|
|
|
if (window.closer() != window.okButton())
|
|
return;
|
|
|
|
bool ok = false;
|
|
|
|
// Get the options
|
|
colorMode = (doc::ColorMode)window.colorMode()->selectedItem();
|
|
w = window.width()->textInt();
|
|
h = window.height()->textInt();
|
|
bg = window.bgColor()->selectedItem();
|
|
if (window.advancedCheck()->isSelected()) {
|
|
pixelRatio = base::convert_to<PixelRatio>(
|
|
window.pixelRatio()->getValue());
|
|
}
|
|
|
|
static_assert(int(ColorMode::RGB) == 0, "RGB pixel format should be 0");
|
|
static_assert(int(ColorMode::INDEXED) == 2, "Indexed pixel format should be 2");
|
|
|
|
colorMode = base::clamp(colorMode, ColorMode::RGB, ColorMode::INDEXED);
|
|
w = base::clamp(w, 1, DOC_SPRITE_MAX_WIDTH);
|
|
h = base::clamp(h, 1, DOC_SPRITE_MAX_HEIGHT);
|
|
bg = base::clamp(bg, 0, 2);
|
|
|
|
// Select the background color
|
|
if (bg >= 0 && bg <= 3) {
|
|
bgColor = bg_table[bg];
|
|
ok = true;
|
|
}
|
|
|
|
if (ok) {
|
|
// Save the configuration
|
|
pref.newFile.width(w);
|
|
pref.newFile.height(h);
|
|
pref.newFile.colorMode(colorMode);
|
|
pref.newFile.backgroundColor(bg);
|
|
pref.newFile.advanced(window.advancedCheck()->isSelected());
|
|
pref.newFile.pixelRatio(window.pixelRatio()->getValue());
|
|
}
|
|
|
|
width = w;
|
|
height = h;
|
|
}
|
|
#endif // ENABLE_UI
|
|
|
|
ASSERT(colorMode == ColorMode::RGB ||
|
|
colorMode == ColorMode::GRAYSCALE ||
|
|
colorMode == ColorMode::INDEXED);
|
|
if (width < 1 || height < 1)
|
|
return;
|
|
|
|
// Create the new sprite
|
|
std::unique_ptr<Sprite> sprite(
|
|
Sprite::MakeStdSprite(
|
|
ImageSpec(colorMode, width, height, 0,
|
|
get_working_rgb_space_from_preferences()), ncolors));
|
|
|
|
sprite->setPixelRatio(pixelRatio);
|
|
|
|
if (sprite->colorMode() != ColorMode::GRAYSCALE)
|
|
get_default_palette()->copyColorsTo(sprite->palette(frame_t(0)));
|
|
|
|
// If the background color isn't transparent, we have to
|
|
// convert the `Layer 1' in a `Background'
|
|
if (bgColor.getType() != app::Color::MaskType) {
|
|
Layer* layer = sprite->root()->firstLayer();
|
|
|
|
if (layer && layer->isImage()) {
|
|
LayerImage* layerImage = static_cast<LayerImage*>(layer);
|
|
layerImage->configureAsBackground();
|
|
|
|
Image* image = layerImage->cel(frame_t(0))->image();
|
|
|
|
// TODO Replace this adding a new parameter to color utils
|
|
Palette oldPal = *get_current_palette();
|
|
set_current_palette(get_default_palette(), false);
|
|
|
|
doc::clear_image(
|
|
image,
|
|
color_utils::color_for_target(
|
|
bgColor,
|
|
ColorTarget(
|
|
ColorTarget::BackgroundLayer,
|
|
sprite->pixelFormat(),
|
|
sprite->transparentColor())));
|
|
|
|
set_current_palette(&oldPal, false);
|
|
}
|
|
}
|
|
#ifdef ENABLE_UI
|
|
else if (clipboardImage) {
|
|
Layer* layer = sprite->root()->firstLayer();
|
|
if (layer && layer->isImage()) {
|
|
LayerImage* layerImage = static_cast<LayerImage*>(layer);
|
|
// layerImage->configureAsBackground();
|
|
|
|
Image* image = layerImage->cel(frame_t(0))->image();
|
|
image->copy(clipboardImage.get(), gfx::Clip(clipboardImage->bounds()));
|
|
|
|
if (clipboardPalette.isBlack()) {
|
|
render::create_palette_from_sprite(
|
|
sprite.get(), 0, sprite->lastFrame(), true,
|
|
&clipboardPalette, nullptr, true);
|
|
}
|
|
sprite->setPalette(&clipboardPalette, false);
|
|
}
|
|
}
|
|
#endif // ENABLE_UI
|
|
|
|
// Show the sprite to the user
|
|
std::unique_ptr<Doc> doc(new Doc(sprite.get()));
|
|
sprite.release();
|
|
doc->setFilename(fmt::format("Sprite-{:04d}", ++g_spriteCounter));
|
|
doc->setContext(ctx);
|
|
doc.release();
|
|
}
|
|
|
|
std::string NewFileCommand::onGetFriendlyName() const
|
|
{
|
|
if (params().fromClipboard())
|
|
return fmt::format(Strings::commands_NewFile_FromClipboard());
|
|
else
|
|
return fmt::format(Strings::commands_NewFile());
|
|
}
|
|
|
|
Command* CommandFactory::createNewFileCommand()
|
|
{
|
|
return new NewFileCommand;
|
|
}
|
|
|
|
} // namespace app
|