Merge branch '1.0'

Conflicts:
	data/gui.xml
	src/app/CMakeLists.txt
	src/app/color_utils.cpp
	src/app/color_utils.h
	src/app/commands/cmd_preview.cpp
	src/app/document_exporter.cpp
	src/app/document_exporter.h
	src/app/ui/editor/standby_state.cpp
	src/config.h
	src/main/resources_win32.rc
This commit is contained in:
David Capello 2014-12-03 11:15:09 -03:00
commit 5aea29348e
31 changed files with 1164 additions and 1014 deletions

View File

@ -26,7 +26,7 @@ endif()
# Note: This needs to be done before the project command
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}" CACHE INTERNAL "internal")
# ASE project
# Aseprite project
project(aseprite C CXX)
######################################################################
@ -82,6 +82,24 @@ endif()
######################################################################
# Directories
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
# We need to specify the output for each configuration to make it work
# on Visual Studio solutions.
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_PROFILE "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_PROFILE "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_PROFILE "${CMAKE_BINARY_DIR}/bin")
set(CURL_DIR ${CMAKE_SOURCE_DIR}/third_party/curl)
set(GIFLIB_DIR ${CMAKE_SOURCE_DIR}/third_party/giflib)
set(LIBFREETYPE_DIR ${CMAKE_SOURCE_DIR}/third_party/freetype)

View File

@ -52,12 +52,8 @@ the source code in a directory called `aseprite-source`):
commands, you have to compile the project executing make, nmake,
opening the solution, etc.
4. When the project is compiled, you can copy the resulting executable
file (e.g. `build/src/aseprite.exe`) to `aseprite-source` and
execute it. If you have used a Visual Studio project, you can copy
the whole `data/` directory to `build/src/RelWithDebInfo/` so you
can run/debug the program from Visual Studio IDE. On Linux, you can
copy the `data/` directory in `~/.aseprite/` directory.
4. When the project is compiled, you can find the executable file
inside `build/bin/aseprite.exe`.
## Mac OS X details

File diff suppressed because it is too large Load Diff

View File

