Add dialog to create new tilemaps selecting the tileset specs

This commit is contained in:
David Capello 2019-04-14 09:01:18 -03:00
parent 21be7c5eac
commit 12e1b4d934
8 changed files with 200 additions and 29 deletions

View File

@ -425,6 +425,9 @@
<key command="NewSpriteFromSelection" shortcut="Ctrl+Alt+N" mac="Cmd+Alt+N" />
<!-- Commands not associated to menu items and without shortcuts by default -->
<key command="NewLayer">
<param name="tilemap" value="true" />
</key>
<key command="PixelPerfectMode" />
<key command="ContiguousFill" />
<key command="SetInkType"><param name="type" value="simple" /></key>
@ -810,6 +813,7 @@
</item>
<item command="NewLayer" text="@.layer_new_tilemap_layer">
<param name="tilemap" value="true" />
<param name="ask" value="true" />
</item>
</menu>
<item command="RemoveLayer" text="@.layer_delete_layer" />

View File

@ -350,6 +350,7 @@ NewLayer_TilemapLayer = Tilemap Layer
NewLayer_FromClipboard = {} from Clipboard
NewLayer_ViaCopy = {} via Copy
NewLayer_ViaCut = {} via Cut
NewLayer_WithDialog = {} (with dialog)
NewSpriteFromSelection = New Sprite from Selection
OpenBrowser = Open Browser
OpenFile = Open Sprite
@ -941,8 +942,14 @@ default_new_folder_name = New Folder
[new_layer]
title = New Layer
name = Name:
tileset = Tileset:
default_new_layer_name = New Layer
[tileset_selector]
new_tileset = New Tileset
grid_width = Grid Width:
grid_height = Grid Height:
[new_sprite]
title = New Sprite
size = Size:

View File

@ -1,20 +1,25 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2016 by David Capello -->
<gui>
<window id="new_layer" text="@.title">
<box vertical="true">
<box horizontal="true">
<box vertical="true" homogeneous="true">
<label text="@.name" />
</box>
<box vertical="true" homogeneous="true">
<entry maxsize="256" text="@.default_new_layer_name" id="name" magnet="true" />
</box>
</box>
<box horizontal="true" homogeneous="true">
<button text="@general.ok" closewindow="true" id="ok" magnet="true" />
<button text="@general.cancel" closewindow="true" />
</box>
</box>
</window>
</gui>
<!-- Aseprite -->
<!-- Copyright (C) 2019 Igara Studio S.A. -->
<!-- Copyright (C) 2001-2016 David Capello -->
<gui>
<window id="new_layer" text="@.title">
<vbox>
<grid columns="2">
<label text="@.name" />
<entry maxsize="256" text="@.default_new_layer_name" id="name" magnet="true" />
<vbox>
<label id="tileset_label" text="@.tileset" />
</vbox>
<hbox id="tileset_options" />
</grid>
<hbox>
<boxfiller />
<hbox homogeneous="true">
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
<button text="@general.cancel" closewindow="true" />
</hbox>
</hbox>
</vbox>
</window>
</gui>

View File

@ -0,0 +1,17 @@
<!-- Aseprite -->
<!-- Copyright (C) 2019 Igara Studio S.A. -->
<gui>
<vbox id="tileset_selector">
<combobox id="tilesets">
<listitem text="@.new_tileset" value="-1" />
</combobox>
<hbox id="grid_options">
<label text="@.grid_width" />
<expr id="grid_width" text="" />
<label text="@.grid_height" />
<expr id="grid_height" text="" />
</hbox>
</vbox>
</gui>

View File

@ -384,6 +384,7 @@ if(ENABLE_UI)
ui/tabs.cpp
ui/tag_window.cpp
ui/task_widget.cpp
ui/tileset_selector.cpp
ui/timeline/ani_controls.cpp
ui/timeline/timeline.cpp
ui/toolbar.cpp

View File

