From 213cab3c04b81428ab715f340bd7c12438fdb980 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sun, 15 Mar 2015 23:24:22 -0400 Subject: Map editor can now add entities to maps Also fixed a big bug regarding scrolling --- tools/mapedit/src/frame.cpp | 129 +++++++++++++++++++++++++++++++++----- tools/mapedit/src/frame.h | 12 ++++ tools/mapedit/src/map.cpp | 4 +- tools/mapedit/src/map.h | 4 +- tools/mapedit/src/tile_widget.cpp | 10 ++- tools/mapedit/src/tile_widget.h | 4 +- tools/mapedit/src/widget.cpp | 123 +++++++++++++++++++++++++++++------- tools/mapedit/src/widget.h | 19 +++++- 8 files changed, 260 insertions(+), 45 deletions(-) diff --git a/tools/mapedit/src/frame.cpp b/tools/mapedit/src/frame.cpp index e0df030..aa77f1f 100644 --- a/tools/mapedit/src/frame.cpp +++ b/tools/mapedit/src/frame.cpp @@ -47,33 +47,82 @@ MapeditFrame::MapeditFrame(Map map, std::string filename) : wxFrame(NULL, wxID_A SetMenuBar(menuBar); // Layout 1: Splitter between map tree and layout 2 - // Layout 2: Non-splitter between layout 3 and tile chooser + // Layout 2: Non-splitter between layout 3 and notebook // Layout 3: Splitter between map editor and properties editor wxSplitterWindow* layout3 = new wxSplitterWindow(this, wxID_ANY); layout3->SetSashGravity(1.0); layout3->SetMinimumPaneSize(20); - tileEditor = new TileWidget(this, wxID_ANY, 6, 6, wxPoint(0,0), wxSize(TILE_WIDTH*6*7,TILE_HEIGHT*10*6)); + notebook = new wxNotebook(this, wxID_ANY); + + tileEditor = new TileWidget(notebook, wxID_ANY, 6, 6, wxPoint(0,0), wxSize(TILE_WIDTH*6*6,TILE_HEIGHT*10*6)); + notebook->AddPage(tileEditor, "Tile Chooser", true); + mapEditor = new MapeditWidget(layout3, wxID_ANY, &this->map, tileEditor, wxPoint(0,0), wxSize(GAME_WIDTH*2, GAME_HEIGHT*2)); + mapEditor->frame = this; + // Set up property editor wxPanel* propertyEditor = new wxPanel(layout3, wxID_ANY); titleBox = new wxTextCtrl(propertyEditor, wxID_ANY, map.getTitle()); titleBox->Bind(wxEVT_TEXT, &MapeditFrame::OnTitleChange, this); wxStaticText* titleLabel = new wxStaticText(propertyEditor, wxID_ANY, "Title:"); - wxFlexGridSizer* propertySizer = new wxFlexGridSizer(1, 2, 9, 25); - propertySizer->Add(titleLabel); - propertySizer->Add(titleBox, 1, wxEXPAND); + wxBoxSizer* propertySizer = new wxBoxSizer(wxVERTICAL); + wxBoxSizer* propertySizer1 = new wxBoxSizer(wxHORIZONTAL); + propertySizer1->Add(titleLabel, 0, wxALIGN_RIGHT | wxLEFT, 10); + propertySizer1->Add(titleBox, 1, wxALIGN_LEFT | wxLEFT | wxRIGHT, 10); + propertySizer->Add(propertySizer1, 1, wxEXPAND | wxTOP, 10); propertyEditor->SetSizer(propertySizer); propertySizer->SetSizeHints(propertyEditor); + // Set up entity editor + wxPanel* entityEditor = new wxPanel(notebook, wxID_ANY); + notebook->AddPage(entityEditor, "Entity Manager", false); + + wxStaticText* entityHeader = new wxStaticText(entityEditor, wxID_ANY, "Add Entity"); + wxFont font = entityHeader->GetFont(); + font.SetWeight(wxFONTWEIGHT_BOLD); + entityHeader->SetFont(font); + + wxStaticText* entityTypeLabel = new wxStaticText(entityEditor, wxID_ANY, "Entity Type:"); + + entityTypeBox = new wxChoice(entityEditor, wxID_ANY); + for (auto entry : MapObject::getAllObjects()) + { + entityTypeBox->Append(entry.second->getType(), entry.second.get()); + } + + addEntityButton = new wxButton(entityEditor, wxID_ANY, "Add Entity"); + addEntityButton->Bind(wxEVT_BUTTON, &MapeditFrame::OnAddEntity, this); + + cancelEntityButton = new wxButton(entityEditor, wxID_ANY, "Cancel"); + cancelEntityButton->Disable(); + cancelEntityButton->Bind(wxEVT_BUTTON, &MapeditFrame::OnCancelAddEntity, this); + + wxBoxSizer* entitySizer = new wxBoxSizer(wxVERTICAL); + entitySizer->Add(entityHeader, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5); + wxBoxSizer* entitySizer1 = new wxBoxSizer(wxHORIZONTAL); + entitySizer1->Add(entityTypeLabel, 0, wxALIGN_LEFT | wxRIGHT, 5); + entitySizer1->Add(entityTypeBox, 1, wxALIGN_LEFT, 0); + entitySizer->Add(entitySizer1, 0, wxEXPAND | wxALIGN_CENTER_HORIZONTAL | wxALL, 5); + wxBoxSizer* entitySizer2 = new wxBoxSizer(wxHORIZONTAL); + entitySizer2->Add(addEntityButton, 1, wxEXPAND | wxRIGHT, 2); + entitySizer2->Add(cancelEntityButton, 1, wxEXPAND | wxLEFT, 2); + entitySizer->Add(entitySizer2, 0, wxEXPAND | wxALIGN_CENTER_HORIZONTAL | wxALL, 5); + entityEditor->SetSizer(entitySizer); + entitySizer->SetSizeHints(entityEditor); + + // Finish setting up the layouts layout3->SplitHorizontally(mapEditor, propertyEditor); + notebook->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, &MapeditFrame::OnTabChange, this); + notebook->Bind(wxEVT_NOTEBOOK_PAGE_CHANGING, &MapeditFrame::OnTabChanging, this); + wxBoxSizer* sizer2 = new wxBoxSizer(wxHORIZONTAL); sizer2->Add(layout3, 1, wxEXPAND, 0); - sizer2->Add(tileEditor, 0, wxALIGN_TOP | wxALIGN_CENTER_HORIZONTAL | wxLEFT, 2); + sizer2->Add(notebook, 0, wxALIGN_TOP | wxALIGN_CENTER_HORIZONTAL | wxLEFT, 2); this->SetSizer(sizer2); sizer2->SetSizeHints(this); } @@ -115,22 +164,22 @@ MapeditWidget* MapeditFrame::GetMapEditor() return mapEditor; } -void MapeditFrame::ZoomIn(wxCommandEvent& event) +void MapeditFrame::ZoomIn(wxCommandEvent&) { mapEditor->ZoomIn(); } -void MapeditFrame::ZoomOut(wxCommandEvent& event) +void MapeditFrame::ZoomOut(wxCommandEvent&) { mapEditor->ZoomOut(); } -void MapeditFrame::OnNew(wxCommandEvent& event) +void MapeditFrame::OnNew(wxCommandEvent&) { NewMap(); } -void MapeditFrame::OnOpen(wxCommandEvent& event) +void MapeditFrame::OnOpen(wxCommandEvent&) { wxFileDialog openFileDialog(this, "Open map", "", "", "XML files (*.xml)|*.xml", wxFD_OPEN|wxFD_FILE_MUST_EXIST); if (openFileDialog.ShowModal() == wxID_CANCEL) @@ -141,7 +190,7 @@ void MapeditFrame::OnOpen(wxCommandEvent& event) OpenMap(openFileDialog.GetPath().c_str()); } -void MapeditFrame::OnSave(wxCommandEvent& event) +void MapeditFrame::OnSave(wxCommandEvent&) { if (filename == "") { @@ -157,12 +206,12 @@ void MapeditFrame::OnSave(wxCommandEvent& event) map.save(filename); } -void MapeditFrame::OnClose(wxCommandEvent& event) +void MapeditFrame::OnClose(wxCommandEvent&) { Close(false); } -void MapeditFrame::OnQuit(wxCommandEvent& event) +void MapeditFrame::OnQuit(wxCommandEvent&) { for (auto window : openWindows) { @@ -173,7 +222,7 @@ void MapeditFrame::OnQuit(wxCommandEvent& event) } } -void MapeditFrame::OnTitleChange(wxCommandEvent& event) +void MapeditFrame::OnTitleChange(wxCommandEvent&) { map.setTitle(titleBox->GetLineText(0).ToStdString()); } @@ -194,3 +243,55 @@ void MapeditFrame::LaunchWindow(Map map, const char* filename) frame->closer = openWindows.insert(end(openWindows), frame); frame->Show(true); } + +void MapeditFrame::OnTabChange(wxBookCtrlEvent& event) +{ + switch (event.GetSelection()) + { + case 0: + mapEditor->SetEditMode(EditTiles); + break; + + case 1: + mapEditor->SetEditMode(EditEntities); + break; + } + + event.Skip(); +} + +void MapeditFrame::OnTabChanging(wxBookCtrlEvent& event) +{ + if (addingEntity) + { + event.Veto(); + return; + } + + event.Skip(); +} + +void MapeditFrame::OnAddEntity(wxCommandEvent&) +{ + addingEntity = true; + addEntityButton->Disable(); + cancelEntityButton->Enable(); + + mapEditor->StartAddingEntity((MapObject*) entityTypeBox->GetClientData(entityTypeBox->GetSelection())); +} + +void MapeditFrame::OnCancelAddEntity(wxCommandEvent&) +{ + addingEntity = false; + addEntityButton->Enable(); + cancelEntityButton->Disable(); + + mapEditor->CancelAddingEntity(); +} + +void MapeditFrame::FinishAddingEntity() +{ + addingEntity = false; + addEntityButton->Enable(); + cancelEntityButton->Disable(); +} diff --git a/tools/mapedit/src/frame.h b/tools/mapedit/src/frame.h index 5e119f3..cb29480 100644 --- a/tools/mapedit/src/frame.h +++ b/tools/mapedit/src/frame.h @@ -11,6 +11,7 @@ #include "widget.h" #include "tile_widget.h" #include +#include class MapeditFrame : public wxFrame { public: @@ -18,6 +19,7 @@ class MapeditFrame : public wxFrame { MapeditFrame(Map map, std::string filename); MapeditWidget* GetMapEditor(); + void FinishAddingEntity(); static void NewMap(); static void OpenMap(const char* filename); @@ -36,12 +38,22 @@ class MapeditFrame : public wxFrame { void OnExit(wxCloseEvent& event); void OnQuit(wxCommandEvent& event); void OnTitleChange(wxCommandEvent& event); + void OnTabChange(wxBookCtrlEvent& event); + void OnTabChanging(wxBookCtrlEvent& event); + void OnAddEntity(wxCommandEvent& event); + void OnCancelAddEntity(wxCommandEvent& event); Map map; MapeditWidget* mapEditor; TileWidget* tileEditor; wxTextCtrl* titleBox; std::string filename; + wxNotebook* notebook; + wxChoice* entityTypeBox; + wxButton* addEntityButton; + wxButton* cancelEntityButton; + + bool addingEntity = false; wxDECLARE_EVENT_TABLE(); }; diff --git a/tools/mapedit/src/map.cpp b/tools/mapedit/src/map.cpp index b0440fb..1414e16 100644 --- a/tools/mapedit/src/map.cpp +++ b/tools/mapedit/src/map.cpp @@ -66,7 +66,7 @@ Map::Map(std::string filename) if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-type")) { xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1); - data.object = MapObject::getAllObjects().at((char*) key); + data.object = MapObject::getAllObjects().at((char*) key).get(); xmlFree(key); } else if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-position")) { @@ -226,7 +226,7 @@ void Map::setTitle(std::string title) this->title = title; } -std::list Map::getObjects() +std::list& Map::getObjects() { return objects; } diff --git a/tools/mapedit/src/map.h b/tools/mapedit/src/map.h index 52e047d..850a66b 100644 --- a/tools/mapedit/src/map.h +++ b/tools/mapedit/src/map.h @@ -44,7 +44,7 @@ class MapWriteException: public std::exception }; struct MapObjectEntry { - std::shared_ptr object; + MapObject* object; std::pair position; }; @@ -64,7 +64,7 @@ class Map { bool hasUnsavedChanges() const; void setTileAt(int x, int y, int tile); int getTileAt(int x, int y) const; - std::list getObjects(); + std::list& getObjects(); private: std::list objects; diff --git a/tools/mapedit/src/tile_widget.cpp b/tools/mapedit/src/tile_widget.cpp index 3b00e59..dc39fdd 100644 --- a/tools/mapedit/src/tile_widget.cpp +++ b/tools/mapedit/src/tile_widget.cpp @@ -34,7 +34,7 @@ void TileWidget::Init() SetVirtualSize(numTilesWidth*TILE_WIDTH*scale, (numTiles / numTilesWidth + 1) * TILE_HEIGHT*scale); } -void TileWidget::OnPaint(wxPaintEvent& event) +void TileWidget::OnPaint(wxPaintEvent&) { wxPaintDC dc(this); wxMemoryDC tiles_dc; @@ -42,6 +42,10 @@ void TileWidget::OnPaint(wxPaintEvent& event) int vX, vY, vW, vH, aW, aH; GetViewStart(&vX, &vY); + int vXX, vYX; + GetScrollPixelsPerUnit(&vXX, &vYX); + vX *= vXX; + vY *= vYX; GetVirtualSize(&vW, &vH); GetSize(&aW, &aH); @@ -63,6 +67,10 @@ void TileWidget::OnClick(wxMouseEvent& event) { int vX, vY, vW, vH; GetViewStart(&vX, &vY); + int vXX, vYX; + GetScrollPixelsPerUnit(&vXX, &vYX); + vX *= vXX; + vY *= vYX; GetVirtualSize(&vW, &vH); wxPoint pos = event.GetPosition(); diff --git a/tools/mapedit/src/tile_widget.h b/tools/mapedit/src/tile_widget.h index 2f1872d..ff45a37 100644 --- a/tools/mapedit/src/tile_widget.h +++ b/tools/mapedit/src/tile_widget.h @@ -28,8 +28,8 @@ class TileWidget : public wxScrolledCanvas { int selected = 0; int scale; - DECLARE_DYNAMIC_CLASS(MapeditWidget); - DECLARE_EVENT_TABLE(); + DECLARE_DYNAMIC_CLASS(MapeditWidget) + DECLARE_EVENT_TABLE() }; #endif diff --git a/tools/mapedit/src/widget.cpp b/tools/mapedit/src/widget.cpp index d7f1a51..ba3b6a5 100644 --- a/tools/mapedit/src/widget.cpp +++ b/tools/mapedit/src/widget.cpp @@ -1,4 +1,5 @@ #include "widget.h" +#include "frame.h" IMPLEMENT_DYNAMIC_CLASS(MapeditWidget,wxScrolledWindow) @@ -36,13 +37,17 @@ wxSize MapeditWidget::DoGetBestSize() const return {GAME_WIDTH*2, GAME_HEIGHT*2}; } -void MapeditWidget::OnPaint(wxPaintEvent& event) +void MapeditWidget::OnPaint(wxPaintEvent&) { wxPaintDC dc(this); wxMemoryDC tiles_dc; tiles_dc.SelectObject(tiles); int vX, vY; GetViewStart(&vX, &vY); + int vXX, vYX; + GetScrollPixelsPerUnit(&vXX, &vYX); + vX *= vXX; + vY *= vYX; for (int y=0; ygetWidth()*scale, object.object->getHeight()*scale, &tiles_dc, 0, 0, object.object->getWidth(), object.object->getHeight()); } - if (mouseIsIn) + if (editMode == EditTiles) { - int tile = tileWidget->getSelected(); - int x = (mousePos.x + vX) / (TILE_WIDTH * scale); - int y = (mousePos.y + vY) / (TILE_HEIGHT * scale); + if (mouseIsIn) + { + int tile = tileWidget->getSelected(); + int x = (mousePos.x + vX) / (TILE_WIDTH * scale); + int y = (mousePos.y + vY) / (TILE_HEIGHT * scale); - tiles_dc.SelectObject(wxNullBitmap); - tiles_dc.SelectObject(tiles); - dc.StretchBlit(x*TILE_WIDTH*scale-vX, y*TILE_HEIGHT*scale-vY, TILE_WIDTH*scale, TILE_HEIGHT*scale, &tiles_dc, tile%8*TILE_WIDTH, tile/8*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT); + tiles_dc.SelectObject(wxNullBitmap); + tiles_dc.SelectObject(tiles); + dc.StretchBlit(x*TILE_WIDTH*scale-vX, y*TILE_HEIGHT*scale-vY, TILE_WIDTH*scale, TILE_HEIGHT*scale, &tiles_dc, tile%8*TILE_WIDTH, tile/8*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT); - wxPen pen(*wxGREEN, 2); - dc.SetPen(pen); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.DrawRectangle(x*TILE_WIDTH*scale-vX, y*TILE_HEIGHT*scale-vY, TILE_WIDTH*scale, TILE_HEIGHT*scale); + wxPen pen(*wxGREEN, 2); + dc.SetPen(pen); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(x*TILE_WIDTH*scale-vX, y*TILE_HEIGHT*scale-vY, TILE_WIDTH*scale, TILE_HEIGHT*scale); + } + } else if (editMode == EditEntities) + { + if ((addingEntity != nullptr) && (mouseIsIn)) + { + wxBitmap sprite = addingEntity->getSprite(); + tiles_dc.SelectObject(wxNullBitmap); + tiles_dc.SelectObject(sprite); + + dc.StretchBlit(mousePos.x - addingEntity->getWidth()/2*scale, mousePos.y - addingEntity->getHeight()/2*scale, addingEntity->getWidth()*scale, addingEntity->getHeight()*scale, &tiles_dc, 0, 0, addingEntity->getWidth(), addingEntity->getHeight()); + + wxPen pen(*wxGREEN, 2); + dc.SetPen(pen); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(mousePos.x - addingEntity->getWidth()/2*scale, mousePos.y - addingEntity->getHeight()/2*scale, addingEntity->getWidth()*scale, addingEntity->getHeight()*scale); + } } } @@ -84,6 +107,10 @@ void MapeditWidget::SetTile(wxPoint pos) { int vX, vY; GetViewStart(&vX, &vY); + int vXX, vYX; + GetScrollPixelsPerUnit(&vXX, &vYX); + vX *= vXX; + vY *= vYX; int x = (pos.x + vX) / (TILE_WIDTH * scale); int y = (pos.y + vY) / (TILE_HEIGHT * scale); @@ -96,32 +123,64 @@ void MapeditWidget::OnClick(wxMouseEvent& event) { mouseIsDown = true; - SetTile(event.GetPosition()); + if (editMode == EditTiles) + { + SetTile(event.GetPosition()); + } else if (editMode == EditEntities) + { + if (addingEntity != nullptr) + { + int vX, vY; + GetViewStart(&vX, &vY); + int vXX, vYX; + GetScrollPixelsPerUnit(&vXX, &vYX); + vX *= vXX; + vY *= vYX; + + int x = (event.GetPosition().x + vX) / scale - (addingEntity->getWidth() / 2); + int y = (event.GetPosition().y + vY) / scale - (addingEntity->getHeight() / 2); + printf("%d,%d\n",x,y); + MapObjectEntry data; + data.object = addingEntity; + data.position = std::make_pair(x,y); + map->getObjects().push_back(data); + + addingEntity = nullptr; + + frame->FinishAddingEntity(); + + Refresh(); + } + } event.Skip(); } void MapeditWidget::OnMouseMove(wxMouseEvent& event) { - if (mouseIsDown) + mousePos = event.GetPosition(); + mouseIsIn = true; + + if (editMode == EditTiles) { - SetTile(event.GetPosition()); + if (mouseIsDown) + { + SetTile(event.GetPosition()); + } } - mouseIsIn = true; - mousePos = event.GetPosition(); Refresh(); } -void MapeditWidget::OnMouseUp(wxMouseEvent& event) +void MapeditWidget::OnMouseUp(wxMouseEvent&) { mouseIsDown = false; } -void MapeditWidget::OnMouseOut(wxMouseEvent& event) +void MapeditWidget::OnMouseOut(wxMouseEvent&) { mouseIsIn = false; - + Refresh(); } @@ -132,7 +191,10 @@ void MapeditWidget::ZoomIn() void MapeditWidget::ZoomOut() { - SetZoomSize(scale-1); + if (scale > 1) + { + SetZoomSize(scale-1); + } } void MapeditWidget::SetZoomSize(int zoom) @@ -141,5 +203,22 @@ void MapeditWidget::SetZoomSize(int zoom) SetVirtualSize(MAP_WIDTH*TILE_WIDTH*scale, MAP_HEIGHT*TILE_HEIGHT*scale); - GetParent()->Refresh(); + Refresh(); +} + +void MapeditWidget::SetEditMode(EditMode editMode) +{ + this->editMode = editMode; + + Refresh(); +} + +void MapeditWidget::StartAddingEntity(MapObject* object) +{ + addingEntity = object; +} + +void MapeditWidget::CancelAddingEntity() +{ + addingEntity = nullptr; } diff --git a/tools/mapedit/src/widget.h b/tools/mapedit/src/widget.h index c8bfb57..9de5b02 100644 --- a/tools/mapedit/src/widget.h +++ b/tools/mapedit/src/widget.h @@ -10,6 +10,13 @@ #include "map.h" #include "tile_widget.h" +class MapeditFrame; + +enum EditMode { + EditTiles, + EditEntities +}; + class MapeditWidget : public wxScrolledWindow { public: MapeditWidget(); @@ -17,6 +24,11 @@ class MapeditWidget : public wxScrolledWindow { void ZoomIn(); void ZoomOut(); + void SetEditMode(EditMode editMode); + void StartAddingEntity(MapObject* object); + void CancelAddingEntity(); + + MapeditFrame* frame; protected: void Init(); @@ -38,9 +50,12 @@ class MapeditWidget : public wxScrolledWindow { int scale; wxPoint mousePos; bool mouseIsIn = false; + EditMode editMode = EditTiles; + + MapObject* addingEntity = nullptr; - DECLARE_DYNAMIC_CLASS(MapeditWidget); - DECLARE_EVENT_TABLE(); + DECLARE_DYNAMIC_CLASS(MapeditWidget) + DECLARE_EVENT_TABLE() }; #endif -- cgit 1.4.1