mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-01 10:13:22 +00:00
Merge branch 'master' into beta
This commit is contained in:
commit
289a6ab864
12
README.md
12
README.md
@ -50,12 +50,14 @@ You can ask for help in:
|
|||||||
|
|
||||||
## Authors
|
## Authors
|
||||||
|
|
||||||
[Igara Studio](https://www.igarastudio.com/) is developing Aseprite:
|
Aseprite is being developed by [Igara Studio](https://www.igarastudio.com/):
|
||||||
|
|
||||||
* [David Capello](https://davidcapello.com/): Lead developer, fixing
|
* [David Capello](https://davidcapello.com/): Lead developer,
|
||||||
issues, new features, and user support.
|
bug fixing & new features in desktop & web, and user support.
|
||||||
* [Gaspar Capello](https://github.com/Gasparoken): Developer, fixing
|
* [Gaspar Capello](https://github.com/Gasparoken): Developer,
|
||||||
issues and new features.
|
bug fixing & new features in desktop, and user support.
|
||||||
|
* [Martin Capello](https://github.com/martincapello): Developer,
|
||||||
|
new store website.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
@ -1109,10 +1109,13 @@
|
|||||||
</item>
|
</item>
|
||||||
<separator />
|
<separator />
|
||||||
<item command="LoadPalette" text="@.load_palette" />
|
<item command="LoadPalette" text="@.load_palette" />
|
||||||
<item command="SavePalette" text="@.save_palette" />
|
|
||||||
<item command="LoadPalette" text="@.load_default_palette">
|
<item command="LoadPalette" text="@.load_default_palette">
|
||||||
<param name="preset" value="default" />
|
<param name="preset" value="default" />
|
||||||
</item>
|
</item>
|
||||||
|
<item command="SavePalette" text="@.save_palette" />
|
||||||
|
<item command="SavePalette" text="@.save_palette_as_preset">
|
||||||
|
<param name="saveAsPreset" value="true" />
|
||||||
|
</item>
|
||||||
<item command="SavePalette" text="@.save_as_default_palette" group="palette_files">
|
<item command="SavePalette" text="@.save_as_default_palette" group="palette_files">
|
||||||
<param name="preset" value="default" />
|
<param name="preset" value="default" />
|
||||||
</item>
|
</item>
|
||||||
|
@ -364,6 +364,12 @@
|
|||||||
<option id="bits_per_pixel" type="int" default="0" />
|
<option id="bits_per_pixel" type="int" default="0" />
|
||||||
<option id="compress" type="bool" default="true" />
|
<option id="compress" type="bool" default="true" />
|
||||||
</section>
|
</section>
|
||||||
|
<section id="css">
|
||||||
|
<option id="show_alert" type="bool" default="true" />
|
||||||
|
<option id="pixel_scale" type="int" default="1" />
|
||||||
|
<option id="with_vars" type="bool" default="false" />
|
||||||
|
<option id="generate_html" type="bool" default="false" />
|
||||||
|
</section>
|
||||||
<section id="webp">
|
<section id="webp">
|
||||||
<option id="show_alert" type="bool" default="true" />
|
<option id="show_alert" type="bool" default="true" />
|
||||||
<option id="loop" type="bool" default="true" />
|
<option id="loop" type="bool" default="true" />
|
||||||
|
@ -1386,9 +1386,10 @@ ryb_color_wheel = RYB Color Wheel
|
|||||||
normal_map_color_wheel = Normal Map Color Wheel
|
normal_map_color_wheel = Normal Map Color Wheel
|
||||||
load_palette = L&oad Palette
|
load_palette = L&oad Palette
|
||||||
save_palette = S&ave Palette
|
save_palette = S&ave Palette
|
||||||
|
save_palette_as_preset = Save Palette as Preset
|
||||||
load_default_palette = Load Default Palette
|
load_default_palette = Load Default Palette
|
||||||
save_as_default_palette = Save as Default Palette
|
save_as_default_palette = Save Palette as Default
|
||||||
create_palette_from_current_sprite = Create Palette from Current Sprite
|
create_palette_from_current_sprite = New Palette from Sprite
|
||||||
|
|
||||||
[palette_size]
|
[palette_size]
|
||||||
title = Palette Size
|
title = Palette Size
|
||||||
@ -1541,6 +1542,12 @@ title = TGA Options
|
|||||||
bits_per_pixel = Bits Per Pixel
|
bits_per_pixel = Bits Per Pixel
|
||||||
compress = Compress
|
compress = Compress
|
||||||
|
|
||||||
|
[css_options]
|
||||||
|
title = CSS Options
|
||||||
|
pixel_scale = Pixel Scale
|
||||||
|
with_vars = Use CSS3 Variables
|
||||||
|
generate_html = Generate Sample HTML File
|
||||||
|
|
||||||
[timeline_conf]
|
[timeline_conf]
|
||||||
position = Position:
|
position = Position:
|
||||||
left = &Left
|
left = &Left
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
<!-- Aseprite -->
|
<!-- Aseprite -->
|
||||||
<!-- Copyright (C) 2018-2020 Igara Studio S.A. -->
|
<!-- Copyright (C) 2018-2021 Igara Studio S.A. -->
|
||||||
<!-- Copyright (C) 2018 David Capello -->
|
<!-- Copyright (C) 2018 David Capello -->
|
||||||
<gui i18nwarnings="false">
|
<gui i18nwarnings="false">
|
||||||
<window id="about" text="About Aseprite">
|
<window id="about" text="About Aseprite">
|
||||||
<vbox>
|
<vbox>
|
||||||
<label text="" id="title" />
|
<label text="" id="title" />
|
||||||
<label text="Animated sprite editor && pixel art tool" />
|
<label text="Animated sprite editor && pixel art tool" />
|
||||||
<separator text="Authors:" horizontal="true" />
|
<separator text="Developers:" horizontal="true" />
|
||||||
<grid columns="2">
|
<grid columns="2">
|
||||||
<link text="David Capello" url="https://twitter.com/davidcapello" />
|
<link text="David Capello" url="https://twitter.com/davidcapello" />
|
||||||
<label text="- Lead developer, graphics && maintainer" />
|
<label text="- Lead developer, new features && bug fixing in desktop && web" />
|
||||||
<link text="Gaspar Capello" url="https://twitter.com/Gasparoken" />
|
<link text="Gaspar Capello" url="https://twitter.com/Gasparoken" />
|
||||||
<label text="- Programmer, bug fixing" />
|
<label text="- Developer, new features && bug fixing in desktop" />
|
||||||
|
<link text="Martin Capello" url="https://twitter.com/martincapell0" />
|
||||||
|
<label text="- Developer, new store website" />
|
||||||
|
|
||||||
<separator text="Contributors:" horizontal="true" cell_hspan="2" />
|
<separator text="Contributors:" horizontal="true" cell_hspan="2" />
|
||||||
<link text="Ilija Melentijevic" url="https://ilkke.net/" />
|
<link text="Ilija Melentijevic" url="https://ilkke.net/" />
|
||||||
@ -20,14 +22,14 @@
|
|||||||
<label text="- Default dark theme introduced in v1.3" />
|
<label text="- Default dark theme introduced in v1.3" />
|
||||||
|
|
||||||
<hbox cell_hspan="2">
|
<hbox cell_hspan="2">
|
||||||
<link text="Other Contributors" url="https://www.aseprite.org/contributors/" />
|
<link text="Other Contributors" url="https://www.aseprite.org/contributors/" />
|
||||||
<label text="&&" />
|
<label text="&&" />
|
||||||
<link text="Third-Party Projects" url="" id="licenses" />
|
<link text="Third-Party Projects" url="" id="licenses" />
|
||||||
</hbox>
|
</hbox>
|
||||||
</grid>
|
</grid>
|
||||||
<separator horizontal="true" />
|
<separator horizontal="true" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="Copyright (C) 2001-2020" />
|
<label text="Copyright (C) 2001-2021" />
|
||||||
<link text="Igara Studio S.A." url="https://www.igarastudio.com/" />
|
<link text="Igara Studio S.A." url="https://www.igarastudio.com/" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<link text="https://www.aseprite.org/" url="https://www.aseprite.org/" />
|
<link text="https://www.aseprite.org/" url="https://www.aseprite.org/" />
|
||||||
|
25
data/widgets/css_options.xml
Normal file
25
data/widgets/css_options.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!-- Aseprite -->
|
||||||
|
<!-- Copyright (C) 2018 by Igara Studio S.A. -->
|
||||||
|
<gui>
|
||||||
|
<window id="css_options" text="@.title">
|
||||||
|
<grid columns="2">
|
||||||
|
<label text="@.pixel_scale" />
|
||||||
|
<expr id="pixel_scale" magnet="true" cell_align="horizontal"/>
|
||||||
|
|
||||||
|
<check text="@.with_vars" id="with_vars" cell_hspan="2" />
|
||||||
|
|
||||||
|
<check text="@.generate_html" id="generate_html" cell_hspan="2" />
|
||||||
|
|
||||||
|
<separator horizontal="true" cell_hspan="2" />
|
||||||
|
|
||||||
|
<hbox cell_hspan="2">
|
||||||
|
<check text="@general.dont_show" id="dont_show" tooltip="@general.dont_show_tooltip" />
|
||||||
|
<boxfiller />
|
||||||
|
</hbox>
|
||||||
|
<box horizontal="true" homogeneous="true" cell_hspan="2" cell_align="right">
|
||||||
|
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
|
||||||
|
<button text="@general.cancel" closewindow="true" />
|
||||||
|
</box>
|
||||||
|
</grid>
|
||||||
|
</window>
|
||||||
|
</gui>
|
@ -440,6 +440,7 @@
|
|||||||
pref="scripts.show_run_script_alert" />
|
pref="scripts.show_run_script_alert" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<label text="@.image_format_alerts" />
|
<label text="@.image_format_alerts" />
|
||||||
|
<check id="css_options_alert" text="!css" pref="css.show_alert" />
|
||||||
<check id="gif_options_alert" text="!gif" pref="gif.show_alert" />
|
<check id="gif_options_alert" text="!gif" pref="gif.show_alert" />
|
||||||
<check id="jpeg_options_alert" text="!jpeg" pref="jpeg.show_alert" />
|
<check id="jpeg_options_alert" text="!jpeg" pref="jpeg.show_alert" />
|
||||||
<check id="svg_options_alert" text="!svg" pref="svg.show_alert" />
|
<check id="svg_options_alert" text="!svg" pref="svg.show_alert" />
|
||||||
|
@ -25,7 +25,7 @@ void global_function(int arg1, int arg2,
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
...
|
...
|
||||||
} while (condition);
|
} while (condition);
|
||||||
|
|
||||||
switch (condition) {
|
switch (condition) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -125,6 +125,7 @@ endif()
|
|||||||
set(file_formats
|
set(file_formats
|
||||||
file/ase_format.cpp
|
file/ase_format.cpp
|
||||||
file/bmp_format.cpp
|
file/bmp_format.cpp
|
||||||
|
file/css_format.cpp
|
||||||
file/fli_format.cpp
|
file/fli_format.cpp
|
||||||
file/gif_format.cpp
|
file/gif_format.cpp
|
||||||
file/ico_format.cpp
|
file/ico_format.cpp
|
||||||
@ -606,7 +607,7 @@ add_library(app-lib
|
|||||||
tools/pick_ink.cpp
|
tools/pick_ink.cpp
|
||||||
tools/point_shape.cpp
|
tools/point_shape.cpp
|
||||||
tools/stroke.cpp
|
tools/stroke.cpp
|
||||||
tools/symmetries.cpp
|
tools/symmetry.cpp
|
||||||
tools/tool_box.cpp
|
tools/tool_box.cpp
|
||||||
tools/tool_loop_manager.cpp
|
tools/tool_loop_manager.cpp
|
||||||
tools/velocity.cpp
|
tools/velocity.cpp
|
||||||
|
@ -124,6 +124,7 @@ namespace app {
|
|||||||
obs::signal<void()> Exit;
|
obs::signal<void()> Exit;
|
||||||
obs::signal<void()> PaletteChange;
|
obs::signal<void()> PaletteChange;
|
||||||
obs::signal<void()> ColorSpaceChange;
|
obs::signal<void()> ColorSpaceChange;
|
||||||
|
obs::signal<void()> PalettePresetsChange;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class CoreModules;
|
class CoreModules;
|
||||||
|
@ -992,6 +992,7 @@ private:
|
|||||||
advancedModeAlert()->resetWithDefaultValue();
|
advancedModeAlert()->resetWithDefaultValue();
|
||||||
invalidFgBgColorAlert()->resetWithDefaultValue();
|
invalidFgBgColorAlert()->resetWithDefaultValue();
|
||||||
runScriptAlert()->resetWithDefaultValue();
|
runScriptAlert()->resetWithDefaultValue();
|
||||||
|
cssOptionsAlert()->resetWithDefaultValue();
|
||||||
gifOptionsAlert()->resetWithDefaultValue();
|
gifOptionsAlert()->resetWithDefaultValue();
|
||||||
jpegOptionsAlert()->resetWithDefaultValue();
|
jpegOptionsAlert()->resetWithDefaultValue();
|
||||||
svgOptionsAlert()->resetWithDefaultValue();
|
svgOptionsAlert()->resetWithDefaultValue();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2020 Igara Studio S.A.
|
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -78,7 +78,7 @@ void RemoveLayerCommand::onExecute(Context* context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (sprite->allLayersCount() == 1) {
|
if (sprite->root()->layersCount() == 1) {
|
||||||
ui::Alert::show(Strings::alerts_cannot_delete_all_layers());
|
ui::Alert::show(Strings::alerts_cannot_delete_all_layers());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "app/app.h"
|
||||||
#include "app/commands/cmd_set_palette.h"
|
#include "app/commands/cmd_set_palette.h"
|
||||||
#include "app/commands/commands.h"
|
#include "app/commands/commands.h"
|
||||||
#include "app/commands/params.h"
|
#include "app/commands/params.h"
|
||||||
@ -35,6 +36,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_preset;
|
std::string m_preset;
|
||||||
|
bool m_saveAsPreset = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
SavePaletteCommand::SavePaletteCommand()
|
SavePaletteCommand::SavePaletteCommand()
|
||||||
@ -45,6 +47,7 @@ SavePaletteCommand::SavePaletteCommand()
|
|||||||
void SavePaletteCommand::onLoadParams(const Params& params)
|
void SavePaletteCommand::onLoadParams(const Params& params)
|
||||||
{
|
{
|
||||||
m_preset = params.get("preset");
|
m_preset = params.get("preset");
|
||||||
|
m_saveAsPreset = (params.get("saveAsPreset") == "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SavePaletteCommand::onExecute(Context* context)
|
void SavePaletteCommand::onExecute(Context* context)
|
||||||
@ -58,8 +61,9 @@ void SavePaletteCommand::onExecute(Context* context)
|
|||||||
else {
|
else {
|
||||||
base::paths exts = get_writable_palette_extensions();
|
base::paths exts = get_writable_palette_extensions();
|
||||||
base::paths selFilename;
|
base::paths selFilename;
|
||||||
|
std::string initialPath = (m_saveAsPreset ? get_preset_palettes_dir(): "");
|
||||||
if (!app::show_file_selector(
|
if (!app::show_file_selector(
|
||||||
"Save Palette", "", exts,
|
"Save Palette", initialPath, exts,
|
||||||
FileSelectorType::Save, selFilename))
|
FileSelectorType::Save, selFilename))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -74,6 +78,9 @@ void SavePaletteCommand::onExecute(Context* context)
|
|||||||
if (!context->activeDocument())
|
if (!context->activeDocument())
|
||||||
set_current_palette(palette, false);
|
set_current_palette(palette, false);
|
||||||
}
|
}
|
||||||
|
if (m_saveAsPreset) {
|
||||||
|
App::instance()->PalettePresetsChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command* CommandFactory::createSavePaletteCommand()
|
Command* CommandFactory::createSavePaletteCommand()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -332,18 +332,13 @@ Doc* Session::restoreBackupRawImages(Backup* backup,
|
|||||||
|
|
||||||
void Session::deleteBackup(Backup* backup)
|
void Session::deleteBackup(Backup* backup)
|
||||||
{
|
{
|
||||||
try {
|
auto it = std::find(m_backups.begin(), m_backups.end(), backup);
|
||||||
auto it = std::find(m_backups.begin(), m_backups.end(), backup);
|
ASSERT(it != m_backups.end());
|
||||||
ASSERT(it != m_backups.end());
|
if (it != m_backups.end())
|
||||||
if (it != m_backups.end())
|
m_backups.erase(it);
|
||||||
m_backups.erase(it);
|
|
||||||
|
|
||||||
if (base::is_directory(backup->dir()))
|
if (base::is_directory(backup->dir()))
|
||||||
deleteDirectory(backup->dir());
|
deleteDirectory(backup->dir());
|
||||||
}
|
|
||||||
catch (const std::exception& ex) {
|
|
||||||
Console::showException(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::loadPid()
|
void Session::loadPid()
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "doc/palette.h"
|
#include "doc/palette.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
#include "doc/tag.h"
|
#include "doc/tag.h"
|
||||||
|
#include "doc/slice.h"
|
||||||
#include "os/display.h"
|
#include "os/display.h"
|
||||||
#include "os/system.h"
|
#include "os/system.h"
|
||||||
#include "ui/system.h"
|
#include "ui/system.h"
|
||||||
@ -519,6 +520,14 @@ Doc* Doc::duplicate(DuplicateType type) const
|
|||||||
for (const Tag* tag : sourceSprite->tags())
|
for (const Tag* tag : sourceSprite->tags())
|
||||||
spriteCopy->tags().add(new Tag(*tag));
|
spriteCopy->tags().add(new Tag(*tag));
|
||||||
|
|
||||||
|
// Copy slices
|
||||||
|
for (const Slice *slice : sourceSprite->slices()) {
|
||||||
|
auto sliceCopy = new Slice(*slice);
|
||||||
|
spriteCopy->slices().add(sliceCopy);
|
||||||
|
|
||||||
|
ASSERT(sliceCopy->owner() == &spriteCopy->slices());
|
||||||
|
}
|
||||||
|
|
||||||
// Copy color palettes
|
// Copy color palettes
|
||||||
{
|
{
|
||||||
PalettesList::const_iterator it = sourceSprite->getPalettes().begin();
|
PalettesList::const_iterator it = sourceSprite->getPalettes().begin();
|
||||||
|
303
src/app/file/css_format.cpp
Normal file
303
src/app/file/css_format.cpp
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (c) 2018-2019 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// 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/console.h"
|
||||||
|
#include "app/context.h"
|
||||||
|
#include "app/doc.h"
|
||||||
|
#include "app/file/file.h"
|
||||||
|
#include "app/file/file_format.h"
|
||||||
|
#include "app/file/format_options.h"
|
||||||
|
#include "app/pref/preferences.h"
|
||||||
|
#include "base/convert_to.h"
|
||||||
|
#include "base/cfile.h"
|
||||||
|
#include "base/file_handle.h"
|
||||||
|
#include "base/string.h"
|
||||||
|
#include "doc/doc.h"
|
||||||
|
#include "ui/window.h"
|
||||||
|
|
||||||
|
#include "css_options.xml.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
using namespace base;
|
||||||
|
|
||||||
|
class CssFormat : public FileFormat {
|
||||||
|
class CssOptions : public FormatOptions {
|
||||||
|
public:
|
||||||
|
CssOptions() : pixelScale(1), gutterSize(0),
|
||||||
|
generateHtml(false),
|
||||||
|
withVars(false) { }
|
||||||
|
int pixelScale;
|
||||||
|
int gutterSize;
|
||||||
|
bool generateHtml;
|
||||||
|
bool withVars;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* onGetName() const override {
|
||||||
|
return "css";
|
||||||
|
}
|
||||||
|
|
||||||
|
void onGetExtensions(base::paths& exts) const override {
|
||||||
|
exts.push_back("css");
|
||||||
|
}
|
||||||
|
|
||||||
|
dio::FileFormat onGetDioFormat() const override {
|
||||||
|
return dio::FileFormat::CSS_STYLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int onGetFlags() const override {
|
||||||
|
return
|
||||||
|
FILE_SUPPORT_SAVE |
|
||||||
|
FILE_SUPPORT_RGB |
|
||||||
|
FILE_SUPPORT_RGBA |
|
||||||
|
FILE_SUPPORT_GRAY |
|
||||||
|
FILE_SUPPORT_GRAYA |
|
||||||
|
FILE_SUPPORT_INDEXED |
|
||||||
|
FILE_SUPPORT_SEQUENCES |
|
||||||
|
FILE_SUPPORT_GET_FORMAT_OPTIONS |
|
||||||
|
FILE_SUPPORT_PALETTE_WITH_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool onLoad(FileOp* fop) override;
|
||||||
|
#ifdef ENABLE_SAVE
|
||||||
|
bool onSave(FileOp* fop) override;
|
||||||
|
#endif
|
||||||
|
FormatOptionsPtr onAskUserForFormatOptions(FileOp* fop) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
FileFormat *CreateCssFormat()
|
||||||
|
{
|
||||||
|
return new CssFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CssFormat::onLoad(FileOp* fop)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_SAVE
|
||||||
|
|
||||||
|
bool CssFormat::onSave(FileOp* fop)
|
||||||
|
{
|
||||||
|
const Image* image = fop->sequenceImage();
|
||||||
|
int x, y, c, r, g, b, a, alpha;
|
||||||
|
const auto css_options = std::static_pointer_cast<CssOptions>(fop->formatOptions());
|
||||||
|
FileHandle handle(open_file_with_exception_sync_on_close(fop->filename(), "wb"));
|
||||||
|
FILE* f = handle.get();
|
||||||
|
auto print_color = [f](int r, int g, int b, int a) {
|
||||||
|
if (a == 255) {
|
||||||
|
fprintf(f, "#%02X%02X%02X", r, g, b);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(f, "rgba(%d, %d, %d, %d)", r, g, b, a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
auto print_shadow_color = [f, css_options, print_color](int x, int y, int r,
|
||||||
|
int g, int b, int a,
|
||||||
|
bool comma = true) {
|
||||||
|
fprintf(f, comma?",\n":"\n");
|
||||||
|
if (css_options->withVars) {
|
||||||
|
fprintf(f, "\tcalc(%d*var(--shadow-mult)) calc(%d*var(--shadow-mult)) var(--blur) var(--spread) ",
|
||||||
|
x, y);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int x_loc = x * (css_options->pixelScale + css_options->gutterSize);
|
||||||
|
int y_loc = y * (css_options->pixelScale + css_options->gutterSize);
|
||||||
|
fprintf(f, "%dpx %dpx ", x_loc, y_loc);
|
||||||
|
}
|
||||||
|
print_color(r, g, b, a);
|
||||||
|
};
|
||||||
|
auto print_shadow_index = [f, css_options](int x, int y, int i, bool comma=true) {
|
||||||
|
fprintf(f, comma?",\n":"\n");
|
||||||
|
fprintf(f, "\tcalc(%d*var(--shadow-mult)) calc(%d*var(--shadow-mult)) var(--blur) var(--spread) var(--color-%d)",
|
||||||
|
x, y, i);
|
||||||
|
};
|
||||||
|
if (css_options->withVars) {
|
||||||
|
fprintf(f, ":root {\n"
|
||||||
|
"\t--blur: 0px;\n"
|
||||||
|
"\t--spread: 0px;\n"
|
||||||
|
"\t--pixel-size: %dpx;\n"
|
||||||
|
"\t--gutter-size: %dpx;\n",
|
||||||
|
css_options->pixelScale,
|
||||||
|
css_options->gutterSize);
|
||||||
|
fprintf(f, "\t--shadow-mult: calc(var(--gutter-size) + var(--pixel-size));\n");
|
||||||
|
if (image->pixelFormat() == IMAGE_INDEXED) {
|
||||||
|
for (y = 0; y < 256; y++) {
|
||||||
|
fop->sequenceGetColor(y, &r, &g, &b);
|
||||||
|
fop->sequenceGetAlpha(y, &a);
|
||||||
|
fprintf(f, "\t--color-%d: ", y);
|
||||||
|
print_color(r, g, b, a);
|
||||||
|
fprintf(f, ";\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(f, "}\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(f, ".pixel-art {\n");
|
||||||
|
fprintf(f, "\tposition: relative;\n");
|
||||||
|
fprintf(f, "\ttop: 0;\n");
|
||||||
|
fprintf(f, "\tleft: 0;\n");
|
||||||
|
if (css_options->withVars) {
|
||||||
|
fprintf(f, "\theight: var(--pixel-size);\n");
|
||||||
|
fprintf(f, "\twidth: var(--pixel-size);\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(f, "\theight: %dpx;\n", css_options->pixelScale);
|
||||||
|
fprintf(f, "\twidth: %dpx;\n", css_options->pixelScale);
|
||||||
|
}
|
||||||
|
fprintf(f, "\tbox-shadow:\n");
|
||||||
|
int num_printed_pixels = 0;
|
||||||
|
switch (image->pixelFormat()) {
|
||||||
|
case IMAGE_RGB: {
|
||||||
|
for (y=0; y<image->height(); y++) {
|
||||||
|
for (x=0; x<image->width(); x++) {
|
||||||
|
c = get_pixel_fast<RgbTraits>(image, x, y);
|
||||||
|
alpha = rgba_geta(c);
|
||||||
|
if (alpha != 0x00) {
|
||||||
|
print_shadow_color(x, y, rgba_getr(c), rgba_getg(c), rgba_getb(c),
|
||||||
|
alpha, num_printed_pixels>0);
|
||||||
|
num_printed_pixels ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fop->setProgress((float)y / (float)(image->height()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IMAGE_GRAYSCALE: {
|
||||||
|
for (y=0; y<image->height(); y++) {
|
||||||
|
for (x=0; x<image->width(); x++) {
|
||||||
|
c = get_pixel_fast<GrayscaleTraits>(image, x, y);
|
||||||
|
auto v = graya_getv(c);
|
||||||
|
alpha = graya_geta(c);
|
||||||
|
if (alpha != 0x00) {
|
||||||
|
print_shadow_color(x, y, v, v, v, alpha, num_printed_pixels>0);
|
||||||
|
num_printed_pixels ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fop->setProgress((float)y / (float)(image->height()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IMAGE_INDEXED: {
|
||||||
|
unsigned char image_palette[256][4];
|
||||||
|
for (y=0; !css_options->withVars && y<256; y++) {
|
||||||
|
fop->sequenceGetColor(y, &r, &g, &b);
|
||||||
|
image_palette[y][0] = r;
|
||||||
|
image_palette[y][1] = g;
|
||||||
|
image_palette[y][2] = b;
|
||||||
|
fop->sequenceGetAlpha(y, &a);
|
||||||
|
image_palette[y][3] = a;
|
||||||
|
}
|
||||||
|
color_t mask_color = -1;
|
||||||
|
if (fop->document()->sprite()->backgroundLayer() == NULL ||
|
||||||
|
!fop->document()->sprite()->backgroundLayer()->isVisible()) {
|
||||||
|
mask_color = fop->document()->sprite()->transparentColor();
|
||||||
|
}
|
||||||
|
for (y=0; y<image->height(); y++) {
|
||||||
|
for (x=0; x<image->width(); x++) {
|
||||||
|
c = get_pixel_fast<IndexedTraits>(image, x, y);
|
||||||
|
if (c != mask_color) {
|
||||||
|
if (css_options->withVars) {
|
||||||
|
print_shadow_index(x, y, c, num_printed_pixels>0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_shadow_color(x, y,
|
||||||
|
image_palette[c][0] & 0xff,
|
||||||
|
image_palette[c][1] & 0xff,
|
||||||
|
image_palette[c][2] & 0xff,
|
||||||
|
image_palette[c][3] & 0xff,
|
||||||
|
num_printed_pixels>0);
|
||||||
|
}
|
||||||
|
num_printed_pixels ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fop->setProgress((float)y / (float)(image->height()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(f, ";\n}\n");
|
||||||
|
if (ferror(f)) {
|
||||||
|
fop->setError("Error writing file.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (css_options->generateHtml) {
|
||||||
|
std::string html_filepath = fop->filename() + ".html";
|
||||||
|
FileHandle handle(open_file_with_exception_sync_on_close(html_filepath, "wb"));
|
||||||
|
FILE* h = handle.get();
|
||||||
|
fprintf(h,
|
||||||
|
"<html><head><link rel=\"stylesheet\" media=\"all\" "
|
||||||
|
"href=\"%s\"></head><body><div "
|
||||||
|
"class=\"pixel-art\"></div></body></html>",
|
||||||
|
fop->filename().c_str());
|
||||||
|
if (ferror(h)) {
|
||||||
|
fop->setError("Error writing html file.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Shows the CSS configuration dialog.
|
||||||
|
FormatOptionsPtr CssFormat::onAskUserForFormatOptions(FileOp* fop)
|
||||||
|
{
|
||||||
|
auto opts = fop->formatOptionsOfDocument<CssOptions>();
|
||||||
|
|
||||||
|
#ifdef ENABLE_UI
|
||||||
|
if (fop->context() && fop->context()->isUIAvailable()) {
|
||||||
|
try {
|
||||||
|
auto &pref = Preferences::instance();
|
||||||
|
|
||||||
|
if (pref.isSet(pref.css.pixelScale))
|
||||||
|
opts->pixelScale = pref.css.pixelScale();
|
||||||
|
|
||||||
|
if (pref.isSet(pref.css.withVars))
|
||||||
|
opts->withVars = pref.css.withVars();
|
||||||
|
|
||||||
|
if (pref.isSet(pref.css.generateHtml))
|
||||||
|
opts->generateHtml = pref.css.generateHtml();
|
||||||
|
|
||||||
|
if (pref.css.showAlert()) {
|
||||||
|
app::gen::CssOptions win;
|
||||||
|
win.pixelScale()->setTextf("%d", opts->pixelScale);
|
||||||
|
win.withVars()->setSelected(opts->withVars);
|
||||||
|
win.generateHtml()->setSelected(opts->generateHtml);
|
||||||
|
win.openWindowInForeground();
|
||||||
|
|
||||||
|
if (win.closer() == win.ok()) {
|
||||||
|
pref.css.showAlert(!win.dontShow()->isSelected());
|
||||||
|
pref.css.pixelScale((int)win.pixelScale()->textInt());
|
||||||
|
pref.css.withVars(win.withVars()->isSelected());
|
||||||
|
pref.css.generateHtml(win.generateHtml()->isSelected());
|
||||||
|
|
||||||
|
opts->generateHtml = pref.css.generateHtml();
|
||||||
|
opts->withVars = pref.css.withVars();
|
||||||
|
opts->pixelScale = pref.css.pixelScale();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
opts.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception &e) {
|
||||||
|
Console::showException(e);
|
||||||
|
return std::shared_ptr<CssOptions>(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace app
|
@ -22,6 +22,7 @@ namespace app {
|
|||||||
|
|
||||||
extern FileFormat* CreateAseFormat();
|
extern FileFormat* CreateAseFormat();
|
||||||
extern FileFormat* CreateBmpFormat();
|
extern FileFormat* CreateBmpFormat();
|
||||||
|
extern FileFormat* CreateCssFormat();
|
||||||
extern FileFormat* CreateFliFormat();
|
extern FileFormat* CreateFliFormat();
|
||||||
extern FileFormat* CreateGifFormat();
|
extern FileFormat* CreateGifFormat();
|
||||||
extern FileFormat* CreateIcoFormat();
|
extern FileFormat* CreateIcoFormat();
|
||||||
@ -57,6 +58,7 @@ FileFormatsManager::FileFormatsManager()
|
|||||||
// The first format is the default image format in FileSelector
|
// The first format is the default image format in FileSelector
|
||||||
registerFormat(CreateAseFormat());
|
registerFormat(CreateAseFormat());
|
||||||
registerFormat(CreateBmpFormat());
|
registerFormat(CreateBmpFormat());
|
||||||
|
registerFormat(CreateCssFormat());
|
||||||
registerFormat(CreateFliFormat());
|
registerFormat(CreateFliFormat());
|
||||||
registerFormat(CreateGifFormat());
|
registerFormat(CreateGifFormat());
|
||||||
registerFormat(CreateIcoFormat());
|
registerFormat(CreateIcoFormat());
|
||||||
|
@ -73,7 +73,10 @@ FileFormat* CreateSvgFormat()
|
|||||||
return new SvgFormat;
|
return new SvgFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SvgFormat::onLoad(FileOp* fop) { return false;}
|
bool SvgFormat::onLoad(FileOp* fop)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_SAVE
|
#ifdef ENABLE_SAVE
|
||||||
|
|
||||||
|
@ -161,12 +161,7 @@ bool set_current_palette(const Palette *_palette, bool forced)
|
|||||||
std::string get_preset_palette_filename(const std::string& preset,
|
std::string get_preset_palette_filename(const std::string& preset,
|
||||||
const std::string& dot_extension)
|
const std::string& dot_extension)
|
||||||
{
|
{
|
||||||
ResourceFinder rf;
|
std::string palettesDir = get_preset_palettes_dir();
|
||||||
rf.includeUserDir(base::join_path("palettes", ".").c_str());
|
|
||||||
std::string palettesDir = rf.getFirstOrCreateDefault();
|
|
||||||
|
|
||||||
if (!base::is_directory(palettesDir))
|
|
||||||
base::make_directory(palettesDir);
|
|
||||||
|
|
||||||
return base::join_path(palettesDir, preset + dot_extension);
|
return base::join_path(palettesDir, preset + dot_extension);
|
||||||
}
|
}
|
||||||
@ -176,4 +171,16 @@ std::string get_default_palette_preset_name()
|
|||||||
return "default";
|
return "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string get_preset_palettes_dir()
|
||||||
|
{
|
||||||
|
ResourceFinder rf;
|
||||||
|
rf.includeUserDir(base::join_path("palettes", ".").c_str());
|
||||||
|
std::string palettesDir = rf.getFirstOrCreateDefault();
|
||||||
|
|
||||||
|
if (!base::is_directory(palettesDir))
|
||||||
|
base::make_directory(palettesDir);
|
||||||
|
|
||||||
|
return palettesDir;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -33,6 +33,7 @@ namespace app {
|
|||||||
std::string get_preset_palette_filename(const std::string& preset,
|
std::string get_preset_palette_filename(const std::string& preset,
|
||||||
const std::string& dot_extension);
|
const std::string& dot_extension);
|
||||||
std::string get_default_palette_preset_name();
|
std::string get_default_palette_preset_name();
|
||||||
|
std::string get_preset_palettes_dir();
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2017 David Capello
|
// Copyright (C) 2001-2017 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -8,6 +8,7 @@
|
|||||||
#include "app/util/wrap_point.h"
|
#include "app/util/wrap_point.h"
|
||||||
|
|
||||||
#include "app/tools/ink.h"
|
#include "app/tools/ink.h"
|
||||||
|
#include "doc/algorithm/flip_image.h"
|
||||||
#include "render/gradient.h"
|
#include "render/gradient.h"
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
@ -61,7 +62,7 @@ class BrushPointShape : public PointShape {
|
|||||||
bool m_firstPoint;
|
bool m_firstPoint;
|
||||||
Brush* m_lastBrush;
|
Brush* m_lastBrush;
|
||||||
BrushType m_origBrushType;
|
BrushType m_origBrushType;
|
||||||
std::shared_ptr<CompressedImage> m_compressedImage;
|
std::array<std::shared_ptr<CompressedImage>, 4> m_compressedImages;
|
||||||
// For dynamics
|
// For dynamics
|
||||||
DynamicsOptions m_dynamics;
|
DynamicsOptions m_dynamics;
|
||||||
bool m_useDynamics;
|
bool m_useDynamics;
|
||||||
@ -192,9 +193,7 @@ public:
|
|||||||
// TODO cache compressed images (or remove them completelly)
|
// TODO cache compressed images (or remove them completelly)
|
||||||
if (m_lastBrush != brush) {
|
if (m_lastBrush != brush) {
|
||||||
m_lastBrush = brush;
|
m_lastBrush = brush;
|
||||||
m_compressedImage.reset(new CompressedImage(brush->image(),
|
m_compressedImages.fill(nullptr);
|
||||||
brush->maskBitmap(),
|
|
||||||
false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x += brush->bounds().x;
|
x += brush->bounds().x;
|
||||||
@ -227,7 +226,7 @@ public:
|
|||||||
|
|
||||||
ink->prepareForPointShape(loop, m_firstPoint, x, y);
|
ink->prepareForPointShape(loop, m_firstPoint, x, y);
|
||||||
|
|
||||||
for (auto scanline : *m_compressedImage) {
|
for (auto scanline : getCompressedImage(pt.symmetry)) {
|
||||||
int u = x+scanline.x;
|
int u = x+scanline.x;
|
||||||
ink->prepareVForPointShape(loop, y+scanline.y);
|
ink->prepareVForPointShape(loop, y+scanline.y);
|
||||||
doInkHline(u, y+scanline.y, u+scanline.w-1, loop);
|
doInkHline(u, y+scanline.y, u+scanline.w-1, loop);
|
||||||
@ -241,6 +240,47 @@ public:
|
|||||||
area.y += y;
|
area.y += y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CompressedImage& getCompressedImage(gen::SymmetryMode symmetryMode) {
|
||||||
|
auto& compressPtr = m_compressedImages[int(symmetryMode)];
|
||||||
|
if (!compressPtr) {
|
||||||
|
switch (symmetryMode) {
|
||||||
|
case gen::SymmetryMode::NONE: {
|
||||||
|
compressPtr.reset(new CompressedImage(m_lastBrush->image(),
|
||||||
|
m_lastBrush->maskBitmap(),
|
||||||
|
false));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gen::SymmetryMode::HORIZONTAL:
|
||||||
|
case gen::SymmetryMode::VERTICAL: {
|
||||||
|
std::unique_ptr<Image> tempImage(Image::createCopy(m_lastBrush->image()));
|
||||||
|
doc::algorithm::FlipType flip =
|
||||||
|
(symmetryMode == gen::SymmetryMode::HORIZONTAL)?
|
||||||
|
doc::algorithm::FlipType::FlipHorizontal:
|
||||||
|
doc::algorithm::FlipType::FlipVertical;
|
||||||
|
doc::algorithm::flip_image(tempImage.get(), tempImage->bounds(), flip);
|
||||||
|
compressPtr.reset(new CompressedImage(tempImage.get(),
|
||||||
|
m_lastBrush->maskBitmap(),
|
||||||
|
false));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gen::SymmetryMode::BOTH: {
|
||||||
|
std::unique_ptr<Image> tempImage(Image::createCopy(m_lastBrush->image()));
|
||||||
|
doc::algorithm::flip_image(tempImage.get(),
|
||||||
|
tempImage->bounds(),
|
||||||
|
doc::algorithm::FlipType::FlipVertical);
|
||||||
|
doc::algorithm::flip_image(tempImage.get(),
|
||||||
|
tempImage->bounds(),
|
||||||
|
doc::algorithm::FlipType::FlipHorizontal);
|
||||||
|
compressPtr.reset(new CompressedImage(tempImage.get(),
|
||||||
|
m_lastBrush->maskBitmap(),
|
||||||
|
false));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *compressPtr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FloodFillPointShape : public PointShape {
|
class FloodFillPointShape : public PointShape {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2015 David Capello
|
// Copyright (C) 2001-2015 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -9,6 +9,7 @@
|
|||||||
#define APP_TOOLS_STROKE_H_INCLUDED
|
#define APP_TOOLS_STROKE_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "app/pref/preferences.h"
|
||||||
#include "gfx/point.h"
|
#include "gfx/point.h"
|
||||||
#include "gfx/rect.h"
|
#include "gfx/rect.h"
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ namespace app {
|
|||||||
float size = 0.0f;
|
float size = 0.0f;
|
||||||
float angle = 0.0f;
|
float angle = 0.0f;
|
||||||
float gradient = 0.0f;
|
float gradient = 0.0f;
|
||||||
|
gen::SymmetryMode symmetry = gen::SymmetryMode::NONE;
|
||||||
Pt() { }
|
Pt() { }
|
||||||
Pt(const gfx::Point& point) : x(point.x), y(point.y) { }
|
Pt(const gfx::Point& point) : x(point.x), y(point.y) { }
|
||||||
Pt(int x, int y) : x(x), y(y) { }
|
Pt(int x, int y) : x(x), y(y) { }
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
// Aseprite
|
|
||||||
// Copyright (C) 2020 Igara Studio S.A.
|
|
||||||
// Copyright (C) 2015-2017 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/tools/symmetries.h"
|
|
||||||
|
|
||||||
#include "app/tools/point_shape.h"
|
|
||||||
#include "app/tools/stroke.h"
|
|
||||||
#include "app/tools/tool_loop.h"
|
|
||||||
#include "doc/brush.h"
|
|
||||||
|
|
||||||
namespace app {
|
|
||||||
namespace tools {
|
|
||||||
|
|
||||||
void HorizontalSymmetry::generateStrokes(const Stroke& mainStroke, Strokes& strokes,
|
|
||||||
ToolLoop* loop)
|
|
||||||
{
|
|
||||||
int brushSize, brushCenter;
|
|
||||||
if (loop->getPointShape()->isFloodFill()) {
|
|
||||||
brushSize = 1;
|
|
||||||
brushCenter = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// TODO we should flip the brush center+image+bitmap or just do
|
|
||||||
// the symmetry of all pixels
|
|
||||||
auto brush = loop->getBrush();
|
|
||||||
brushSize = brush->bounds().w;
|
|
||||||
brushCenter = brush->center().x;
|
|
||||||
}
|
|
||||||
|
|
||||||
strokes.push_back(mainStroke);
|
|
||||||
|
|
||||||
Stroke stroke2;
|
|
||||||
for (const auto& pt : mainStroke) {
|
|
||||||
Stroke::Pt pt2 = pt;
|
|
||||||
pt2.x = m_x - ((pt.x-brushCenter) - m_x + 1) - (brushSize - brushCenter - 1);
|
|
||||||
stroke2.addPoint(pt2);
|
|
||||||
}
|
|
||||||
strokes.push_back(stroke2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VerticalSymmetry::generateStrokes(const Stroke& mainStroke, Strokes& strokes,
|
|
||||||
ToolLoop* loop)
|
|
||||||
{
|
|
||||||
int brushSize, brushCenter;
|
|
||||||
if (loop->getPointShape()->isFloodFill()) {
|
|
||||||
brushSize = 1;
|
|
||||||
brushCenter = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
auto brush = loop->getBrush();
|
|
||||||
brushSize = brush->bounds().h;
|
|
||||||
brushCenter = brush->center().y;
|
|
||||||
}
|
|
||||||
|
|
||||||
strokes.push_back(mainStroke);
|
|
||||||
|
|
||||||
Stroke stroke2;
|
|
||||||
for (const auto& pt : mainStroke) {
|
|
||||||
Stroke::Pt pt2 = pt;
|
|
||||||
pt2.y = m_y - ((pt.y-brushCenter) - m_y + 1) - (brushSize - brushCenter - 1);
|
|
||||||
stroke2.addPoint(pt2);
|
|
||||||
}
|
|
||||||
strokes.push_back(stroke2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SymmetryCombo::generateStrokes(const Stroke& mainStroke, Strokes& strokes,
|
|
||||||
ToolLoop* loop)
|
|
||||||
{
|
|
||||||
Strokes strokes0;
|
|
||||||
m_a->generateStrokes(mainStroke, strokes0, loop);
|
|
||||||
for (const Stroke& stroke : strokes0)
|
|
||||||
m_b->generateStrokes(stroke, strokes, loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace tools
|
|
||||||
} // namespace app
|
|
@ -1,50 +0,0 @@
|
|||||||
// Aseprite
|
|
||||||
// Copyright (C) 2015-2018 David Capello
|
|
||||||
//
|
|
||||||
// This program is distributed under the terms of
|
|
||||||
// the End-User License Agreement for Aseprite.
|
|
||||||
|
|
||||||
#ifndef APP_TOOLS_SYMMETRIES_H_INCLUDED
|
|
||||||
#define APP_TOOLS_SYMMETRIES_H_INCLUDED
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "app/tools/stroke.h"
|
|
||||||
#include "app/tools/symmetry.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace app {
|
|
||||||
namespace tools {
|
|
||||||
|
|
||||||
class HorizontalSymmetry : public Symmetry {
|
|
||||||
public:
|
|
||||||
HorizontalSymmetry(double x) : m_x(x) { }
|
|
||||||
void generateStrokes(const Stroke& mainStroke, Strokes& strokes,
|
|
||||||
ToolLoop* loop) override;
|
|
||||||
private:
|
|
||||||
double m_x;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VerticalSymmetry : public Symmetry {
|
|
||||||
public:
|
|
||||||
VerticalSymmetry(double y) : m_y(y) { }
|
|
||||||
void generateStrokes(const Stroke& mainStroke, Strokes& strokes,
|
|
||||||
ToolLoop* loop) override;
|
|
||||||
private:
|
|
||||||
double m_y;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SymmetryCombo : public Symmetry {
|
|
||||||
public:
|
|
||||||
SymmetryCombo(Symmetry* a, Symmetry* b) : m_a(a), m_b(b) { }
|
|
||||||
void generateStrokes(const Stroke& mainStroke, Strokes& strokes,
|
|
||||||
ToolLoop* loop) override;
|
|
||||||
private:
|
|
||||||
std::unique_ptr<tools::Symmetry> m_a;
|
|
||||||
std::unique_ptr<tools::Symmetry> m_b;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace tools
|
|
||||||
} // namespace app
|
|
||||||
|
|
||||||
#endif
|
|
91
src/app/tools/symmetry.cpp
Normal file
91
src/app/tools/symmetry.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2021 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// 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/tools/symmetry.h"
|
||||||
|
|
||||||
|
#include "app/tools/point_shape.h"
|
||||||
|
#include "app/tools/tool_loop.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
namespace tools {
|
||||||
|
|
||||||
|
void Symmetry::generateStrokes(const Stroke& stroke, Strokes& strokes,
|
||||||
|
ToolLoop* loop)
|
||||||
|
{
|
||||||
|
Stroke stroke2;
|
||||||
|
strokes.push_back(stroke);
|
||||||
|
gen::SymmetryMode symmetryMode = loop->getSymmetry()->mode();
|
||||||
|
switch (symmetryMode) {
|
||||||
|
case gen::SymmetryMode::NONE:
|
||||||
|
ASSERT(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case gen::SymmetryMode::HORIZONTAL:
|
||||||
|
case gen::SymmetryMode::VERTICAL:
|
||||||
|
calculateSymmetricalStroke(stroke, stroke2, loop, symmetryMode);
|
||||||
|
strokes.push_back(stroke2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case gen::SymmetryMode::BOTH: {
|
||||||
|
calculateSymmetricalStroke(stroke, stroke2, loop, gen::SymmetryMode::HORIZONTAL);
|
||||||
|
strokes.push_back(stroke2);
|
||||||
|
|
||||||
|
Stroke stroke3;
|
||||||
|
calculateSymmetricalStroke(stroke, stroke3, loop, gen::SymmetryMode::VERTICAL);
|
||||||
|
strokes.push_back(stroke3);
|
||||||
|
|
||||||
|
Stroke stroke4;
|
||||||
|
calculateSymmetricalStroke(stroke3, stroke4, loop, gen::SymmetryMode::BOTH);
|
||||||
|
strokes.push_back(stroke4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Symmetry::calculateSymmetricalStroke(const Stroke& refStroke, Stroke& stroke,
|
||||||
|
ToolLoop* loop, gen::SymmetryMode symmetryMode)
|
||||||
|
{
|
||||||
|
int brushSize, brushCenter;
|
||||||
|
if (loop->getPointShape()->isFloodFill()) {
|
||||||
|
brushSize = 1;
|
||||||
|
brushCenter = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO we should flip the brush center+image+bitmap or just do
|
||||||
|
// the symmetry of all pixels
|
||||||
|
auto brush = loop->getBrush();
|
||||||
|
if (symmetryMode == gen::SymmetryMode::HORIZONTAL || symmetryMode == gen::SymmetryMode::BOTH) {
|
||||||
|
brushSize = brush->bounds().w;
|
||||||
|
brushCenter = brush->center().x;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
brushSize = brush->bounds().h;
|
||||||
|
brushCenter = brush->center().y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool isDynamic = loop->getDynamics().isDynamic();
|
||||||
|
for (const auto& pt : refStroke) {
|
||||||
|
if (isDynamic) {
|
||||||
|
brushSize = pt.size;
|
||||||
|
brushCenter = (brushSize - brushSize % 2) / 2;
|
||||||
|
}
|
||||||
|
Stroke::Pt pt2 = pt;
|
||||||
|
pt2.symmetry = symmetryMode;
|
||||||
|
if (symmetryMode == gen::SymmetryMode::HORIZONTAL || symmetryMode == gen::SymmetryMode::BOTH)
|
||||||
|
pt2.x = 2 * (m_x + brushCenter) - pt2.x - brushSize;
|
||||||
|
else
|
||||||
|
pt2.y = 2 * (m_y + brushCenter) - pt2.y - brushSize;
|
||||||
|
stroke.addPoint(pt2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tools
|
||||||
|
} // namespace app
|
@ -1,4 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
|
// Copyright (C) 2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2015 David Capello
|
// Copyright (C) 2015 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -9,24 +10,34 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "app/tools/stroke.h"
|
#include "app/tools/stroke.h"
|
||||||
|
#include "app/pref/preferences.h"
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
namespace tools {
|
namespace tools {
|
||||||
|
|
||||||
class ToolLoop;
|
class ToolLoop;
|
||||||
|
|
||||||
// This class controls user input.
|
class Symmetry {
|
||||||
class Symmetry {
|
public:
|
||||||
public:
|
Symmetry(gen::SymmetryMode symmetryMode, double x, double y)
|
||||||
virtual ~Symmetry() { }
|
: m_symmetryMode(symmetryMode)
|
||||||
|
, m_x(x)
|
||||||
|
, m_y(y) {
|
||||||
|
}
|
||||||
|
|
||||||
// The "stroke" must be relative to the sprite origin.
|
void generateStrokes(const Stroke& stroke, Strokes& strokes, ToolLoop* loop);
|
||||||
virtual void generateStrokes(const Stroke& stroke, Strokes& strokes, ToolLoop* loop) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace tools
|
gen::SymmetryMode mode() const { return m_symmetryMode; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calculateSymmetricalStroke(const Stroke& refStroke, Stroke& stroke,
|
||||||
|
ToolLoop* loop, gen::SymmetryMode symmetryMode);
|
||||||
|
|
||||||
|
gen::SymmetryMode m_symmetryMode;
|
||||||
|
double m_x, m_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace tools
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2016-2017 David Capello
|
// Copyright (C) 2016-2017 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -16,6 +16,7 @@
|
|||||||
#include "app/ui/main_window.h"
|
#include "app/ui/main_window.h"
|
||||||
#include "app/ui/separator_in_view.h"
|
#include "app/ui/separator_in_view.h"
|
||||||
#include "app/ui/skin/skin_theme.h"
|
#include "app/ui/skin/skin_theme.h"
|
||||||
|
#include "app/ui/status_bar.h"
|
||||||
#include "app/ui/workspace.h"
|
#include "app/ui/workspace.h"
|
||||||
#include "base/file_handle.h"
|
#include "base/file_handle.h"
|
||||||
#include "base/fs.h"
|
#include "base/fs.h"
|
||||||
@ -572,7 +573,8 @@ WorkspaceView* BrowserView::cloneWorkspaceView()
|
|||||||
|
|
||||||
void BrowserView::onWorkspaceViewSelected()
|
void BrowserView::onWorkspaceViewSelected()
|
||||||
{
|
{
|
||||||
// Do nothing
|
if (auto statusBar = StatusBar::instance())
|
||||||
|
statusBar->clearText();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BrowserView::onCloseView(Workspace* workspace, bool quitting)
|
bool BrowserView::onCloseView(Workspace* workspace, bool quitting)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2017 David Capello
|
// Copyright (C) 2001-2017 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
#include "app/app_menus.h"
|
#include "app/app_menus.h"
|
||||||
|
#include "app/console.h"
|
||||||
#include "app/crash/data_recovery.h"
|
#include "app/crash/data_recovery.h"
|
||||||
#include "app/crash/session.h"
|
#include "app/crash/session.h"
|
||||||
#include "app/doc.h"
|
#include "app/doc.h"
|
||||||
@ -106,19 +107,31 @@ public:
|
|||||||
|
|
||||||
m_task = new TaskWidget(
|
m_task = new TaskWidget(
|
||||||
TaskWidget::kCannotCancel,
|
TaskWidget::kCannotCancel,
|
||||||
[this](base::task_token& t){
|
[this](base::task_token& t) {
|
||||||
// Warning: This is executed from a worker thread
|
try {
|
||||||
m_session->deleteBackup(m_backup);
|
// Warning: This is executed from a worker thread
|
||||||
ui::execute_from_ui_thread(
|
m_session->deleteBackup(m_backup);
|
||||||
[this]{
|
|
||||||
onDeleteTaskWidget();
|
|
||||||
|
|
||||||
// We cannot use this->deferDelete() here because it looks
|
ui::execute_from_ui_thread(
|
||||||
// like the m_task field can be still in use.
|
[this]{
|
||||||
setVisible(false);
|
onDeleteTaskWidget();
|
||||||
|
|
||||||
updateView();
|
// We cannot use this->deferDelete() here because it looks
|
||||||
});
|
// like the m_task field can be still in use.
|
||||||
|
setVisible(false);
|
||||||
|
|
||||||
|
updateView();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (const std::exception& ex) {
|
||||||
|
std::string err = ex.what();
|
||||||
|
if (!err.empty()) {
|
||||||
|
ui::execute_from_ui_thread(
|
||||||
|
[err]{
|
||||||
|
Console().printf("Error deleting file: %s", err.c_str());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
addChild(m_task);
|
addChild(m_task);
|
||||||
updateView();
|
updateView();
|
||||||
@ -477,6 +490,7 @@ void DataRecoveryView::onDelete()
|
|||||||
int(items.size()))) != 1)
|
int(items.size()))) != 1)
|
||||||
return; // Cancel
|
return; // Cancel
|
||||||
|
|
||||||
|
Console console;
|
||||||
for (auto item : items)
|
for (auto item : items)
|
||||||
item->deleteBackup();
|
item->deleteBackup();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -248,7 +248,8 @@ WorkspaceView* DocView::cloneWorkspaceView()
|
|||||||
|
|
||||||
void DocView::onWorkspaceViewSelected()
|
void DocView::onWorkspaceViewSelected()
|
||||||
{
|
{
|
||||||
StatusBar::instance()->showDefaultText(m_document);
|
if (auto statusBar = StatusBar::instance())
|
||||||
|
statusBar->showDefaultText(m_document);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocView::onClonedFrom(WorkspaceView* from)
|
void DocView::onClonedFrom(WorkspaceView* from)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -29,7 +29,7 @@
|
|||||||
#include "app/tools/freehand_algorithm.h"
|
#include "app/tools/freehand_algorithm.h"
|
||||||
#include "app/tools/ink.h"
|
#include "app/tools/ink.h"
|
||||||
#include "app/tools/point_shape.h"
|
#include "app/tools/point_shape.h"
|
||||||
#include "app/tools/symmetries.h"
|
#include "app/tools/symmetry.h"
|
||||||
#include "app/tools/tool.h"
|
#include "app/tools/tool.h"
|
||||||
#include "app/tools/tool_box.h"
|
#include "app/tools/tool_box.h"
|
||||||
#include "app/tools/tool_loop.h"
|
#include "app/tools/tool_loop.h"
|
||||||
@ -239,27 +239,10 @@ public:
|
|||||||
|
|
||||||
// Symmetry mode
|
// Symmetry mode
|
||||||
if (Preferences::instance().symmetryMode.enabled()) {
|
if (Preferences::instance().symmetryMode.enabled()) {
|
||||||
switch (m_docPref.symmetry.mode()) {
|
if (m_docPref.symmetry.mode() != gen::SymmetryMode::NONE)
|
||||||
|
m_symmetry.reset(new tools::Symmetry(m_docPref.symmetry.mode(),
|
||||||
case app::gen::SymmetryMode::NONE:
|
m_docPref.symmetry.xAxis(),
|
||||||
ASSERT(m_symmetry == nullptr);
|
m_docPref.symmetry.yAxis()));
|
||||||
break;
|
|
||||||
|
|
||||||
case app::gen::SymmetryMode::HORIZONTAL:
|
|
||||||
m_symmetry.reset(new app::tools::HorizontalSymmetry(m_docPref.symmetry.xAxis()));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case app::gen::SymmetryMode::VERTICAL:
|
|
||||||
m_symmetry.reset(new app::tools::VerticalSymmetry(m_docPref.symmetry.yAxis()));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case app::gen::SymmetryMode::BOTH:
|
|
||||||
m_symmetry.reset(
|
|
||||||
new app::tools::SymmetryCombo(
|
|
||||||
new app::tools::HorizontalSymmetry(m_docPref.symmetry.xAxis()),
|
|
||||||
new app::tools::VerticalSymmetry(m_docPref.symmetry.yAxis())));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore opacity for these inks
|
// Ignore opacity for these inks
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -261,9 +261,19 @@ void MainWindow::showHome()
|
|||||||
m_tabsBar->selectTab(m_homeView);
|
m_tabsBar->selectTab(m_homeView);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::isHomeSelected()
|
void MainWindow::showDefaultStatusBar()
|
||||||
{
|
{
|
||||||
return (m_tabsBar->getSelectedTab() == m_homeView && m_homeView);
|
if (DocView* docView = getDocView())
|
||||||
|
m_statusBar->showDefaultText(docView->document());
|
||||||
|
else if (isHomeSelected())
|
||||||
|
m_statusBar->showAbout();
|
||||||
|
else
|
||||||
|
m_statusBar->clearText();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWindow::isHomeSelected() const
|
||||||
|
{
|
||||||
|
return (m_homeView && m_workspace->activeView() == m_homeView);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showBrowser(const std::string& filename)
|
void MainWindow::showBrowser(const std::string& filename)
|
||||||
@ -473,12 +483,12 @@ void MainWindow::onTabsContainerDoubleClicked(Tabs* tabs)
|
|||||||
void MainWindow::onMouseOverTab(Tabs* tabs, TabView* tabView)
|
void MainWindow::onMouseOverTab(Tabs* tabs, TabView* tabView)
|
||||||
{
|
{
|
||||||
// Note: tabView can be NULL
|
// Note: tabView can be NULL
|
||||||
if (DocView* docView = dynamic_cast<DocView*>(tabView)) {
|
if (DocView* docView = dynamic_cast<DocView*>(tabView))
|
||||||
m_statusBar->showDefaultText(docView->document());
|
m_statusBar->showDefaultText(docView->document());
|
||||||
}
|
else if (tabView)
|
||||||
else {
|
m_statusBar->setStatusText(0, tabView->getTabText());
|
||||||
|
else
|
||||||
m_statusBar->showDefaultText();
|
m_statusBar->showDefaultText();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onMouseLeaveTab()
|
void MainWindow::onMouseLeaveTab()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -71,9 +71,10 @@ namespace app {
|
|||||||
void showNotification(INotificationDelegate* del);
|
void showNotification(INotificationDelegate* del);
|
||||||
void showHomeOnOpen();
|
void showHomeOnOpen();
|
||||||
void showHome();
|
void showHome();
|
||||||
bool isHomeSelected();
|
void showDefaultStatusBar();
|
||||||
void showDevConsole();
|
void showDevConsole();
|
||||||
void showBrowser(const std::string& filename);
|
void showBrowser(const std::string& filename);
|
||||||
|
bool isHomeSelected() const;
|
||||||
|
|
||||||
Mode getMode() const { return m_mode; }
|
Mode getMode() const { return m_mode; }
|
||||||
void setMode(Mode mode);
|
void setMode(Mode mode);
|
||||||
|
@ -42,6 +42,7 @@ PalettePopup::PalettePopup()
|
|||||||
addChild(m_popup);
|
addChild(m_popup);
|
||||||
|
|
||||||
m_paletteListBox.DoubleClickItem.connect([this]{ onLoadPal(); });
|
m_paletteListBox.DoubleClickItem.connect([this]{ onLoadPal(); });
|
||||||
|
m_paletteListBox.FinishLoading.connect([this]{ onSearchChange(); });
|
||||||
m_popup->search()->Change.connect([this]{ onSearchChange(); });
|
m_popup->search()->Change.connect([this]{ onSearchChange(); });
|
||||||
m_popup->loadPal()->Click.connect([this]{ onLoadPal(); });
|
m_popup->loadPal()->Click.connect([this]{ onLoadPal(); });
|
||||||
m_popup->openFolder()->Click.connect([this]{ onOpenFolder(); });
|
m_popup->openFolder()->Click.connect([this]{ onOpenFolder(); });
|
||||||
|
@ -124,6 +124,9 @@ PalettesListBox::PalettesListBox()
|
|||||||
m_extPaletteChanges =
|
m_extPaletteChanges =
|
||||||
App::instance()->extensions().PalettesChange.connect(
|
App::instance()->extensions().PalettesChange.connect(
|
||||||
[this]{ reload(); });
|
[this]{ reload(); });
|
||||||
|
m_extPresetsChanges =
|
||||||
|
App::instance()->PalettePresetsChange.connect(
|
||||||
|
[this]{ reload(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
doc::Palette* PalettesListBox::selectedPalette()
|
doc::Palette* PalettesListBox::selectedPalette()
|
||||||
|
@ -34,6 +34,7 @@ namespace app {
|
|||||||
|
|
||||||
ui::TooltipManager m_tooltips;
|
ui::TooltipManager m_tooltips;
|
||||||
obs::scoped_connection m_extPaletteChanges;
|
obs::scoped_connection m_extPaletteChanges;
|
||||||
|
obs::scoped_connection m_extPresetsChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -211,8 +211,10 @@ void ResourcesListBox::onTick()
|
|||||||
listItem.release();
|
listItem.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_resourcesLoader->isDone())
|
if (m_resourcesLoader->isDone()) {
|
||||||
|
FinishLoading();
|
||||||
stop();
|
stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourcesListBox::stop()
|
void ResourcesListBox::stop()
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "app/res/resources_loader.h"
|
#include "app/res/resources_loader.h"
|
||||||
|
#include "obs/signal.h"
|
||||||
#include "ui/listbox.h"
|
#include "ui/listbox.h"
|
||||||
#include "ui/listitem.h"
|
#include "ui/listitem.h"
|
||||||
#include "ui/timer.h"
|
#include "ui/timer.h"
|
||||||
@ -43,6 +44,8 @@ class ResourceListItem : public ui::ListItem {
|
|||||||
|
|
||||||
void reload();
|
void reload();
|
||||||
|
|
||||||
|
obs::signal<void()> FinishLoading;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool onProcessMessage(ui::Message* msg) override;
|
virtual bool onProcessMessage(ui::Message* msg) override;
|
||||||
virtual void onChange() override;
|
virtual void onChange() override;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -61,6 +61,40 @@ using namespace gfx;
|
|||||||
using namespace ui;
|
using namespace ui;
|
||||||
using namespace doc;
|
using namespace doc;
|
||||||
|
|
||||||
|
class StatusBar::AboutStatusBar : public HBox {
|
||||||
|
public:
|
||||||
|
AboutStatusBar()
|
||||||
|
: m_label(fmt::format("{} {} by ", get_app_name(), get_app_version()))
|
||||||
|
, m_link("", "Igara Studio")
|
||||||
|
{
|
||||||
|
m_link.Click.connect(
|
||||||
|
[]{
|
||||||
|
Command* cmd = Commands::instance()->byId(CommandId::About());
|
||||||
|
UIContext::instance()->executeCommandFromMenuOrShortcut(cmd);
|
||||||
|
});
|
||||||
|
|
||||||
|
addChild(new BoxFiller);
|
||||||
|
addChild(&m_label);
|
||||||
|
addChild(&m_link);
|
||||||
|
addChild(new BoxFiller);
|
||||||
|
|
||||||
|
InitTheme.connect(
|
||||||
|
[this]{
|
||||||
|
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
|
||||||
|
ui::Style* style = theme->styles.workspaceLink();
|
||||||
|
noBorderNoChildSpacing();
|
||||||
|
m_label.setStyle(style);
|
||||||
|
m_link.setStyle(style);
|
||||||
|
m_label.noBorderNoChildSpacing();
|
||||||
|
m_link.noBorderNoChildSpacing();
|
||||||
|
});
|
||||||
|
initTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::Label m_label;
|
||||||
|
ui::LinkLabel m_link;
|
||||||
|
};
|
||||||
|
|
||||||
class StatusBar::Indicators : public HBox {
|
class StatusBar::Indicators : public HBox {
|
||||||
|
|
||||||
class Indicator : public Widget {
|
class Indicator : public Widget {
|
||||||
@ -632,6 +666,7 @@ StatusBar* StatusBar::m_instance = NULL;
|
|||||||
|
|
||||||
StatusBar::StatusBar(TooltipManager* tooltipManager)
|
StatusBar::StatusBar(TooltipManager* tooltipManager)
|
||||||
: m_timeout(0)
|
: m_timeout(0)
|
||||||
|
, m_about(new AboutStatusBar)
|
||||||
, m_indicators(new Indicators)
|
, m_indicators(new Indicators)
|
||||||
, m_docControls(new HBox)
|
, m_docControls(new HBox)
|
||||||
, m_tipwindow(nullptr)
|
, m_tipwindow(nullptr)
|
||||||
@ -642,8 +677,12 @@ StatusBar::StatusBar(TooltipManager* tooltipManager)
|
|||||||
setDoubleBuffered(true);
|
setDoubleBuffered(true);
|
||||||
setFocusStop(true);
|
setFocusStop(true);
|
||||||
|
|
||||||
|
m_about->setExpansive(true);
|
||||||
|
m_about->setVisible(true);
|
||||||
m_indicators->setExpansive(true);
|
m_indicators->setExpansive(true);
|
||||||
|
m_indicators->setVisible(false);
|
||||||
m_docControls->setVisible(false);
|
m_docControls->setVisible(false);
|
||||||
|
addChild(m_about);
|
||||||
addChild(m_indicators);
|
addChild(m_indicators);
|
||||||
addChild(m_docControls);
|
addChild(m_docControls);
|
||||||
|
|
||||||
@ -698,6 +737,7 @@ void StatusBar::onSelectedToolChange(tools::Tool* tool)
|
|||||||
|
|
||||||
void StatusBar::clearText()
|
void StatusBar::clearText()
|
||||||
{
|
{
|
||||||
|
showIndicators();
|
||||||
setStatusText(1, std::string());
|
setStatusText(1, std::string());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,16 +746,11 @@ void StatusBar::clearText()
|
|||||||
// details of the main window/docs/etc.
|
// details of the main window/docs/etc.
|
||||||
void StatusBar::showDefaultText()
|
void StatusBar::showDefaultText()
|
||||||
{
|
{
|
||||||
if (current_editor) {
|
auto mainWindow = (App::instance() ? App::instance()->mainWindow(): nullptr);
|
||||||
showDefaultText(current_editor->document());
|
if (mainWindow)
|
||||||
}
|
mainWindow->showDefaultStatusBar();
|
||||||
else if (App::instance()->mainWindow()->isHomeSelected()) {
|
else
|
||||||
setStatusText(0, fmt::format("-- {} {} by David & Gaspar Capello -- Igara Studio --",
|
|
||||||
get_app_name(), get_app_version()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
clearText();
|
clearText();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusBar::showDefaultText(Doc* doc)
|
void StatusBar::showDefaultText(Doc* doc)
|
||||||
@ -742,18 +777,22 @@ void StatusBar::showDefaultText(Doc* doc)
|
|||||||
|
|
||||||
void StatusBar::updateFromEditor(Editor* editor)
|
void StatusBar::updateFromEditor(Editor* editor)
|
||||||
{
|
{
|
||||||
if (editor)
|
if (editor) {
|
||||||
|
showIndicators();
|
||||||
m_zoomEntry->setZoom(editor->zoom());
|
m_zoomEntry->setZoom(editor->zoom());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusBar::showBackupIcon(BackupIcon icon)
|
void StatusBar::showBackupIcon(BackupIcon icon)
|
||||||
{
|
{
|
||||||
|
showIndicators();
|
||||||
m_indicators->showBackupIcon(icon);
|
m_indicators->showBackupIcon(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StatusBar::setStatusText(int msecs, const std::string& msg)
|
bool StatusBar::setStatusText(int msecs, const std::string& msg)
|
||||||
{
|
{
|
||||||
if ((base::current_tick() > m_timeout) || (msecs > 0)) {
|
if ((base::current_tick() > m_timeout) || (msecs > 0)) {
|
||||||
|
showIndicators();
|
||||||
IndicatorsGeneration(m_indicators).add(msg.c_str());
|
IndicatorsGeneration(m_indicators).add(msg.c_str());
|
||||||
m_timeout = base::current_tick() + msecs;
|
m_timeout = base::current_tick() + msecs;
|
||||||
return true;
|
return true;
|
||||||
@ -795,6 +834,7 @@ void StatusBar::showTip(int msecs, const std::string& msg)
|
|||||||
void StatusBar::showColor(int msecs, const char* text, const app::Color& color)
|
void StatusBar::showColor(int msecs, const char* text, const app::Color& color)
|
||||||
{
|
{
|
||||||
if ((base::current_tick() > m_timeout) || (msecs > 0)) {
|
if ((base::current_tick() > m_timeout) || (msecs > 0)) {
|
||||||
|
showIndicators();
|
||||||
IndicatorsGeneration gen(m_indicators);
|
IndicatorsGeneration gen(m_indicators);
|
||||||
gen.add(color);
|
gen.add(color);
|
||||||
if (text)
|
if (text)
|
||||||
@ -818,7 +858,9 @@ void StatusBar::showTile(int msecs, const char* text, doc::tile_t tile)
|
|||||||
|
|
||||||
void StatusBar::showTool(int msecs, tools::Tool* tool)
|
void StatusBar::showTool(int msecs, tools::Tool* tool)
|
||||||
{
|
{
|
||||||
ASSERT(tool != NULL);
|
showIndicators();
|
||||||
|
|
||||||
|
ASSERT(tool != nullptr);
|
||||||
IndicatorsGeneration(m_indicators).add(tool);
|
IndicatorsGeneration(m_indicators).add(tool);
|
||||||
|
|
||||||
m_timeout = base::current_tick() + msecs;
|
m_timeout = base::current_tick() + msecs;
|
||||||
@ -946,4 +988,22 @@ void StatusBar::updateSnapToGridWindowPosition()
|
|||||||
rc.y-m_snapToGridWindow->bounds().h);
|
rc.y-m_snapToGridWindow->bounds().h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StatusBar::showAbout()
|
||||||
|
{
|
||||||
|
if (!m_about->isVisible()) {
|
||||||
|
m_indicators->setVisible(false);
|
||||||
|
m_about->setVisible(true);
|
||||||
|
m_about->layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusBar::showIndicators()
|
||||||
|
{
|
||||||
|
if (!m_indicators->isVisible()) {
|
||||||
|
m_about->setVisible(false);
|
||||||
|
m_indicators->setVisible(true);
|
||||||
|
m_indicators->layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -56,7 +56,8 @@ namespace app {
|
|||||||
|
|
||||||
void clearText();
|
void clearText();
|
||||||
void showDefaultText();
|
void showDefaultText();
|
||||||
void showDefaultText(Doc* document);
|
void showDefaultText(Doc* doc);
|
||||||
|
void showAbout();
|
||||||
|
|
||||||
bool setStatusText(int msecs, const std::string& text);
|
bool setStatusText(int msecs, const std::string& text);
|
||||||
void showTip(int msecs, const std::string& msg);
|
void showTip(int msecs, const std::string& msg);
|
||||||
@ -88,9 +89,14 @@ namespace app {
|
|||||||
void newFrame();
|
void newFrame();
|
||||||
void onChangeZoom(const render::Zoom& zoom);
|
void onChangeZoom(const render::Zoom& zoom);
|
||||||
void updateSnapToGridWindowPosition();
|
void updateSnapToGridWindowPosition();
|
||||||
|
void showIndicators();
|
||||||
|
|
||||||
base::tick_t m_timeout;
|
base::tick_t m_timeout;
|
||||||
|
|
||||||
|
// About text
|
||||||
|
class AboutStatusBar;
|
||||||
|
AboutStatusBar* m_about;
|
||||||
|
|
||||||
// Indicators
|
// Indicators
|
||||||
class Indicators;
|
class Indicators;
|
||||||
class IndicatorsGeneration;
|
class IndicatorsGeneration;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -100,16 +100,17 @@ void UIContext::setActiveView(DocView* docView)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (docView) {
|
if (docView) {
|
||||||
|
current_editor = docView->editor();
|
||||||
mainWin->getTabsBar()->selectTab(docView);
|
mainWin->getTabsBar()->selectTab(docView);
|
||||||
|
|
||||||
if (mainWin->getWorkspace()->activeView() != docView)
|
if (mainWin->getWorkspace()->activeView() != docView)
|
||||||
mainWin->getWorkspace()->setActiveView(docView);
|
mainWin->getWorkspace()->setActiveView(docView);
|
||||||
|
|
||||||
|
if (current_editor)
|
||||||
|
current_editor->requestFocus();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
current_editor = (docView ? docView->editor(): nullptr);
|
current_editor = nullptr;
|
||||||
|
|
||||||
if (current_editor)
|
|
||||||
current_editor->requestFocus();
|
|
||||||
|
|
||||||
mainWin->getPreviewEditor()->updateUsingEditor(current_editor);
|
mainWin->getPreviewEditor()->updateUsingEditor(current_editor);
|
||||||
mainWin->getTimeline()->updateUsingEditor(current_editor);
|
mainWin->getTimeline()->updateUsingEditor(current_editor);
|
||||||
|
@ -141,6 +141,9 @@ FileFormat detect_format_by_file_extension(const std::string& filename)
|
|||||||
if (ext == "tga")
|
if (ext == "tga")
|
||||||
return FileFormat::TARGA_IMAGE;
|
return FileFormat::TARGA_IMAGE;
|
||||||
|
|
||||||
|
if (ext == "css")
|
||||||
|
return FileFormat::CSS_STYLE;
|
||||||
|
|
||||||
if (ext == "webp")
|
if (ext == "webp")
|
||||||
return FileFormat::WEBP_ANIMATION;
|
return FileFormat::WEBP_ANIMATION;
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ enum class FileFormat {
|
|||||||
SVG_IMAGE,
|
SVG_IMAGE,
|
||||||
TARGA_IMAGE,
|
TARGA_IMAGE,
|
||||||
WEBP_ANIMATION,
|
WEBP_ANIMATION,
|
||||||
|
CSS_STYLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dio
|
} // namespace dio
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#define DOC_KEYFRAMES_H_INCLUDED
|
#define DOC_KEYFRAMES_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/disable_copying.h"
|
|
||||||
#include "doc/frame.h"
|
#include "doc/frame.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -111,6 +110,11 @@ namespace doc {
|
|||||||
|
|
||||||
Keyframes() { }
|
Keyframes() { }
|
||||||
|
|
||||||
|
Keyframes(const Keyframes& other) {
|
||||||
|
for (const auto& key : other.m_keys)
|
||||||
|
m_keys.push_back(Key(key.frame(), new T(*key.value())));
|
||||||
|
}
|
||||||
|
|
||||||
void insert(const frame_t frame, T* value) {
|
void insert(const frame_t frame, T* value) {
|
||||||
auto it = getIterator(frame);
|
auto it = getIterator(frame);
|
||||||
if (it == end())
|
if (it == end())
|
||||||
@ -189,9 +193,6 @@ namespace doc {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
List m_keys;
|
List m_keys;
|
||||||
|
|
||||||
// Disable operator=
|
|
||||||
DISABLE_COPYING(Keyframes);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace doc
|
} // namespace doc
|
||||||
|
@ -42,6 +42,14 @@ Slice::Slice()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Slice::Slice(const Slice& other)
|
||||||
|
: WithUserData(other)
|
||||||
|
, m_owner(nullptr)
|
||||||
|
, m_name(other.m_name)
|
||||||
|
, m_keys(other.m_keys)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Slice::~Slice()
|
Slice::~Slice()
|
||||||
{
|
{
|
||||||
ASSERT(!m_owner);
|
ASSERT(!m_owner);
|
||||||
|
@ -55,6 +55,7 @@ namespace doc {
|
|||||||
typedef List::const_iterator const_iterator;
|
typedef List::const_iterator const_iterator;
|
||||||
|
|
||||||
Slice();
|
Slice();
|
||||||
|
Slice(const Slice& other);
|
||||||
~Slice();
|
~Slice();
|
||||||
|
|
||||||
int getMemSize() const override;
|
int getMemSize() const override;
|
||||||
@ -90,8 +91,6 @@ namespace doc {
|
|||||||
Slices* m_owner;
|
Slices* m_owner;
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
List m_keys;
|
List m_keys;
|
||||||
|
|
||||||
DISABLE_COPYING(Slice);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace doc
|
} // namespace doc
|
||||||
|
@ -23,7 +23,7 @@ BEGIN
|
|||||||
VALUE "FileDescription", "Aseprite - Animated sprites editor & pixel art tool"
|
VALUE "FileDescription", "Aseprite - Animated sprites editor & pixel art tool"
|
||||||
VALUE "FileVersion", "1,3,0,0"
|
VALUE "FileVersion", "1,3,0,0"
|
||||||
VALUE "InternalName", "aseprite"
|
VALUE "InternalName", "aseprite"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2001-2020 Igara Studio S.A."
|
VALUE "LegalCopyright", "Copyright (C) 2001-2021 Igara Studio S.A."
|
||||||
VALUE "OriginalFilename", "aseprite.exe"
|
VALUE "OriginalFilename", "aseprite.exe"
|
||||||
VALUE "ProductName", "ASEPRITE"
|
VALUE "ProductName", "ASEPRITE"
|
||||||
VALUE "ProductVersion", "1,3,0,0"
|
VALUE "ProductVersion", "1,3,0,0"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite UI Library
|
// Aseprite UI Library
|
||||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
@ -106,7 +106,11 @@ Widget::~Widget()
|
|||||||
|
|
||||||
void Widget::deferDelete()
|
void Widget::deferDelete()
|
||||||
{
|
{
|
||||||
manager()->addToGarbage(this);
|
if (auto man = manager())
|
||||||
|
man->addToGarbage(this);
|
||||||
|
else {
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::initTheme()
|
void Widget::initTheme()
|
||||||
@ -219,7 +223,8 @@ void Widget::setVisible(bool state)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!hasFlags(HIDDEN)) {
|
if (!hasFlags(HIDDEN)) {
|
||||||
manager()->freeWidget(this); // Free from manager
|
if (auto man = manager())
|
||||||
|
man->freeWidget(this); // Free from manager
|
||||||
enableFlags(HIDDEN);
|
enableFlags(HIDDEN);
|
||||||
|
|
||||||
onVisible(false);
|
onVisible(false);
|
||||||
@ -241,7 +246,8 @@ void Widget::setEnabled(bool state)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!hasFlags(DISABLED)) {
|
if (!hasFlags(DISABLED)) {
|
||||||
manager()->freeWidget(this); // Free from the manager
|
if (auto man = manager())
|
||||||
|
man->freeWidget(this); // Free from the manager
|
||||||
|
|
||||||
enableFlags(DISABLED);
|
enableFlags(DISABLED);
|
||||||
invalidate();
|
invalidate();
|
||||||
@ -541,9 +547,8 @@ void Widget::removeChild(WidgetsList::iterator& it)
|
|||||||
m_children.erase(it);
|
m_children.erase(it);
|
||||||
|
|
||||||
// Free from manager
|
// Free from manager
|
||||||
Manager* manager = this->manager();
|
if (auto man = manager())
|
||||||
if (manager)
|
man->freeWidget(child);
|
||||||
manager->freeWidget(child);
|
|
||||||
|
|
||||||
child->m_parent = nullptr;
|
child->m_parent = nullptr;
|
||||||
}
|
}
|
||||||
@ -617,7 +622,8 @@ void Widget::layout()
|
|||||||
void Widget::loadLayout()
|
void Widget::loadLayout()
|
||||||
{
|
{
|
||||||
if (!m_id.empty()) {
|
if (!m_id.empty()) {
|
||||||
LayoutIO* io = manager()->getLayoutIO();
|
auto man = manager();
|
||||||
|
LayoutIO* io = (man ? man->getLayoutIO(): nullptr);
|
||||||
if (io) {
|
if (io) {
|
||||||
std::string layout = io->loadLayout(this);
|
std::string layout = io->loadLayout(this);
|
||||||
if (!layout.empty()) {
|
if (!layout.empty()) {
|
||||||
@ -636,7 +642,8 @@ void Widget::loadLayout()
|
|||||||
void Widget::saveLayout()
|
void Widget::saveLayout()
|
||||||
{
|
{
|
||||||
if (!m_id.empty()) {
|
if (!m_id.empty()) {
|
||||||
LayoutIO* io = manager()->getLayoutIO();
|
auto man = manager();
|
||||||
|
LayoutIO* io = (man ? man->getLayoutIO(): nullptr);
|
||||||
if (io) {
|
if (io) {
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
SaveLayoutEvent ev(this, s);
|
SaveLayoutEvent ev(this, s);
|
||||||
@ -690,8 +697,8 @@ void Widget::setBoundsQuietly(const gfx::Rect& rc)
|
|||||||
m_bounds = rc;
|
m_bounds = rc;
|
||||||
|
|
||||||
// Remove all paint messages for this widget.
|
// Remove all paint messages for this widget.
|
||||||
if (Manager* manager = this->manager())
|
if (Manager* man = manager())
|
||||||
manager->removeMessagesFor(this, kPaintMessage);
|
man->removeMessagesFor(this, kPaintMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Test moving this inside the if (m_bounds != rc) { ... }
|
// TODO Test moving this inside the if (m_bounds != rc) { ... }
|
||||||
@ -975,6 +982,8 @@ void Widget::flushRedraw()
|
|||||||
|
|
||||||
Manager* manager = this->manager();
|
Manager* manager = this->manager();
|
||||||
ASSERT(manager);
|
ASSERT(manager);
|
||||||
|
if (!manager)
|
||||||
|
return;
|
||||||
|
|
||||||
while (!processing.empty()) {
|
while (!processing.empty()) {
|
||||||
Widget* widget = processing.front();
|
Widget* widget = processing.front();
|
||||||
@ -1300,36 +1309,44 @@ void Widget::resetSizeHint()
|
|||||||
|
|
||||||
void Widget::requestFocus()
|
void Widget::requestFocus()
|
||||||
{
|
{
|
||||||
manager()->setFocus(this);
|
if (auto man = manager())
|
||||||
|
man->setFocus(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::releaseFocus()
|
void Widget::releaseFocus()
|
||||||
{
|
{
|
||||||
if (hasFocus())
|
if (hasFocus()) {
|
||||||
manager()->freeFocus();
|
if (auto man = manager())
|
||||||
|
man->freeFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Captures the mouse to send all the future mouse messsages to the
|
// Captures the mouse to send all the future mouse messsages to the
|
||||||
// specified widget (included the kMouseMoveMessage and kSetCursorMessage).
|
// specified widget (included the kMouseMoveMessage and kSetCursorMessage).
|
||||||
void Widget::captureMouse()
|
void Widget::captureMouse()
|
||||||
{
|
{
|
||||||
if (!manager()->getCapture()) {
|
if (auto man = manager()) {
|
||||||
manager()->setCapture(this);
|
if (!man->getCapture()) {
|
||||||
|
man->setCapture(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Releases the capture of the mouse events.
|
// Releases the capture of the mouse events.
|
||||||
void Widget::releaseMouse()
|
void Widget::releaseMouse()
|
||||||
{
|
{
|
||||||
if (manager()->getCapture() == this) {
|
if (auto man = manager()) {
|
||||||
manager()->freeCapture();
|
if (man->getCapture() == this) {
|
||||||
|
man->freeCapture();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Widget::offerCapture(ui::MouseMessage* mouseMsg, int widget_type)
|
bool Widget::offerCapture(ui::MouseMessage* mouseMsg, int widget_type)
|
||||||
{
|
{
|
||||||
if (hasCapture()) {
|
if (hasCapture()) {
|
||||||
Widget* pick = manager()->pick(mouseMsg->position());
|
auto man = manager();
|
||||||
|
Widget* pick = (man ? man->pick(mouseMsg->position()): nullptr);
|
||||||
if (pick && pick != this && pick->type() == widget_type) {
|
if (pick && pick != this && pick->type() == widget_type) {
|
||||||
releaseMouse();
|
releaseMouse();
|
||||||
|
|
||||||
@ -1340,7 +1357,7 @@ bool Widget::offerCapture(ui::MouseMessage* mouseMsg, int widget_type)
|
|||||||
mouseMsg->modifiers(),
|
mouseMsg->modifiers(),
|
||||||
mouseMsg->position());
|
mouseMsg->position());
|
||||||
mouseMsg2->setRecipient(pick);
|
mouseMsg2->setRecipient(pick);
|
||||||
manager()->enqueueMessage(mouseMsg2);
|
man->enqueueMessage(mouseMsg2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1601,8 +1618,8 @@ void Widget::offsetWidgets(int dx, int dy)
|
|||||||
m_bounds.offset(dx, dy);
|
m_bounds.offset(dx, dy);
|
||||||
|
|
||||||
// Remove all paint messages for this widget.
|
// Remove all paint messages for this widget.
|
||||||
if (Manager* manager = this->manager())
|
if (auto man = manager())
|
||||||
manager->removeMessagesFor(this, kPaintMessage);
|
man->removeMessagesFor(this, kPaintMessage);
|
||||||
|
|
||||||
for (auto child : m_children)
|
for (auto child : m_children)
|
||||||
child->offsetWidgets(dx, dy);
|
child->offsetWidgets(dx, dy);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user