@ -39,11 +39,7 @@ set(aseprite_libraries
# Directories where .h files can be found
include_directories(. .. ../third_party)
# Directory where generated files by "gen" utility will stay.
include_directories(${CMAKE_CURRENT_BINARY_DIR})
# Third-party libraries
if(USE_SHARED_ALLEGRO4)
# Find the shared Allegro 4 library
find_library(LIBALLEGRO4_LIBRARY alleg)
@ -237,7 +233,22 @@ if(LIBALLEGRO4_LINK_FLAGS)
endif()
######################################################################
# ASEPRITE application
# Copy data/ directory target
file(GLOB_RECURSE src_data_files
RELATIVE ${CMAKE_SOURCE_DIR}/data/ "${CMAKE_SOURCE_DIR}/data/*.*")
foreach(fn ${src_data_files})
add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/bin/data/${fn}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/data/${fn} ${CMAKE_BINARY_DIR}/bin/data/${fn}
MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/data/${fn})
list(APPEND out_data_files ${CMAKE_BINARY_DIR}/bin/data/${fn})
endforeach()
add_custom_target(copy_data DEPENDS ${out_data_files})
######################################################################
# Aseprite application
if(WIN32)
set(win32_resources main/resources_win32.rc)
@ -247,8 +258,12 @@ if(UNIX)
set(x11_resources main/xpm_icon.c)
endif(UNIX)
add_executable(aseprite WIN32 main/main.cpp ${win32_resources} ${x11_resources})
add_executable(aseprite WIN32
main/main.cpp
${win32_resources}
${x11_resources})
target_link_libraries(aseprite ${all_libs})
add_dependencies(aseprite copy_data)
install(TARGETS aseprite
RUNTIME DESTINATION bin)
@ -256,34 +271,6 @@ install(TARGETS aseprite
install(DIRECTORY ../data
DESTINATION share/aseprite)
if(EXISTS ../docs/quickref.pdf)
install(FILES ../docs/quickref.pdf
DESTINATION share/aseprite/docs/quickref.pdf)
endif()
######################################################################
# Generate source files from widget XML files
file(GLOB widget_files ${CMAKE_SOURCE_DIR}/data/widgets/*.xml)
foreach(widget_file ${widget_files})
get_filename_component(widget_name ${widget_file} NAME_WE)
set(target_name generated_${widget_name})
set(output_fn ${CMAKE_CURRENT_BINARY_DIR}/generated_${widget_name}.h)
add_custom_command(
OUTPUT ${output_fn}
COMMAND gen/gen --input ${widget_file} --widgetid ${widget_name} > ${output_fn}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
MAIN_DEPENDENCY ${widget_file}
DEPENDS gen)
add_custom_target(${target_name} DEPENDS ${output_fn})
set_source_files_properties(${target_name} PROPERTIES GENERATED TRUE)
add_dependencies(app-lib ${target_name})
endforeach()
######################################################################
# Tests
@ -306,6 +293,13 @@ function(find_tests dir dependencies)
get_filename_component(testname ${testsourcefile} NAME_WE)
add_executable(${testname} ${testsourcefile})
if(MSVC)
# Fix problem compiling gen from a Visual Studio solution
set_target_properties(${testname}
PROPERTIES LINK_FLAGS -ENTRY:"mainCRTStartup")
endif()
target_link_libraries(${testname} gtest ${ARGV})
if(LIBALLEGRO4_LINK_FLAGS)
target_link_libraries(${testname} ${LIBALLEGRO4_LINK_FLAGS})

View File

@ -226,8 +226,10 @@ int allegro_main(int argc, char *argv[], NSObject* app_delegate)
__crt0_argc = argc;
__crt0_argv = argv;
#if 0
if (!osx_bootstrap_ok()) /* not safe to use NSApplication */
call_user_main();
#endif
[NSApplication sharedApplication];

View File

@ -440,10 +440,12 @@ static int osx_sys_init(void)
{
long result;
#if 0
/* If we're in the 'dead bootstrap' environment, the Mac driver won't work. */
if (!osx_bootstrap_ok()) {
return -1;
}
#endif
/* Install emergency-exit signal handlers */
old_sig_abrt = signal(SIGABRT, osx_signal_handler);

View File

@ -1,6 +1,31 @@
# Aseprite
# Copyright (C) 2001-2014 David Capello
######################################################################
# Generate source files from widget XML files
file(GLOB widget_files ${CMAKE_SOURCE_DIR}/data/widgets/*.xml)
foreach(widget_file ${widget_files})
get_filename_component(widget_name ${widget_file} NAME_WE)
set(target_name generated_${widget_name})
set(output_fn ${CMAKE_CURRENT_BINARY_DIR}/generated_${widget_name}.h)
add_custom_command(
OUTPUT ${output_fn}
COMMAND ${CMAKE_BINARY_DIR}/bin/gen --input ${widget_file} --widgetid ${widget_name} > ${output_fn}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
MAIN_DEPENDENCY ${widget_file}
DEPENDS gen)
list(APPEND generated_header_files ${output_fn})
endforeach()
# Directory where generated files by "gen" utility will stay.
include_directories(${CMAKE_CURRENT_BINARY_DIR})
######################################################################
# app-lib target
add_library(app-lib
app.cpp
app_menus.cpp
@ -260,4 +285,5 @@ add_library(app-lib
widget_loader.cpp
xml_document.cpp
xml_exception.cpp
zoom.cpp)
zoom.cpp
${generated_header_files})

View File

@ -124,9 +124,10 @@ App::App()
m_instance = this;
}
void App::initialize(int argc, const char* argv[])
void App::initialize(const AppOptions& options)
{
AppOptions options(argc, argv);
if (options.startUI())
m_guiSystem.reset(new ui::GuiSystem);
// Initializes the application loading the modules, setting the
// graphics mode, loading the configuration and resources, etc.
@ -210,6 +211,8 @@ void App::initialize(int argc, const char* argv[])
// Procress options
PRINTF("Processing options...\n");
bool ignoreEmpty = false;
// Open file specified in the command line
if (!options.values().empty()) {
Console console;
@ -258,6 +261,10 @@ void App::initialize(int argc, const char* argv[])
importLayer = value.value();
importLayerSaveAs = value.value();
}
// --ignore-empty
else if (opt == &options.ignoreEmpty()) {
ignoreEmpty = true;
}
// --save-as <filename>
else if (opt == &options.saveAs()) {
Document* doc = NULL;
@ -380,6 +387,9 @@ void App::initialize(int argc, const char* argv[])
if (m_exporter != NULL) {
PRINTF("Exporting sheet...\n");
if (ignoreEmpty)
m_exporter->setIgnoreEmptyCels(true);
m_exporter->exportSheet();
m_exporter.reset(NULL);
}

View File

@ -33,8 +33,13 @@ namespace doc {
class Layer;
}
namespace ui {
class GuiSystem;
}
namespace app {
class AppOptions;
class Document;
class DocumentExporter;
class INotificationDelegate;
@ -65,7 +70,7 @@ namespace app {
// Runs the Aseprite application. In GUI mode it's the top-level
// window, in console/scripting it just runs the specified
// scripts.
void initialize(int argc, const char* argv[]);
void initialize(const AppOptions& options);
void run();
tools::ToolBox* getToolBox() const;
@ -91,6 +96,7 @@ namespace app {
static App* m_instance;
base::SystemConsole m_systemConsole;
base::UniquePtr<ui::GuiSystem> m_guiSystem;
Modules* m_modules;
LegacyModules* m_legacy;
bool m_isGui;

View File

@ -48,6 +48,7 @@ AppOptions::AppOptions(int argc, const char* argv[])
, m_sheetPack(m_po.add("sheet-pack").description("Use a packing algorithm to avoid waste of space\nin the texture"))
, m_splitLayers(m_po.add("split-layers").description("Import each layer of the next given sprite as\na separated image in the sheet"))
, m_importLayer(m_po.add("import-layer").requiresValue("<name>").description("Import just one layer of the next given sprite"))
, m_ignoreEmpty(m_po.add("ignore-empty").description("Do not export empty frames/cels"))
, m_verbose(m_po.add("verbose").description("Explain what is being done"))
, m_help(m_po.add("help").mnemonic('?').description("Display this help and exits"))
, m_version(m_po.add("version").description("Output version information and exit"))

View File

@ -56,6 +56,7 @@ public:
const Option& sheetPack() const { return m_sheetPack; }
const Option& splitLayers() const { return m_splitLayers; }
const Option& importLayer() const { return m_importLayer; }
const Option& ignoreEmpty() const { return m_ignoreEmpty; }
bool hasExporterParams() const;
@ -82,6 +83,7 @@ private:
Option& m_sheetPack;
Option& m_splitLayers;
Option& m_importLayer;
Option& m_ignoreEmpty;
Option& m_verbose;
Option& m_help;

View File

@ -117,7 +117,7 @@ doc::color_t color_utils::color_for_layer(const app::Color& color, Layer* layer)
return color_for_target(color, ColorTarget(layer));
}
doc::color_t color_utils::color_for_target(const app::Color& color, const ColorTarget& colorTarget)
doc::color_t color_utils::color_for_target_mask(const app::Color& color, const ColorTarget& colorTarget)
{
doc::color_t c = -1;
@ -149,6 +149,13 @@ doc::color_t color_utils::color_for_target(const app::Color& color, const ColorT
}
}
return c;
}
doc::color_t color_utils::color_for_target(const app::Color& color, const ColorTarget& colorTarget)
{
doc::color_t c = color_utils::color_for_target_mask(color, colorTarget);
switch (colorTarget.pixelFormat()) {
case IMAGE_RGB:
if (colorTarget.isBackground())

View File

@ -39,6 +39,7 @@ namespace app {
gfx::Color color_for_ui(const app::Color& color);
doc::color_t color_for_image(const app::Color& color, doc::PixelFormat format);
doc::color_t color_for_layer(const app::Color& color, doc::Layer* layer);
doc::color_t color_for_target_mask(const app::Color& color, const ColorTarget& colorTarget);
doc::color_t color_for_target(const app::Color& color, const ColorTarget& colorTarget);
} // namespace color_utils

View File

@ -190,11 +190,11 @@ protected:
m_editor->layer(),
m_editor->frame());
ImageBufferPtr buf = Editor::getRenderImageBuffer();
m_render.reset(
renderEngine.renderSprite(
0, 0, m_sprite->width(), m_sprite->height(),
m_editor->frame(), Zoom(1, 1), false, false,
Editor::getRenderImageBuffer()));
m_editor->frame(), Zoom(1, 1), false, false, buf));
}
int x, y, w, h, u, v;

View File

@ -30,6 +30,7 @@
#include "base/convert_to.h"
#include "base/path.h"
#include "base/unique_ptr.h"
#include "doc/algorithm/shrink_bounds.h"
#include "doc/cel.h"
#include "doc/dithering_method.h"
#include "doc/image.h"
@ -205,6 +206,7 @@ DocumentExporter::DocumentExporter()
, m_texturePack(false)
, m_scale(1.0)
, m_scaleMode(DefaultScaleMode)
, m_ignoreEmptyCels(false)
{
}
@ -264,6 +266,7 @@ void DocumentExporter::exportSheet()
void DocumentExporter::captureSamples(Samples& samples)
{
ImageBufferPtr checkEmptyImageBuf;
std::vector<char> buf(32);
for (auto& item : m_documents) {
@ -289,7 +292,35 @@ void DocumentExporter::captureSamples(Samples& samples)
+ "." + base::get_file_extension(filename));
}
samples.addSample(Sample(doc, sprite, layer, frame, filename));
Sample sample(doc, sprite, layer, frame, filename);
if (m_ignoreEmptyCels) {
if (layer && layer->isImage() &&
!static_cast<LayerImage*>(layer)->getCel(frame)) {
// Empty cel this sample completely
continue;
}
base::UniquePtr<Image> checkEmptyImage(
Image::create(sprite->pixelFormat(),
sprite->width(),
sprite->height(),
checkEmptyImageBuf));
checkEmptyImage->setMaskColor(sprite->transparentColor());
clear_image(checkEmptyImage, sprite->transparentColor());
renderSample(sample, checkEmptyImage, 0, 0);
gfx::Rect frameBounds;
if (!algorithm::shrink_bounds(checkEmptyImage, frameBounds,
sprite->transparentColor())) {
// If shrink_bounds returns false, it's because the whole
// image is transparent (equal to the mask color).
continue;
}
}
samples.addSample(sample);
}
}
}
@ -355,12 +386,7 @@ void DocumentExporter::renderTexture(const Samples& samples, Image* textureImage
int x = sample.inTextureBounds().x - sample.trimmedBounds().x;
int y = sample.inTextureBounds().y - sample.trimmedBounds().y;
if (sample.layer()) {
layer_render(sample.layer(), textureImage, x, y, sample.frame());
}
else {
sample.sprite()->render(textureImage, x, y, sample.frame());
}
renderSample(sample, textureImage, x, y);
}
}
@ -415,4 +441,14 @@ void DocumentExporter::createDataFile(const Samples& samples, std::ostream& os,
<< "}\n";
}
void DocumentExporter::renderSample(const Sample& sample, doc::Image* dst, int x, int y)
{
if (sample.layer()) {
layer_render(sample.layer(), dst, x, y, sample.frame());
}
else {
sample.sprite()->render(dst, x, y, sample.frame());
}
}
} // namespace app

View File

@ -89,6 +89,10 @@ namespace app {
m_scaleMode = mode;
}
void setIgnoreEmptyCels(bool ignore) {
m_ignoreEmptyCels = ignore;
}
void addDocument(Document* document, doc::Layer* layer = NULL) {
m_documents.push_back(Item(document, layer));
}
@ -106,6 +110,7 @@ namespace app {
Document* createEmptyTexture(const Samples& samples);
void renderTexture(const Samples& samples, doc::Image* textureImage);
void createDataFile(const Samples& samples, std::ostream& os, doc::Image* textureImage);
void renderSample(const Sample& sample, doc::Image* dst, int x, int y);
class Item {
public:
@ -126,6 +131,7 @@ namespace app {
bool m_texturePack;
double m_scale;
ScaleMode m_scaleMode;
bool m_ignoreEmptyCels;
Items m_documents;
DISABLE_COPYING(DocumentExporter);

View File

@ -428,10 +428,24 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg)
CommandsModule::instance()->getCommandByName(CommandId::OpenFile);
Params params;
for (DropFilesMessage::Files::const_iterator
it = files.begin(); it != files.end(); ++it) {
params.set("filename", it->c_str());
UIContext::instance()->executeCommand(cmd_open_file, &params);
UIContext* ctx = UIContext::instance();
for (const auto& fn : files) {
// If the document is already open, select it.
Document* doc = static_cast<Document*>(ctx->documents().getByFileName(fn));
if (doc) {
DocumentView* docView = ctx->getFirstDocumentView(doc);
if (docView)
ctx->setActiveView(docView);
else {
ASSERT(false); // Must be some DocumentView available
}
}
// Load the file
else {
params.set("filename", fn.c_str());
ctx->executeCommand(cmd_open_file, &params);
}
}
}
break;

View File

@ -1416,22 +1416,10 @@ void Editor::pasteImage(const Image* image, const gfx::Point& pos)
int y = pos.y;
{
// Then we check if the image will be visible by the user.
Rect visibleBounds = getVisibleSpriteBounds();
Rect visibleBounds = getVisibleSpriteBounds().shrink(4*ui::guiscale());
x = MID(visibleBounds.x-image->width(), x, visibleBounds.x+visibleBounds.w-1);
y = MID(visibleBounds.y-image->height(), y, visibleBounds.y+visibleBounds.h-1);
// If the visible part of the pasted image will not fit in the
// visible bounds of the editor, we put the image in the center of
// the visible bounds.
Rect visiblePasted = visibleBounds.createIntersect(gfx::Rect(x, y, image->width(), image->height()));
if (((visibleBounds.w >= image->width() && visiblePasted.w < image->width()/2) ||
(visibleBounds.w < image->width() && visiblePasted.w < visibleBounds.w/2)) ||
((visibleBounds.h >= image->height() && visiblePasted.h < image->width()/2) ||
(visibleBounds.h < image->height() && visiblePasted.h < visibleBounds.h/2))) {
x = visibleBounds.x + visibleBounds.w/2 - image->width()/2;
y = visibleBounds.y + visibleBounds.h/2 - image->height()/2;
}
// We limit the image inside the sprite's bounds.
x = MID(0, x, sprite->width() - image->width());
y = MID(0, y, sprite->height() - image->height());

View File

@ -499,7 +499,8 @@ void MovingPixelsState::setTransparentColor(const app::Color& color)
Layer* layer = m_editor->layer();
ASSERT(layer != NULL);
m_pixelsMovement->setMaskColor(color_utils::color_for_layer(color, layer));
m_pixelsMovement->setMaskColor(
color_utils::color_for_target_mask(color, ColorTarget(layer)));
}
void MovingPixelsState::dropPixels(Editor* editor)

View File

@ -164,7 +164,6 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
return true;
UIContext* context = UIContext::instance();
tools::Tool* currentTool = editor->getCurrentEditorTool();
tools::Ink* clickedInk = editor->getCurrentEditorInk();
DocumentLocation location;
editor->getDocumentLocation(&location);
@ -203,6 +202,10 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
StatusBar::instance()->showTip(1000,
"The background layer cannot be moved");
}
else if (!layer->isVisible()) {
StatusBar::instance()->showTip(1000,
"Layer '%s' is hidden", layer->name().c_str());
}
else if (!layer->isMovable() || !layer->isEditable()) {
StatusBar::instance()->showTip(1000,
"Layer '%s' is locked", layer->name().c_str());

View File

@ -1671,12 +1671,8 @@ void Timeline::hotThis(int hot_part, LayerIndex hot_layer, FrameNumber hot_frame
}
// Invalidate the old and new 'hot' thing.
else {
invalidatePart(m_hot_part,
m_hot_layer,
m_hot_frame);
invalidatePart(m_hot_part,
m_hot_layer,
m_hot_frame);
invalidatePart(m_hot_part, m_hot_layer, m_hot_frame);
invalidatePart(hot_part, hot_layer, hot_frame);
}
// Draw the new 'hot' thing.

View File

@ -122,8 +122,7 @@ size_t UIContext::countViewsOf(Document* document) const
Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
size_t counter = 0;
for (Workspace::iterator it=workspace->begin(); it != workspace->end(); ++it) {
WorkspaceView* view = *it;
for (auto view : *workspace) {
if (DocumentView* docView = dynamic_cast<DocumentView*>(view)) {
if (docView->getDocument() == document) {
++counter;
@ -134,6 +133,21 @@ size_t UIContext::countViewsOf(Document* document) const
return counter;
}
DocumentView* UIContext::getFirstDocumentView(Document* document) const
{
Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
for (auto view : *workspace) {
if (DocumentView* docView = dynamic_cast<DocumentView*>(view)) {
if (docView->getDocument() == document) {
return docView;
}
}
}
return NULL;
}
Editor* UIContext::activeEditor()
{
DocumentView* view = activeView();

View File

@ -44,6 +44,8 @@ namespace app {
// Returns the number of views that the given document has.
size_t countViewsOf(Document* document) const;
DocumentView* getFirstDocumentView(Document* document) const;
// Returns the current editor. It can be null.
Editor* activeEditor();

View File

@ -11,6 +11,7 @@
#include "doc/documents.h"
#include "base/mutex.h"
#include "base/path.h"
#include "doc/document.h"
#include <algorithm>
@ -87,18 +88,28 @@ void Documents::move(Document* doc, int index)
Document* Documents::getById(ObjectId id) const
{
for (const_iterator it = begin(), end = this->end(); it != end; ++it) {
if ((*it)->id() == id)
return *it;
for (const auto& doc : *this) {
if (doc->id() == id)
return doc;
}
return NULL;
}
Document* Documents::getByName(const std::string& name) const
{
for (const_iterator it = begin(), end = this->end(); it != end; ++it) {
if ((*it)->name() == name)
return *it;
for (const auto& doc : *this) {
if (doc->name() == name)
return doc;
}
return NULL;
}
Document* Documents::getByFileName(const std::string& filename) const
{
std::string fixfn = base::fix_path_separators(filename);
for (const auto& doc : *this) {
if (base::fix_path_separators(doc->filename()) == fixfn)
return doc;
}
return NULL;
}

View File

@ -56,6 +56,7 @@ namespace doc {
Document* operator[](int index) const { return m_docs[index]; }
Document* getById(ObjectId id) const;
Document* getByName(const std::string& name) const;
Document* getByFileName(const std::string& filename) const;
private:
// Deletes all documents in the list (calling "delete" operation).

View File

@ -486,7 +486,7 @@ void Sprite::pickCels(int x, int y, FrameNumber frame, int opacityThreshold, Cel
for (int i=(int)layers.size()-1; i>=0; --i) {
Layer* layer = layers[i];
if (!layer->isImage())
if (!layer->isImage() || !layer->isVisible())
continue;
Cel* cel = static_cast<LayerImage*>(layer)->getCel(frame);

View File

@ -5,6 +5,12 @@ add_executable(gen
gen.cpp
ui_class.cpp)
if(MSVC)
# Fix problem compiling gen from a Visual Studio solution
set_target_properties(gen
PROPERTIES LINK_FLAGS -ENTRY:"mainCRTStartup")
endif()
target_link_libraries(gen base-lib)
if(USE_SHARED_TINYXML)
target_link_libraries(gen ${LIBTINYXML_LIBRARY})

View File

@ -21,6 +21,7 @@
#endif
#include "app/app.h"
#include "app/app_options.h"
#include "app/console.h"
#include "app/resource_finder.h"
#include "app/send_crash.h"
@ -30,7 +31,6 @@
#include "she/error.h"
#include "she/scoped_handle.h"
#include "she/system.h"
#include "ui/base.h"
#include <cstdlib>
#include <ctime>
@ -67,9 +67,10 @@ int app_main(int argc, char* argv[])
try {
base::MemoryDump memoryDump;
she::ScopedHandle<she::System> system(she::create_system());
MemLeak memleak;
ui::GuiSystem guiSystem;
app::AppOptions options(argc, const_cast<const char**>(argv));
she::ScopedHandle<she::System> system(she::create_system());
app::App app;
// Change the name of the memory dump file
@ -79,7 +80,7 @@ int app_main(int argc, char* argv[])
memoryDump.setFileName(filename);
}
app.initialize(argc, const_cast<const char**>(argv));
app.initialize(options);
app.run();
return 0;
}

View File

@ -712,7 +712,9 @@ public:
Alleg4System()
: m_font(font, Alleg4Font::None) // Default Allegro font
{
allegro_init();
if (allegro_init() < 0)
throw std::runtime_error("Cannot initialize Allegro library");
set_uformat(U_UTF8);
_al_detect_filename_encoding();
install_timer();

View File

@ -14,7 +14,10 @@ namespace she {
class ScopedHandle {
public:
ScopedHandle(T* handle) : m_handle(handle) { }
~ScopedHandle() { m_handle->dispose(); }
~ScopedHandle() {
if (m_handle)
m_handle->dispose();
}
T* operator->() { return m_handle; }
operator T*() { return m_handle; }

View File

@ -33,6 +33,7 @@ if(NOT USE_SHARED_GTEST)
endif()
if(ENABLE_UPDATER AND NOT USE_SHARED_CURL)
set(BUILD_RELEASE_DEBUG_DIRS 1)
add_subdirectory(curl)
endif()