670 lines
22 KiB
C++
670 lines
22 KiB
C++
|
/*
|
||
|
Moonfall Copyright (C) 2008 Alex Yatskov
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include "Pch.h"
|
||
|
#include "FrameSpriteEditor.h"
|
||
|
|
||
|
BEGIN_EVENT_TABLE(FrameSpriteEditor, wxFrame)
|
||
|
EVT_CLOSE( FrameSpriteEditor::OnClose)
|
||
|
EVT_MENU(ID_MENU_FILE_NEW, FrameSpriteEditor::OnMenuSelectedFileNew)
|
||
|
EVT_MENU(ID_MENU_FILE_OPEN, FrameSpriteEditor::OnMenuSelectedFileOpen)
|
||
|
EVT_MENU(ID_MENU_FILE_SAVE, FrameSpriteEditor::OnMenuSelectedFileSave)
|
||
|
EVT_MENU(ID_MENU_FILE_SAVE_AS, FrameSpriteEditor::OnMenuSelectedFileSaveAs)
|
||
|
EVT_MENU(ID_MENU_FILE_EXIT, FrameSpriteEditor::OnMenuSelectedFileExit)
|
||
|
EVT_MENU(ID_MENU_IMAGE_INSERT, FrameSpriteEditor::OnMenuSelectedImageInsert)
|
||
|
EVT_MENU(ID_MENU_IMAGE_DELETE, FrameSpriteEditor::OnMenuSelectedImageDelete)
|
||
|
EVT_MENU(ID_MENU_SPRITE_RENAME, FrameSpriteEditor::OnMenuSelectedSpriteRename)
|
||
|
EVT_MENU(ID_MENU_SPRITE_DELETE, FrameSpriteEditor::OnMenuSelectedSpriteDelete)
|
||
|
EVT_MENU(ID_MENU_SHAPE_RENAME, FrameSpriteEditor::OnMenuSelectedShapeRename)
|
||
|
EVT_MENU(ID_MENU_SHAPE_DELETE, FrameSpriteEditor::OnMenuSelectedShapeDelete)
|
||
|
END_EVENT_TABLE()
|
||
|
|
||
|
FrameSpriteEditor::FrameSpriteEditor(wxWindow* parent, const wxString& manifestFilename) :
|
||
|
wxFrame(parent, wxID_ANY, wxT("Sprite Editor"), wxDefaultPosition, wxSize(800, 600)),
|
||
|
m_listImages(NULL),
|
||
|
m_listSprites(NULL),
|
||
|
m_listShapes(NULL),
|
||
|
m_scrolledWindow(NULL),
|
||
|
m_panelCanvas(NULL),
|
||
|
m_textGrid(NULL),
|
||
|
m_draggingSprite(false),
|
||
|
m_draggingShape(false),
|
||
|
m_gridSize(16),
|
||
|
m_imageIndex(wxNOT_FOUND),
|
||
|
m_spriteIndex(wxNOT_FOUND),
|
||
|
m_shapeIndex(wxNOT_FOUND)
|
||
|
{
|
||
|
InitializeUi();
|
||
|
InitializeMenuBar();
|
||
|
|
||
|
m_currentFilename = manifestFilename;
|
||
|
|
||
|
if (!manifestFilename.IsEmpty() && LoadManifest(manifestFilename))
|
||
|
{
|
||
|
UpdateImageList();
|
||
|
UpdateSpriteList();
|
||
|
UpdateShapeList();
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool FrameSpriteEditor::LoadManifest(const wxString& filename)
|
||
|
{
|
||
|
ClearManifest();
|
||
|
|
||
|
if (!m_spriteManager.LoadManifest(filename.ToAscii().data()))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
std::vector<SpriteSummary> summary;
|
||
|
m_spriteManager.SummarizeSprites(&summary);
|
||
|
|
||
|
for (std::vector<SpriteSummary>::iterator summaryIter = summary.begin(); summaryIter != summary.end(); ++summaryIter)
|
||
|
{
|
||
|
std::vector<Image>::iterator imageIter;
|
||
|
for (imageIter = m_images.begin(); imageIter != m_images.end(); ++imageIter)
|
||
|
{
|
||
|
if (imageIter->filename == summaryIter->asset)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (imageIter == m_images.end())
|
||
|
{
|
||
|
m_images.push_back(Image(summaryIter->asset));
|
||
|
imageIter = m_images.begin() + m_images.size() - 1;
|
||
|
}
|
||
|
|
||
|
imageIter->sprites.push_back(Sprite(summaryIter->alias, summaryIter->position, summaryIter->size, summaryIter->shapes));
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool FrameSpriteEditor::SaveManifest(const wxString& filename)
|
||
|
{
|
||
|
m_spriteManager.ClearManifest();
|
||
|
|
||
|
for (std::vector<Image>::iterator imageIter = m_images.begin(); imageIter != m_images.end(); ++imageIter)
|
||
|
{
|
||
|
for (std::vector<Sprite>::iterator spriteIter = imageIter->sprites.begin(); spriteIter != imageIter->sprites.end(); ++spriteIter)
|
||
|
{
|
||
|
m_spriteManager.AppendManifest(
|
||
|
spriteIter->alias.c_str(),
|
||
|
imageIter->filename.c_str(),
|
||
|
spriteIter->position,
|
||
|
spriteIter->size,
|
||
|
spriteIter->shapes
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return m_spriteManager.SaveManifest(filename.ToAscii().data());
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::ClearManifest()
|
||
|
{
|
||
|
m_spriteManager.ClearManifest();
|
||
|
m_images.clear();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedFileNew(wxCommandEvent& event)
|
||
|
{
|
||
|
m_currentFilename.Empty();
|
||
|
ClearManifest();
|
||
|
|
||
|
UpdateImageList();
|
||
|
UpdateSpriteList();
|
||
|
UpdateShapeList();
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedFileOpen(wxCommandEvent& event)
|
||
|
{
|
||
|
const wxString filename = wxFileSelector(
|
||
|
wxT("Choose a sprite manifest file"),
|
||
|
wxEmptyString,
|
||
|
wxEmptyString,
|
||
|
wxEmptyString,
|
||
|
wxT("XML files (*.xml)|*.xml"),
|
||
|
wxFD_OPEN,
|
||
|
this
|
||
|
);
|
||
|
|
||
|
if (filename.IsEmpty())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_currentFilename = filename;
|
||
|
LoadManifest(filename);
|
||
|
|
||
|
UpdateImageList();
|
||
|
UpdateSpriteList();
|
||
|
UpdateShapeList();
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedFileSave(wxCommandEvent& event)
|
||
|
{
|
||
|
if (m_currentFilename.IsEmpty())
|
||
|
{
|
||
|
OnMenuSelectedFileSaveAs(event);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SaveManifest(m_currentFilename);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedFileSaveAs(wxCommandEvent& event)
|
||
|
{
|
||
|
const wxString filename = wxFileSelector(
|
||
|
wxT("Choose a sprite manifest file"),
|
||
|
wxEmptyString,
|
||
|
wxEmptyString,
|
||
|
wxEmptyString,
|
||
|
wxT("XML files (*.xml)|*.xml"),
|
||
|
wxFD_SAVE,
|
||
|
this
|
||
|
);
|
||
|
|
||
|
if (filename.IsEmpty())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_currentFilename = filename;
|
||
|
SaveManifest(filename);
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedFileExit(wxCommandEvent& event)
|
||
|
{
|
||
|
Hide();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnCanvasLeftDown(wxMouseEvent& event)
|
||
|
{
|
||
|
if (m_imageIndex != wxNOT_FOUND)
|
||
|
{
|
||
|
if (!event.ControlDown())
|
||
|
{
|
||
|
m_draggingSprite = true;
|
||
|
}
|
||
|
else if (m_spriteIndex != wxNOT_FOUND)
|
||
|
{
|
||
|
m_draggingShape = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_marquee = Marquee(AdjustPosition(Vector2i(event.GetX(), event.GetY())), Vector2i(0, 0));
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnCanvasLeftUp(wxMouseEvent& event)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
if (m_imageIndex == wxNOT_FOUND || m_marquee.size.x == 0 || m_marquee.size.y == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Image& image = m_images[m_imageIndex];
|
||
|
|
||
|
if (m_draggingSprite)
|
||
|
{
|
||
|
wxTextEntryDialog dialog(this, wxT("Sprite alias"), wxT("Input a sprite alias"));
|
||
|
if (dialog.ShowModal() != wxID_OK || dialog.GetValue().IsEmpty())
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
image.sprites.push_back(Sprite(dialog.GetValue().ToAscii().data(), m_marquee.position, m_marquee.size));
|
||
|
UpdateSpriteList();
|
||
|
}
|
||
|
else if (m_draggingShape && m_spriteIndex != wxNOT_FOUND)
|
||
|
{
|
||
|
Sprite& sprite = image.sprites[m_spriteIndex];
|
||
|
|
||
|
long shapeType = 0;
|
||
|
wxTextEntryDialog dialogId(this, wxT("Shape type"), wxT("Input shape type"));
|
||
|
if (dialogId.ShowModal() != wxID_OK || !dialogId.GetValue().ToLong(&shapeType) || shapeType >= ACTOR_SHAPE_TYPE_COUNT)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
long shapeData = 0;
|
||
|
wxTextEntryDialog dialogData(this, wxT("Shape data"), wxT("Input shape data"));
|
||
|
if (dialogData.ShowModal() != wxID_OK || !dialogData.GetValue().ToLong(&shapeData))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ActorShape& shape = sprite.shapes[shapeType];
|
||
|
shape.data = shapeData;
|
||
|
shape.position = m_marquee.position - sprite.position;
|
||
|
shape.size = m_marquee.size;
|
||
|
shape.enabled = true;;
|
||
|
|
||
|
UpdateShapeList();
|
||
|
}
|
||
|
}
|
||
|
while (false);
|
||
|
|
||
|
m_draggingSprite = false;
|
||
|
m_draggingShape = false;
|
||
|
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnCanvasRightDown(wxMouseEvent& event)
|
||
|
{
|
||
|
if (m_draggingSprite || m_draggingShape || m_imageIndex == wxNOT_FOUND)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const Image& image = m_images[m_imageIndex];
|
||
|
|
||
|
for (size_t i = 0; i < image.sprites.size(); ++i)
|
||
|
{
|
||
|
const Sprite& sprite = image.sprites[i];
|
||
|
const Rect4i spriteRect(sprite.position.x, sprite.position.y, sprite.position.x + sprite.size.x, sprite.position.y + sprite.size.y);
|
||
|
|
||
|
if (spriteRect.Contains(event.GetX(), event.GetY()))
|
||
|
{
|
||
|
m_spriteIndex = static_cast<int>(i);
|
||
|
m_listSprites->SetSelection(m_spriteIndex);
|
||
|
UpdateShapeList();
|
||
|
UpdateCanvas();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnCanvasMotion(wxMouseEvent& event)
|
||
|
{
|
||
|
if (!m_draggingSprite && !m_draggingShape)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Vector2i position = AdjustPosition(Vector2i(event.GetX(), event.GetY()));
|
||
|
position.x = MAX(position.x, m_marquee.position.x);
|
||
|
position.y = MAX(position.y, m_marquee.position.y);
|
||
|
|
||
|
m_marquee.size = position - m_marquee.position;
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnCanvasPaint(wxPaintEvent& event)
|
||
|
{
|
||
|
wxBufferedPaintDC dc(m_panelCanvas);
|
||
|
dc.SetBackground(wxBrush(wxColor(0x00, 0x00, 0x00), wxSOLID));
|
||
|
dc.Clear();
|
||
|
|
||
|
if (m_currentBitmap.IsOk())
|
||
|
{
|
||
|
dc.SetBrush(wxBrush(wxColor(0x00, 0x00, 0xff), wxSOLID));
|
||
|
dc.SetPen(wxPen(wxColor(0x00, 0x00, 0x00), 1, wxTRANSPARENT));
|
||
|
dc.DrawRectangle(BITMAP_OFFSET, BITMAP_OFFSET, m_currentBitmap.GetWidth(), m_currentBitmap.GetHeight());
|
||
|
dc.DrawBitmap(m_currentBitmap, BITMAP_OFFSET, BITMAP_OFFSET, true);
|
||
|
}
|
||
|
|
||
|
dc.SetBrush(wxBrush(wxColor(0x00, 0x00, 0x00), wxTRANSPARENT));
|
||
|
|
||
|
if (m_draggingSprite)
|
||
|
{
|
||
|
dc.SetPen(wxPen(wxColor(0x00, 0xff, 0x00), 2, wxSOLID));
|
||
|
dc.DrawRectangle(m_marquee.position.x + BITMAP_OFFSET, m_marquee.position.y + BITMAP_OFFSET, m_marquee.size.x, m_marquee.size.y);
|
||
|
}
|
||
|
else if (m_draggingShape)
|
||
|
{
|
||
|
dc.SetPen(wxPen(wxColor(0xff, 0xff, 0x00), 2, wxSOLID));
|
||
|
dc.DrawRectangle(m_marquee.position.x + BITMAP_OFFSET, m_marquee.position.y + BITMAP_OFFSET, m_marquee.size.x, m_marquee.size.y);
|
||
|
}
|
||
|
else if (m_spriteIndex != wxNOT_FOUND && m_imageIndex != wxNOT_FOUND)
|
||
|
{
|
||
|
const Sprite& sprite = m_images[m_imageIndex].sprites[m_spriteIndex];
|
||
|
dc.SetPen(wxPen(wxColor(0x00, 0xff, 0x00), 2, wxSHORT_DASH));
|
||
|
dc.DrawRectangle(sprite.position.x + BITMAP_OFFSET, sprite.position.y + BITMAP_OFFSET, sprite.size.x, sprite.size.y);
|
||
|
|
||
|
if (m_shapeIndex != wxNOT_FOUND)
|
||
|
{
|
||
|
const ActorShape& shape = sprite.shapes[m_shapeIndex];
|
||
|
if (shape.enabled)
|
||
|
{
|
||
|
dc.SetPen(wxPen(wxColor(0xff, 0xff, 0x00), 2, wxSHORT_DASH));
|
||
|
dc.DrawRectangle(shape.position.x + sprite.position.x + BITMAP_OFFSET, shape.position.y + sprite.position.y + BITMAP_OFFSET, shape.size.x, shape.size.y);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedImageInsert(wxCommandEvent& event)
|
||
|
{
|
||
|
wxFileName filename = wxFileSelector(
|
||
|
wxT("Choose an image file"),
|
||
|
wxEmptyString,
|
||
|
wxEmptyString,
|
||
|
wxEmptyString,
|
||
|
wxT("PNG files (*.png)|*.png"),
|
||
|
wxFD_OPEN,
|
||
|
this
|
||
|
);
|
||
|
|
||
|
if (!filename.IsOk() || !filename.MakeRelativeTo(wxGetCwd()))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_images.push_back(Image(filename.GetFullPath().ToAscii().data()));
|
||
|
|
||
|
UpdateImageList();
|
||
|
UpdateSpriteList();
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedImageDelete(wxCommandEvent& event)
|
||
|
{
|
||
|
if (m_imageIndex == wxNOT_FOUND)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_images.erase(m_images.begin() + m_imageIndex);
|
||
|
|
||
|
UpdateImageList();
|
||
|
UpdateSpriteList();
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedSpriteRename(wxCommandEvent& event)
|
||
|
{
|
||
|
if (m_imageIndex == wxNOT_FOUND || m_spriteIndex == wxNOT_FOUND)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
wxTextEntryDialog dialog(this, wxT("Sprite alias"), wxT("Input a sprite alias"), wxString::FromAscii(m_images[m_imageIndex].sprites[m_spriteIndex].alias.c_str()));
|
||
|
if (dialog.ShowModal() != wxID_OK || dialog.GetValue().IsEmpty())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_images[m_imageIndex].sprites[m_spriteIndex].alias = dialog.GetValue().ToAscii().data();
|
||
|
UpdateSpriteList();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedSpriteDelete(wxCommandEvent& event)
|
||
|
{
|
||
|
if (m_imageIndex == wxNOT_FOUND || m_spriteIndex == wxNOT_FOUND)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
std::vector<Sprite>& sprites = m_images[m_imageIndex].sprites;
|
||
|
sprites.erase(sprites.begin() + m_spriteIndex);
|
||
|
UpdateSpriteList();
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedShapeRename(wxCommandEvent& event)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnMenuSelectedShapeDelete(wxCommandEvent& event)
|
||
|
{
|
||
|
if (m_imageIndex == wxNOT_FOUND || m_spriteIndex == wxNOT_FOUND || m_shapeIndex == wxNOT_FOUND)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_images[m_imageIndex].sprites[m_spriteIndex].shapes[m_shapeIndex].enabled = false;
|
||
|
|
||
|
UpdateShapeList();
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnImagesRightDown(wxMouseEvent& event)
|
||
|
{
|
||
|
wxMenu menu;
|
||
|
menu.Append(ID_MENU_IMAGE_INSERT, wxT("&Insert image..."));
|
||
|
menu.Append(ID_MENU_IMAGE_DELETE, wxT("&Delete image"))->Enable(m_imageIndex != wxNOT_FOUND);
|
||
|
PopupMenu(&menu);
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnSpritesRightDown(wxMouseEvent& event)
|
||
|
{
|
||
|
wxMenu menu;
|
||
|
menu.Append(ID_MENU_SPRITE_RENAME, wxT("&Rename sprite..."))->Enable(m_spriteIndex != wxNOT_FOUND);
|
||
|
menu.Append(ID_MENU_SPRITE_DELETE, wxT("&Delete sprite"))->Enable(m_spriteIndex != wxNOT_FOUND);
|
||
|
PopupMenu(&menu);
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnShapesRightDown(wxMouseEvent& event)
|
||
|
{
|
||
|
wxMenu menu;
|
||
|
menu.Append(ID_MENU_SHAPE_RENAME, wxT("&Rename shape..."))->Enable(m_shapeIndex != wxNOT_FOUND);
|
||
|
menu.Append(ID_MENU_SHAPE_DELETE, wxT("&Delete shape"))->Enable(m_shapeIndex != wxNOT_FOUND);
|
||
|
PopupMenu(&menu);
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnImagesSelected(wxCommandEvent& event)
|
||
|
{
|
||
|
m_imageIndex = m_listImages->GetSelection();
|
||
|
|
||
|
if (m_imageIndex == wxNOT_FOUND)
|
||
|
{
|
||
|
m_currentBitmap = wxNullBitmap;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
const wxString filename = m_listImages->GetString(m_imageIndex);
|
||
|
m_currentBitmap.LoadFile(filename, wxBITMAP_TYPE_PNG);
|
||
|
}
|
||
|
|
||
|
UpdateSpriteList();
|
||
|
UpdateShapeList();
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnSpritesSelected(wxCommandEvent& event)
|
||
|
{
|
||
|
m_spriteIndex = m_listSprites->GetSelection();
|
||
|
UpdateShapeList();
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnShapesSelected(wxCommandEvent& event)
|
||
|
{
|
||
|
m_shapeIndex = m_listShapes->GetSelection();
|
||
|
UpdateCanvas();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnModifiedGrid(wxCommandEvent& event)
|
||
|
{
|
||
|
long gridSize = m_gridSize;
|
||
|
m_textGrid->GetValue().ToLong(&gridSize);
|
||
|
m_gridSize = gridSize;
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::OnClose(wxCloseEvent& event)
|
||
|
{
|
||
|
Hide();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::UpdateCanvas()
|
||
|
{
|
||
|
if (m_currentBitmap.IsOk())
|
||
|
{
|
||
|
m_panelCanvas->SetMinSize(wxSize(m_currentBitmap.GetWidth() + BITMAP_OFFSET, m_currentBitmap.GetHeight() + BITMAP_OFFSET));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_panelCanvas->SetMinSize(wxSize(0, 0));
|
||
|
}
|
||
|
|
||
|
m_scrolledWindow->FitInside();
|
||
|
m_panelCanvas->Refresh(false);
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::UpdateImageList()
|
||
|
{
|
||
|
m_listImages->Clear();
|
||
|
|
||
|
for (std::vector<Image>::iterator iter = m_images.begin(); iter != m_images.end(); ++iter)
|
||
|
{
|
||
|
m_listImages->Append(wxString::FromAscii(iter->filename.c_str()));
|
||
|
}
|
||
|
|
||
|
GetSizer()->Layout();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::UpdateSpriteList()
|
||
|
{
|
||
|
m_listSprites->Clear();
|
||
|
|
||
|
if (m_imageIndex != wxNOT_FOUND)
|
||
|
{
|
||
|
std::vector<Sprite>& sprites = m_images[m_imageIndex].sprites;
|
||
|
for (std::vector<Sprite>::iterator iter = sprites.begin(); iter != sprites.end(); ++iter)
|
||
|
{
|
||
|
m_listSprites->Append(wxString::FromAscii(iter->alias.c_str()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GetSizer()->Layout();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::UpdateShapeList()
|
||
|
{
|
||
|
static const wchar_t* shapeNames[] = { L"COLLISION_SOLID", L"COLLISION_INTERACT" };
|
||
|
|
||
|
m_listShapes->Clear();
|
||
|
|
||
|
if (m_imageIndex != wxNOT_FOUND && m_spriteIndex != wxNOT_FOUND)
|
||
|
{
|
||
|
const ActorShape* const shapes = m_images[m_imageIndex].sprites[m_spriteIndex].shapes;
|
||
|
for (int i = 0; i < ACTOR_SHAPE_TYPE_COUNT; ++i)
|
||
|
{
|
||
|
if (shapes[i].enabled)
|
||
|
{
|
||
|
m_listShapes->Append(wxString::Format(wxT("%s: %d"), shapeNames[i], shapes[i].data));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_listShapes->Append(wxString::Format(wxT("%s: NULL"), shapeNames[i]));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GetSizer()->Layout();
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::InitializeUi()
|
||
|
{
|
||
|
m_listImages = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE);
|
||
|
m_listImages->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(FrameSpriteEditor::OnImagesRightDown), NULL, this);
|
||
|
m_listImages->Connect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FrameSpriteEditor::OnImagesSelected), NULL, this);
|
||
|
|
||
|
m_listSprites = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE);
|
||
|
m_listSprites->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(FrameSpriteEditor::OnSpritesRightDown), NULL, this);
|
||
|
m_listSprites->Connect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FrameSpriteEditor::OnSpritesSelected), NULL, this);
|
||
|
|
||
|
m_listShapes = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE);
|
||
|
m_listShapes->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(FrameSpriteEditor::OnShapesRightDown), NULL, this);
|
||
|
m_listShapes->Connect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FrameSpriteEditor::OnShapesSelected), NULL, this);
|
||
|
|
||
|
m_scrolledWindow = new wxScrolledWindow(this);
|
||
|
m_scrolledWindow->SetScrollRate(1, 1);
|
||
|
|
||
|
m_panelCanvas = new wxPanel(m_scrolledWindow);
|
||
|
m_panelCanvas->SetBackgroundColour(wxColour(0x00, 0x00, 0x00));
|
||
|
m_panelCanvas->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(FrameSpriteEditor::OnCanvasLeftDown), NULL, this);
|
||
|
m_panelCanvas->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(FrameSpriteEditor::OnCanvasLeftUp), NULL, this);
|
||
|
m_panelCanvas->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(FrameSpriteEditor::OnCanvasRightDown), NULL, this);
|
||
|
m_panelCanvas->Connect(wxEVT_MOTION, wxMouseEventHandler(FrameSpriteEditor::OnCanvasMotion), NULL, this);
|
||
|
m_panelCanvas->Connect(wxEVT_PAINT, wxPaintEventHandler(FrameSpriteEditor::OnCanvasPaint), NULL, this);
|
||
|
|
||
|
m_textGrid = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
|
||
|
m_textGrid->Connect(wxEVT_COMMAND_TEXT_ENTER, wxTextEventHandler(FrameSpriteEditor::OnModifiedGrid), NULL, this);
|
||
|
m_textGrid->SetValue(wxString::Format(wxT("%d"), m_gridSize));
|
||
|
|
||
|
wxBoxSizer* sizerScroll = new wxBoxSizer(wxVERTICAL);
|
||
|
sizerScroll->Add(m_panelCanvas, 1, wxEXPAND);
|
||
|
m_scrolledWindow->SetSizer(sizerScroll);
|
||
|
|
||
|
wxBoxSizer* sizerOptions = new wxBoxSizer(wxHORIZONTAL);
|
||
|
sizerOptions->Add(new wxStaticText(this, wxID_ANY, wxT("Grid")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||
|
sizerOptions->Add(m_textGrid, 0, wxALL, 5);
|
||
|
|
||
|
wxBoxSizer* sizerAssets = new wxBoxSizer(wxVERTICAL);
|
||
|
sizerAssets->Add(new wxStaticText(this, wxID_ANY, wxT("Images")), 0, wxALL, 5);
|
||
|
sizerAssets->Add(m_listImages, 1, wxALL | wxEXPAND, 5);
|
||
|
sizerAssets->Add(new wxStaticText(this, wxID_ANY, wxT("Sprites")), 0, wxALL, 5);
|
||
|
sizerAssets->Add(m_listSprites, 1, wxALL | wxEXPAND, 5);
|
||
|
sizerAssets->Add(new wxStaticText(this, wxID_ANY, wxT("Shapes")), 0, wxALL, 5);
|
||
|
sizerAssets->Add(m_listShapes, 1, wxALL | wxEXPAND, 5);
|
||
|
|
||
|
wxBoxSizer* sizerCanvas = new wxBoxSizer(wxVERTICAL);
|
||
|
sizerCanvas->Add(m_scrolledWindow, 1, wxEXPAND | wxALL, 5);
|
||
|
sizerCanvas->Add(sizerOptions, 0, wxALIGN_RIGHT, 5);
|
||
|
|
||
|
wxBoxSizer* sizerLayout = new wxBoxSizer(wxHORIZONTAL);
|
||
|
sizerLayout->Add(sizerAssets, 0, wxEXPAND);
|
||
|
sizerLayout->Add(sizerCanvas, 1, wxEXPAND);
|
||
|
SetSizer(sizerLayout);
|
||
|
}
|
||
|
|
||
|
void FrameSpriteEditor::InitializeMenuBar()
|
||
|
{
|
||
|
wxMenu* menuFile = new wxMenu();
|
||
|
menuFile->Append(ID_MENU_FILE_NEW, wxT("&New\tCtrl+N"));
|
||
|
menuFile->Append(ID_MENU_FILE_OPEN, wxT("&Open\tCtrl+O"));
|
||
|
menuFile->Append(ID_MENU_FILE_SAVE, wxT("&Save\tCtrl+S"));
|
||
|
menuFile->Append(ID_MENU_FILE_SAVE_AS, wxT("Save &As...\tCtrl+Shift+S"));
|
||
|
menuFile->AppendSeparator();
|
||
|
menuFile->Append(ID_MENU_FILE_EXIT, wxT("E&xit\tCtrl+Q"));
|
||
|
|
||
|
wxMenuBar* menuBar = new wxMenuBar();
|
||
|
menuBar->Append(menuFile, wxT("&File"));
|
||
|
SetMenuBar(menuBar);
|
||
|
}
|
||
|
|
||
|
Vector2i FrameSpriteEditor::AdjustPosition(const Vector2i& position) const
|
||
|
{
|
||
|
const Vector2i mod(position.x % m_gridSize, position.y % m_gridSize);
|
||
|
Vector2i positionAdj = position - mod;
|
||
|
const Vector2i sign(positionAdj.x >= 0 ? 1 : -1, positionAdj.y >= 0 ? 1 : -1);
|
||
|
|
||
|
if (abs(mod.x) > m_gridSize / 2)
|
||
|
{
|
||
|
positionAdj.x += m_gridSize * sign.x;
|
||
|
}
|
||
|
|
||
|
if (abs(mod.y) > m_gridSize / 2)
|
||
|
{
|
||
|
positionAdj.y += m_gridSize * sign.y;
|
||
|
}
|
||
|
|
||
|
return positionAdj - Vector2i(BITMAP_OFFSET, BITMAP_OFFSET);
|
||
|
}
|