mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-25 10:43:46 +00:00
Add progress dialog/bar when we change color mode
Added a new app::RenderTaskJob to execute a lambda function as in a background thread in a app::Job that can be used as a render::TaskDelegate by some render functions.
This commit is contained in:
parent
573cad4777
commit
131336d015
@ -24,34 +24,74 @@
|
|||||||
#include "doc/palette.h"
|
#include "doc/palette.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
#include "render/quantization.h"
|
#include "render/quantization.h"
|
||||||
|
#include "render/task_delegate.h"
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
namespace cmd {
|
namespace cmd {
|
||||||
|
|
||||||
using namespace doc;
|
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,
|
SetPixelFormat::SetPixelFormat(Sprite* sprite,
|
||||||
const PixelFormat newFormat,
|
const PixelFormat newFormat,
|
||||||
const render::DitheringAlgorithm dithering)
|
const render::DitheringAlgorithm dithering,
|
||||||
|
render::TaskDelegate* delegate)
|
||||||
: WithSprite(sprite)
|
: WithSprite(sprite)
|
||||||
, m_oldFormat(sprite->pixelFormat())
|
, m_oldFormat(sprite->pixelFormat())
|
||||||
, m_newFormat(newFormat)
|
, m_newFormat(newFormat)
|
||||||
, m_dithering(dithering)
|
|
||||||
{
|
{
|
||||||
if (sprite->pixelFormat() == newFormat)
|
if (sprite->pixelFormat() == newFormat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
SuperDelegate superDel(sprite->uniqueCels().size(), delegate);
|
||||||
|
|
||||||
for (Cel* cel : sprite->uniqueCels()) {
|
for (Cel* cel : sprite->uniqueCels()) {
|
||||||
ImageRef old_image = cel->imageRef();
|
ImageRef old_image = cel->imageRef();
|
||||||
ImageRef new_image(
|
ImageRef new_image(
|
||||||
render::convert_pixel_format
|
render::convert_pixel_format
|
||||||
(old_image.get(), NULL, newFormat, m_dithering,
|
(old_image.get(), NULL, newFormat, dithering,
|
||||||
sprite->rgbMap(cel->frame()),
|
sprite->rgbMap(cel->frame()),
|
||||||
sprite->palette(cel->frame()),
|
sprite->palette(cel->frame()),
|
||||||
cel->layer()->isBackground(),
|
cel->layer()->isBackground(),
|
||||||
old_image->maskColor()));
|
old_image->maskColor(),
|
||||||
|
&superDel));
|
||||||
|
|
||||||
m_seq.add(new cmd::ReplaceImage(sprite, old_image, new_image));
|
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.
|
// Set all cels opacity to 100% if we are converting to indexed.
|
||||||
|
@ -17,6 +17,10 @@ namespace doc {
|
|||||||
class Sprite;
|
class Sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
class TaskDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
namespace cmd {
|
namespace cmd {
|
||||||
|
|
||||||
@ -25,7 +29,8 @@ namespace cmd {
|
|||||||
public:
|
public:
|
||||||
SetPixelFormat(doc::Sprite* sprite,
|
SetPixelFormat(doc::Sprite* sprite,
|
||||||
const doc::PixelFormat newFormat,
|
const doc::PixelFormat newFormat,
|
||||||
const render::DitheringAlgorithm dithering);
|
const render::DitheringAlgorithm dithering,
|
||||||
|
render::TaskDelegate* delegate);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onExecute() override;
|
void onExecute() override;
|
||||||
@ -40,7 +45,6 @@ namespace cmd {
|
|||||||
|
|
||||||
doc::PixelFormat m_oldFormat;
|
doc::PixelFormat m_oldFormat;
|
||||||
doc::PixelFormat m_newFormat;
|
doc::PixelFormat m_newFormat;
|
||||||
render::DitheringAlgorithm m_dithering;
|
|
||||||
CmdSequence m_seq;
|
CmdSequence m_seq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "app/modules/editors.h"
|
#include "app/modules/editors.h"
|
||||||
#include "app/modules/gui.h"
|
#include "app/modules/gui.h"
|
||||||
#include "app/modules/palettes.h"
|
#include "app/modules/palettes.h"
|
||||||
|
#include "app/render_task_job.h"
|
||||||
#include "app/transaction.h"
|
#include "app/transaction.h"
|
||||||
#include "app/ui/editor/editor.h"
|
#include "app/ui/editor/editor.h"
|
||||||
#include "app/ui/skin/skin_theme.h"
|
#include "app/ui/skin/skin_theme.h"
|
||||||
@ -397,14 +398,20 @@ void ChangePixelFormatCommand::onExecute(Context* context)
|
|||||||
if (context->activeDocument()->sprite()->pixelFormat() == m_format)
|
if (context->activeDocument()->sprite()->pixelFormat() == m_format)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
{
|
RenderTaskJob job(
|
||||||
ContextWriter writer(context);
|
"Converting Color Mode",
|
||||||
Transaction transaction(writer.context(), "Color Mode Change");
|
[this, &job, context]{
|
||||||
Sprite* sprite(writer.sprite());
|
ContextWriter writer(context);
|
||||||
|
Transaction transaction(writer.context(), "Color Mode Change");
|
||||||
transaction.execute(new cmd::SetPixelFormat(sprite, m_format, m_dithering));
|
Sprite* sprite(writer.sprite());
|
||||||
transaction.commit();
|
transaction.execute(
|
||||||
}
|
new cmd::SetPixelFormat(
|
||||||
|
sprite, m_format, m_dithering, &job));
|
||||||
|
if (!job.isCanceled())
|
||||||
|
transaction.commit();
|
||||||
|
});
|
||||||
|
job.startJob();
|
||||||
|
job.waitJob();
|
||||||
|
|
||||||
if (context->isUIAvailable())
|
if (context->isUIAvailable())
|
||||||
app_refresh_screen();
|
app_refresh_screen();
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "app/job.h"
|
#include "app/job.h"
|
||||||
#include "app/modules/palettes.h"
|
#include "app/modules/palettes.h"
|
||||||
#include "app/pref/preferences.h"
|
#include "app/pref/preferences.h"
|
||||||
|
#include "app/render_task_job.h"
|
||||||
#include "app/transaction.h"
|
#include "app/transaction.h"
|
||||||
#include "app/ui/color_bar.h"
|
#include "app/ui/color_bar.h"
|
||||||
#include "app/ui_context.h"
|
#include "app/ui_context.h"
|
||||||
@ -25,7 +26,6 @@
|
|||||||
#include "doc/palette.h"
|
#include "doc/palette.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
#include "render/quantization.h"
|
#include "render/quantization.h"
|
||||||
#include "render/task_delegate.h"
|
|
||||||
#include "ui/manager.h"
|
#include "ui/manager.h"
|
||||||
|
|
||||||
#include "palette_from_sprite.xml.h"
|
#include "palette_from_sprite.xml.h"
|
||||||
@ -42,37 +42,6 @@ protected:
|
|||||||
void onExecute(Context* context) override;
|
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()
|
ColorQuantizationCommand::ColorQuantizationCommand()
|
||||||
: Command("ColorQuantization",
|
: Command("ColorQuantization",
|
||||||
"Create Palette from Current Sprite (Color Quantization)",
|
"Create Palette from Current Sprite (Color Quantization)",
|
||||||
@ -144,7 +113,14 @@ void ColorQuantizationCommand::onExecute(Context* context)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Palette tmpPalette(frame, entries.picks());
|
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.startJob();
|
||||||
job.waitJob();
|
job.waitJob();
|
||||||
if (job.isCanceled())
|
if (job.isCanceled())
|
||||||
|
@ -707,7 +707,8 @@ void DocumentExporter::renderTexture(const Samples& samples, Image* textureImage
|
|||||||
cmd::SetPixelFormat(
|
cmd::SetPixelFormat(
|
||||||
sample.sprite(),
|
sample.sprite(),
|
||||||
textureImage->pixelFormat(),
|
textureImage->pixelFormat(),
|
||||||
render::DitheringAlgorithm::None)
|
render::DitheringAlgorithm::None,
|
||||||
|
nullptr) // TODO add a delegate to show progress
|
||||||
.execute(UIContext::instance());
|
.execute(UIContext::instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
src/app/render_task_job.h
Normal file
46
src/app/render_task_job.h
Normal file
@ -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 <functional>
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
class RenderTaskJob : public Job,
|
||||||
|
public render::TaskDelegate {
|
||||||
|
public:
|
||||||
|
template<typename T>
|
||||||
|
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<void()> m_func;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite Document Library
|
// 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.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -64,6 +64,13 @@ namespace doc {
|
|||||||
iterator begin() { return m_begin; }
|
iterator begin() { return m_begin; }
|
||||||
iterator end() { return m_end; }
|
iterator end() { return m_end; }
|
||||||
|
|
||||||
|
int size() {
|
||||||
|
int count = 0;
|
||||||
|
for (auto it=begin(), e=end(); it!=e; ++it)
|
||||||
|
++count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SelectedFrames m_selFrames;
|
SelectedFrames m_selFrames;
|
||||||
iterator m_begin, m_end;
|
iterator m_begin, m_end;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user