@ -27,6 +27,7 @@
#include "app/tx.h"
#include "app/ui/main_window.h"
#include "app/ui/status_bar.h"
#include "app/ui/tileset_selector.h"
#include "app/ui_context.h"
#include "app/util/clipboard.h"
#include "app/util/new_image_from_mask.h"
@ -145,10 +146,10 @@ private:
void NewLayerCommand::onExecute(Context* context)
{
ContextWriter writer(context);
ContextReader reader(context);
Site site = context->activeSite();
Doc* document(writer.document());
Sprite* sprite(writer.sprite());
Doc* document(reader.document());
Sprite* sprite(reader.sprite());
std::string name;
Doc* pasteDoc = nullptr;
@ -186,21 +187,40 @@ void NewLayerCommand::onExecute(Context* context)
return;
}
// Information about the tileset to be used used for new tilemaps
TilesetSelector::Info tilesetInfo;
tilesetInfo.newTileset = true;
tilesetInfo.grid = context->activeSite().grid();
#ifdef ENABLE_UI
// If params specify to ask the user about the name...
if (params().ask() && context->isUIAvailable()) {
// We open the window to ask the name
app::gen::NewLayer window;
TilesetSelector* tilesetSelector = nullptr;
window.name()->setText(name.c_str());
window.name()->setMinSize(gfx::Size(128, 0));
// Tileset selector for new tilemaps
const bool isTilemap = (m_type == Type::TilemapLayer);
window.tilesetLabel()->setVisible(isTilemap);
window.tilesetOptions()->setVisible(isTilemap);
if (isTilemap) {
tilesetSelector = new TilesetSelector(sprite, tilesetInfo);
window.tilesetOptions()->addChild(tilesetSelector);
}
window.openWindowInForeground();
if (window.closer() != window.ok())
return;
name = window.name()->text();
if (tilesetSelector)
tilesetInfo = tilesetSelector->getInfo();
}
#endif
ContextWriter writer(reader);
LayerGroup* parent = sprite->root();
Layer* activeLayer = writer.layer();
SelectedLayers selLayers = site.selectedLayers();
@ -240,13 +260,17 @@ void NewLayerCommand::onExecute(Context* context)
afterBackground = true;
break;
case Type::TilemapLayer: {
// TODO show a dialog to configure the grid
auto grid = doc::Grid::MakeRect(gfx::Size(16, 16));
auto tileset = new Tileset(sprite, grid, 0);
auto addTileset = new cmd::AddTileset(sprite, tileset);
tx(addTileset);
tileset_index tsi;
if (tilesetInfo.newTileset) {
auto tileset = new Tileset(sprite, tilesetInfo.grid, 0);
auto addTileset = new cmd::AddTileset(sprite, tileset);
tx(addTileset);
auto tsi = addTileset->tilesetIndex();
tsi = addTileset->tilesetIndex();
}
else {
tsi = tilesetInfo.tsi;
}
layer = new LayerTilemap(sprite, tsi);
layer->setName(name);
@ -434,6 +458,8 @@ std::string NewLayerCommand::onGetFriendlyName() const
text = fmt::format(Strings::commands_NewLayer_ViaCopy(), text);
if (params().viaCut())
text = fmt::format(Strings::commands_NewLayer_ViaCut(), text);
if (params().ask())
text = fmt::format(Strings::commands_NewLayer_WithDialog(), text);
return text;
}

View File

@ -0,0 +1,70 @@
// Aseprite
// Copyright (C) 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/ui/tileset_selector.h"
#include "doc/sprite.h"
#include "doc/tilesets.h"
#include "fmt/format.h"
#include "ui/listitem.h"
#include "ui/window.h"
namespace app {
using namespace ui;
TilesetSelector::TilesetSelector(const doc::Sprite* sprite,
const TilesetSelector::Info& info)
{
initTheme();
gridWidth()->setTextf("%d", info.grid.tileSize().w);
gridHeight()->setTextf("%d", info.grid.tileSize().h);
doc::tileset_index tsi = 0;
for (doc::Tileset* tileset : *sprite->tilesets()) {
tilesets()->addItem(
new ListItem(
fmt::format("Tileset #{0} ({1}x{2}): \"{3}\"",
tsi,
tileset->grid().tileSize().w,
tileset->grid().tileSize().w,
tileset->name())));
++tsi;
}
tilesets()->Change.connect(
[this]() {
int index = tilesets()->getSelectedItemIndex();
gridOptions()->setVisible(index == 0);
gridOptions()->setVisible(index == 0);
this->window()->layout();
});
}
TilesetSelector::Info TilesetSelector::getInfo()
{
int itemIndex = tilesets()->getSelectedItemIndex();
Info info;
if (itemIndex == 0) {
gfx::Size sz(std::max(1, gridWidth()->textInt()),
std::max(1, gridHeight()->textInt()));
info.newTileset = true;
info.grid = doc::Grid::MakeRect(sz);
}
else {
info.newTileset = false;
info.tsi = itemIndex-1;
}
return info;
}
} // namespace app

View File

@ -0,0 +1,41 @@
// Aseprite
// Copyright (c) 2019 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_UI_TILESET_SELECTOR_H_INCLUDED
#define APP_UI_TILESET_SELECTOR_H_INCLUDED
#pragma once
#include "doc/grid.h"
#include "doc/tile.h"
#include "tileset_selector.xml.h"
namespace doc {
class Sprite;
class Tileset;
}
namespace app {
class TilesetSelector : public app::gen::TilesetSelector {
public:
struct Info {
bool newTileset = true;
doc::Grid grid;
doc::tileset_index tsi = 0;
};
TilesetSelector(const doc::Sprite* sprite,
const TilesetSelector::Info& info);
Info getInfo();
protected:
};
} // namespace app
#endif