diff --git a/src/app/cmd/set_pixel_format.cpp b/src/app/cmd/set_pixel_format.cpp index fafb90612..66b424e9e 100644 --- a/src/app/cmd/set_pixel_format.cpp +++ b/src/app/cmd/set_pixel_format.cpp @@ -24,34 +24,74 @@ #include "doc/palette.h" #include "doc/sprite.h" #include "render/quantization.h" +#include "render/task_delegate.h" namespace app { namespace cmd { using namespace doc; +namespace { + +class SuperDelegate : public render::TaskDelegate { +public: + SuperDelegate(int ncels, render::TaskDelegate* delegate) + : m_ncels(ncels) + , m_curCel(0) + , m_delegate(delegate) { + } + + void notifyTaskProgress(double progress) override { + if (m_delegate) + m_delegate->notifyTaskProgress( + (progress + m_curCel) / m_ncels); + } + + bool continueTask() override { + if (m_delegate) + return m_delegate->continueTask(); + else + return true; + } + + void nextCel() { + ++m_curCel; + } + +private: + int m_ncels; + int m_curCel; + TaskDelegate* m_delegate; +}; + +} // anonymous namespace + SetPixelFormat::SetPixelFormat(Sprite* sprite, const PixelFormat newFormat, - const render::DitheringAlgorithm dithering) + const render::DitheringAlgorithm dithering, + render::TaskDelegate* delegate) : WithSprite(sprite) , m_oldFormat(sprite->pixelFormat()) , m_newFormat(newFormat) - , m_dithering(dithering) { if (sprite->pixelFormat() == newFormat) return; + SuperDelegate superDel(sprite->uniqueCels().size(), delegate); + for (Cel* cel : sprite->uniqueCels()) { ImageRef old_image = cel->imageRef(); ImageRef new_image( render::convert_pixel_format - (old_image.get(), NULL, newFormat, m_dithering, + (old_image.get(), NULL, newFormat, dithering, sprite->rgbMap(cel->frame()), sprite->palette(cel->frame()), cel->layer()->isBackground(), - old_image->maskColor())); + old_image->maskColor(), + &superDel)); m_seq.add(new cmd::ReplaceImage(sprite, old_image, new_image)); + superDel.nextCel(); } // Set all cels opacity to 100% if we are converting to indexed. diff --git a/src/app/cmd/set_pixel_format.h b/src/app/cmd/set_pixel_format.h index ac051f753..0b55cecab 100644 --- a/src/app/cmd/set_pixel_format.h +++ b/src/app/cmd/set_pixel_format.h @@ -17,6 +17,10 @@ namespace doc { class Sprite; } +namespace render { + class TaskDelegate; +} + namespace app { namespace cmd { @@ -25,7 +29,8 @@ namespace cmd { public: SetPixelFormat(doc::Sprite* sprite, const doc::PixelFormat newFormat, - const render::DitheringAlgorithm dithering); + const render::DitheringAlgorithm dithering, + render::TaskDelegate* delegate); protected: void onExecute() override; @@ -40,7 +45,6 @@ namespace cmd { doc::PixelFormat m_oldFormat; doc::PixelFormat m_newFormat; - render::DitheringAlgorithm m_dithering; CmdSequence m_seq; }; diff --git a/src/app/commands/cmd_change_pixel_format.cpp b/src/app/commands/cmd_change_pixel_format.cpp index 56e5a97c0..f73edb72a 100644 --- a/src/app/commands/cmd_change_pixel_format.cpp +++ b/src/app/commands/cmd_change_pixel_format.cpp @@ -16,6 +16,7 @@ #include "app/modules/editors.h" #include "app/modules/gui.h" #include "app/modules/palettes.h" +#include "app/render_task_job.h" #include "app/transaction.h" #include "app/ui/editor/editor.h" #include "app/ui/skin/skin_theme.h" @@ -397,14 +398,20 @@ void ChangePixelFormatCommand::onExecute(Context* context) if (context->activeDocument()->sprite()->pixelFormat() == m_format) return; - { - ContextWriter writer(context); - Transaction transaction(writer.context(), "Color Mode Change"); - Sprite* sprite(writer.sprite()); - - transaction.execute(new cmd::SetPixelFormat(sprite, m_format, m_dithering)); - transaction.commit(); - } + RenderTaskJob job( + "Converting Color Mode", + [this, &job, context]{ + ContextWriter writer(context); + Transaction transaction(writer.context(), "Color Mode Change"); + Sprite* sprite(writer.sprite()); + transaction.execute( + new cmd::SetPixelFormat( + sprite, m_format, m_dithering, &job)); + if (!job.isCanceled()) + transaction.commit(); + }); + job.startJob(); + job.waitJob(); if (context->isUIAvailable()) app_refresh_screen(); diff --git a/src/app/commands/cmd_color_quantization.cpp b/src/app/commands/cmd_color_quantization.cpp index eb2262a05..22dc76011 100644 --- a/src/app/commands/cmd_color_quantization.cpp +++ b/src/app/commands/cmd_color_quantization.cpp @@ -17,6 +17,7 @@ #include "app/job.h" #include "app/modules/palettes.h" #include "app/pref/preferences.h" +#include "app/render_task_job.h" #include "app/transaction.h" #include "app/ui/color_bar.h" #include "app/ui_context.h" @@ -25,7 +26,6 @@ #include "doc/palette.h" #include "doc/sprite.h" #include "render/quantization.h" -#include "render/task_delegate.h" #include "ui/manager.h" #include "palette_from_sprite.xml.h" @@ -42,37 +42,6 @@ protected: void onExecute(Context* context) override; }; -class ColorQuantizationJob : public Job, - public render::TaskDelegate { -public: - ColorQuantizationJob(Sprite* sprite, bool withAlpha, Palette* palette) - : Job("Creating Palette") - , m_sprite(sprite) - , m_withAlpha(withAlpha) - , m_palette(palette) { - } - -private: - - void onJob() override { - render::create_palette_from_sprite( - m_sprite, 0, m_sprite->lastFrame(), - m_withAlpha, m_palette, this); - } - - bool continueTask() override { - return !isCanceled(); - } - - void notifyTaskProgress(double progress) override { - jobProgress(progress); - } - - Sprite* m_sprite; - bool m_withAlpha; - Palette* m_palette; -}; - ColorQuantizationCommand::ColorQuantizationCommand() : Command("ColorQuantization", "Create Palette from Current Sprite (Color Quantization)", @@ -144,7 +113,14 @@ void ColorQuantizationCommand::onExecute(Context* context) return; Palette tmpPalette(frame, entries.picks()); - ColorQuantizationJob job(sprite, withAlpha, &tmpPalette); + + RenderTaskJob job( + "Creating Palette", + [sprite, withAlpha, &tmpPalette, &job]{ + render::create_palette_from_sprite( + sprite, 0, sprite->lastFrame(), + withAlpha, &tmpPalette, &job); + }); job.startJob(); job.waitJob(); if (job.isCanceled()) diff --git a/src/app/document_exporter.cpp b/src/app/document_exporter.cpp index 637faf30d..e426e3ac1 100644 --- a/src/app/document_exporter.cpp +++ b/src/app/document_exporter.cpp @@ -707,7 +707,8 @@ void DocumentExporter::renderTexture(const Samples& samples, Image* textureImage cmd::SetPixelFormat( sample.sprite(), textureImage->pixelFormat(), - render::DitheringAlgorithm::None) + render::DitheringAlgorithm::None, + nullptr) // TODO add a delegate to show progress .execute(UIContext::instance()); } diff --git a/src/app/render_task_job.h b/src/app/render_task_job.h new file mode 100644 index 000000000..a3977a66b --- /dev/null +++ b/src/app/render_task_job.h @@ -0,0 +1,46 @@ +// Aseprite +// Copyright (C) 2017 David Capello +// +// This program is distributed under the terms of +// the End-User License Agreement for Aseprite. + +#ifndef APP_RENDER_TASK_JOB_H_INCLUDED +#define APP_RENDER_TASK_JOB_H_INCLUDED +#pragma once + +#include "app/job.h" +#include "render/task_delegate.h" + +#include + +namespace app { + +class RenderTaskJob : public Job, + public render::TaskDelegate { +public: + template + RenderTaskJob(const char* jobName, T&& func) + : Job(jobName) + , m_func(std::move(func)) { + } + +private: + + void onJob() override { + m_func(); + } + + // render::TaskDelegate impl + bool continueTask() override { + return !isCanceled(); + } + void notifyTaskProgress(double progress) override { + jobProgress(progress); + } + + std::function m_func; +}; + +} // namespace app + +#endif diff --git a/src/doc/cels_range.h b/src/doc/cels_range.h index ecb057d06..25048c22c 100644 --- a/src/doc/cels_range.h +++ b/src/doc/cels_range.h @@ -1,5 +1,5 @@ // Aseprite Document Library -// Copyright (c) 2001-2016 David Capello +// Copyright (c) 2001-2017 David Capello // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. @@ -64,6 +64,13 @@ namespace doc { iterator begin() { return m_begin; } iterator end() { return m_end; } + int size() { + int count = 0; + for (auto it=begin(), e=end(); it!=e; ++it) + ++count; + return count; + } + private: SelectedFrames m_selFrames; iterator m_begin, m_end;