Add layer opacity property (fix #225)

This commit is contained in:
David Capello 2015-06-14 20:23:49 -03:00
parent 415995183d
commit fb4b2e76c8
9 changed files with 148 additions and 21 deletions

View File

@ -1,5 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2014 by David Capello -->
<!-- Copyright (C) 2001-2015 by David Capello -->
<gui>
<window text="Layer Properties" id="layer_properties">
<vbox>
@ -9,6 +9,9 @@
<label text="Mode:" />
<combobox id="mode" />
<label text="Opacity:" />
<slider id="opacity" min="0" max="255" width="128" />
</grid>
<separator horizontal="true" />
<hbox>

View File

@ -114,6 +114,7 @@ add_library(app-lib
cmd/set_frame_tag_name.cpp
cmd/set_frame_tag_range.cpp
cmd/set_layer_blend_mode.cpp
cmd/set_layer_opacity.cpp
cmd/set_layer_flags.cpp
cmd/set_layer_name.cpp
cmd/set_mask.cpp

View File

@ -0,0 +1,39 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/cmd/set_layer_opacity.h"
#include "doc/layer.h"
namespace app {
namespace cmd {
SetLayerOpacity::SetLayerOpacity(LayerImage* layer, int opacity)
: WithLayer(layer)
, m_oldOpacity(layer->opacity())
, m_newOpacity(opacity)
{
}
void SetLayerOpacity::onExecute()
{
static_cast<LayerImage*>(layer())->setOpacity(m_newOpacity);
layer()->incrementVersion();
}
void SetLayerOpacity::onUndo()
{
static_cast<LayerImage*>(layer())->setOpacity(m_oldOpacity);
layer()->incrementVersion();
}
} // namespace cmd
} // namespace app

View File

@ -0,0 +1,43 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifndef APP_CMD_SET_LAYER_OPACITY_H_INCLUDED
#define APP_CMD_SET_LAYER_OPACITY_H_INCLUDED
#pragma once
#include "app/cmd.h"
#include "app/cmd/with_layer.h"
namespace doc {
class LayerImage;
}
namespace app {
namespace cmd {
using namespace doc;
class SetLayerOpacity : public Cmd
, public WithLayer {
public:
SetLayerOpacity(LayerImage* layer, int opacity);
protected:
void onExecute() override;
void onUndo() override;
size_t onMemSize() const override {
return sizeof(*this);
}
private:
int m_oldOpacity;
int m_newOpacity;
};
} // namespace cmd
} // namespace app
#endif

View File

@ -15,6 +15,7 @@
#include "app/app.h"
#include "app/cmd/set_layer_blend_mode.h"
#include "app/cmd/set_layer_name.h"
#include "app/cmd/set_layer_opacity.h"
#include "app/commands/command.h"
#include "app/context_access.h"
#include "app/modules/gui.h"
@ -45,7 +46,8 @@ public:
LayerPropertiesWindow(const LayerImage* layer)
: m_layer(const_cast<LayerImage*>(layer))
, m_oldBlendMode(layer->blendMode()) {
, m_oldBlendMode(layer->blendMode())
, m_oldOpacity(layer->opacity()) {
name()->setText(layer->name().c_str());
name()->setMinSize(gfx::Size(128, 0));
name()->setExpansive(true);
@ -67,8 +69,13 @@ public:
mode()->addItem("Color");
mode()->addItem("Luminosity");
mode()->setSelectedItemIndex((int)layer->blendMode());
opacity()->setValue(layer->opacity());
mode()->setEnabled(!layer->isBackground());
mode()->Change.connect(Bind<void>(&LayerPropertiesWindow::onBlendModeChange, this));
opacity()->setEnabled(!layer->isBackground());
mode()->Change.connect(Bind<void>(&LayerPropertiesWindow::onLayerPropsChange, this));
opacity()->Change.connect(Bind<void>(&LayerPropertiesWindow::onLayerPropsChange, this));
remapWindow();
centerWindow();
@ -83,26 +90,34 @@ public:
return (BlendMode)mode()->getSelectedItemIndex();
}
int opacityValue() const {
return opacity()->getValue();
}
protected:
bool onProcessMessage(ui::Message* msg) override {
switch (msg->type()) {
case kCloseMessage:
m_layer->setBlendMode(m_oldBlendMode);
m_layer->setOpacity(m_oldOpacity);
save_window_pos(this, "LayerProperties");
break;
}
return Window::onProcessMessage(msg);
}
void onBlendModeChange() {
void onLayerPropsChange() {
m_layer->setBlendMode(blendModeValue());
m_layer->setOpacity(opacityValue());
update_screen_for_document(
static_cast<app::Document*>(m_layer->sprite()->document()));
}
LayerImage* m_layer;
BlendMode m_oldBlendMode;
int m_oldOpacity;
};
LayerPropertiesCommand::LayerPropertiesCommand()
@ -129,9 +144,11 @@ void LayerPropertiesCommand::onExecute(Context* context)
if (window.getKiller() == window.ok()) {
std::string newName = window.nameValue();
int newOpacity = window.opacityValue();
BlendMode newBlendMode = window.blendModeValue();
if (newName != layer->name() ||
newOpacity != layer->opacity() ||
newBlendMode != layer->blendMode()) {
ContextWriter writer(reader);
{
@ -140,6 +157,9 @@ void LayerPropertiesCommand::onExecute(Context* context)
if (newName != layer->name())
transaction.execute(new cmd::SetLayerName(writer.layer(), newName));
if (newOpacity != layer->opacity())
transaction.execute(new cmd::SetLayerOpacity(static_cast<LayerImage*>(writer.layer()), newOpacity));
if (newBlendMode != layer->blendMode())
transaction.execute(new cmd::SetLayerBlendMode(static_cast<LayerImage*>(writer.layer()), newBlendMode));

View File

@ -84,6 +84,7 @@ Cel* Layer::cel(frame_t frame) const
LayerImage::LayerImage(Sprite* sprite)
: Layer(ObjectType::LayerImage, sprite)
, m_opacity(255)
, m_blendmode(BlendMode::NORMAL)
{
}

View File

@ -119,6 +119,9 @@ namespace doc {
BlendMode blendMode() const { return m_blendmode; }
void setBlendMode(BlendMode blendmode) { m_blendmode = blendmode; }
int opacity() const { return m_opacity; }
void setOpacity(int opacity) { m_opacity = opacity; }
void addCel(Cel *cel);
void removeCel(Cel *cel);
void moveCel(Cel *cel, frame_t frame);
@ -139,6 +142,7 @@ namespace doc {
void destroyAllCels();
BlendMode m_blendmode;
int m_opacity;
CelList m_cels; // List of all cels inside this layer used by frames.
};

View File

@ -44,8 +44,13 @@ void write_layer(std::ostream& os, const Layer* layer)
switch (layer->type()) {
case ObjectType::LayerImage: {
CelConstIterator it, begin = static_cast<const LayerImage*>(layer)->getCelBegin();
CelConstIterator end = static_cast<const LayerImage*>(layer)->getCelEnd();
const LayerImage* imgLayer = static_cast<const LayerImage*>(layer);
CelConstIterator it, begin = imgLayer->getCelBegin();
CelConstIterator end = imgLayer->getCelEnd();
// Blend mode & opacity
write16(os, (int)imgLayer->blendMode());
write8(os, imgLayer->opacity());
// Images
int images = 0;
@ -73,7 +78,7 @@ void write_layer(std::ostream& os, const Layer* layer)
}
// Cels
write16(os, static_cast<const LayerImage*>(layer)->getCelsCount());
write16(os, imgLayer->getCelsCount());
for (it=begin; it != end; ++it) {
const Cel* cel = *it;
write_cel(os, cel);
@ -108,8 +113,14 @@ Layer* read_layer(std::istream& is, SubObjectsFromSprite* subObjects)
switch (static_cast<ObjectType>(layer_type)) {
case ObjectType::LayerImage: {
LayerImage* imgLayer = new LayerImage(subObjects->sprite());
// Create layer
layer.reset(new LayerImage(subObjects->sprite()));
layer.reset(imgLayer);
// Blend mode & opacity
imgLayer->setBlendMode((BlendMode)read16(is));
imgLayer->setOpacity(read8(is));
// Read images
int images = read16(is); // Number of images
@ -132,7 +143,7 @@ Layer* read_layer(std::istream& is, SubObjectsFromSprite* subObjects)
Cel* cel = read_cel(is, subObjects);
// Add the cel in the layer
static_cast<LayerImage*>(layer.get())->addCel(cel);
imgLayer->addCel(cel);
}
break;
}

View File

@ -680,18 +680,25 @@ void Render::renderLayer(
}
if (src_image) {
int t, output_opacity;
const LayerImage* imgLayer = static_cast<const LayerImage*>(layer);
BlendMode layerBlendMode =
(blend_mode == BlendMode::UNSPECIFIED ?
imgLayer->blendMode():
blend_mode);
output_opacity = MID(0, cel->opacity(), 255);
output_opacity = MUL_UN8(output_opacity, m_globalOpacity, t);
ASSERT(cel->opacity() >= 0);
ASSERT(cel->opacity() <= 255);
ASSERT(imgLayer->opacity() >= 0);
ASSERT(imgLayer->opacity() <= 255);
// Multiple three opacities: cel*layer*global
int t;
int opacity = cel->opacity();
opacity = MUL_UN8(opacity, imgLayer->opacity(), t);
opacity = MUL_UN8(opacity, m_globalOpacity, t);
ASSERT(src_image->maskColor() == m_sprite->transparentColor());
BlendMode layer_blend_mode =
(blend_mode == BlendMode::UNSPECIFIED ?
static_cast<const LayerImage*>(layer)->blendMode():
blend_mode);
// Draw parts outside the "m_extraCel" area
if (drawExtra && m_extraType == ExtraType::PATCH) {
gfx::Region originalAreas(area.srcBounds());
@ -703,8 +710,7 @@ void Render::renderLayer(
image, src_image, pal,
cel, gfx::Clip(area.dst.x+rc.x-area.src.x,
area.dst.y+rc.y-area.src.y, rc), scaled_func,
output_opacity,
layer_blend_mode, zoom);
opacity, layerBlendMode, zoom);
}
}
// Draw the whole cel
@ -712,8 +718,7 @@ void Render::renderLayer(
renderCel(
image, src_image, pal,
cel, area, scaled_func,
output_opacity,
layer_blend_mode, zoom);
opacity, layerBlendMode, zoom);
}
}
}