diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2015-03-17 13:58:32 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2015-03-17 13:58:32 -0400 |
commit | e882367d80a0bcdd09b5412d908b0fdb6b6bfe34 (patch) | |
tree | e5a023fc51f02cf37b97bfbb9ef09d2ddfc6591e /tools | |
parent | 29f818c314f86f9a842840c20d9634f0711507a6 (diff) | |
download | therapy-e882367d80a0bcdd09b5412d908b0fdb6b6bfe34.tar.gz therapy-e882367d80a0bcdd09b5412d908b0fdb6b6bfe34.tar.bz2 therapy-e882367d80a0bcdd09b5412d908b0fdb6b6bfe34.zip |
Implemented undo/redo framework in map editor
Diffstat (limited to 'tools')
-rw-r--r-- | tools/mapedit/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tools/mapedit/src/frame.cpp | 197 | ||||
-rw-r--r-- | tools/mapedit/src/frame.h | 30 | ||||
-rw-r--r-- | tools/mapedit/src/map.cpp | 16 | ||||
-rw-r--r-- | tools/mapedit/src/map.h | 9 | ||||
-rw-r--r-- | tools/mapedit/src/undo.cpp | 95 | ||||
-rw-r--r-- | tools/mapedit/src/undo.h | 63 | ||||
-rw-r--r-- | tools/mapedit/src/widget.cpp | 110 | ||||
-rw-r--r-- | tools/mapedit/src/widget.h | 4 | ||||
-rw-r--r-- | tools/mapedit/src/world.cpp | 4 |
10 files changed, 482 insertions, 47 deletions
diff --git a/tools/mapedit/CMakeLists.txt b/tools/mapedit/CMakeLists.txt index 12af38c..ca44fc5 100644 --- a/tools/mapedit/CMakeLists.txt +++ b/tools/mapedit/CMakeLists.txt | |||
@@ -45,6 +45,7 @@ add_executable(AromatherapyMapEditor | |||
45 | src/tile_widget.cpp | 45 | src/tile_widget.cpp |
46 | src/object.cpp | 46 | src/object.cpp |
47 | src/world.cpp | 47 | src/world.cpp |
48 | src/undo.cpp | ||
48 | ) | 49 | ) |
49 | target_link_libraries(AromatherapyMapEditor ${ALL_LIBS}) | 50 | target_link_libraries(AromatherapyMapEditor ${ALL_LIBS}) |
50 | install(TARGETS AromatherapyMapEditor RUNTIME DESTINATION ${BIN_DIR}) | 51 | install(TARGETS AromatherapyMapEditor RUNTIME DESTINATION ${BIN_DIR}) |
diff --git a/tools/mapedit/src/frame.cpp b/tools/mapedit/src/frame.cpp index 66775e1..3646d4e 100644 --- a/tools/mapedit/src/frame.cpp +++ b/tools/mapedit/src/frame.cpp | |||
@@ -19,6 +19,8 @@ enum { | |||
19 | MENU_FILE_CLOSE, | 19 | MENU_FILE_CLOSE, |
20 | MENU_MAP_ADD_ROOT, | 20 | MENU_MAP_ADD_ROOT, |
21 | MENU_MAP_ADD_CHILD, | 21 | MENU_MAP_ADD_CHILD, |
22 | MENU_EDIT_UNDO, | ||
23 | MENU_EDIT_REDO, | ||
22 | TOOL_FILE_NEW, | 24 | TOOL_FILE_NEW, |
23 | TOOL_FILE_OPEN, | 25 | TOOL_FILE_OPEN, |
24 | TOOL_FILE_SAVE, | 26 | TOOL_FILE_SAVE, |
@@ -43,6 +45,8 @@ wxBEGIN_EVENT_TABLE(MapeditFrame, wxFrame) | |||
43 | EVT_MENU(MENU_FILE_CLOSE, MapeditFrame::OnClose) | 45 | EVT_MENU(MENU_FILE_CLOSE, MapeditFrame::OnClose) |
44 | EVT_MENU(MENU_MAP_ADD_ROOT, MapeditFrame::OnAddRoot) | 46 | EVT_MENU(MENU_MAP_ADD_ROOT, MapeditFrame::OnAddRoot) |
45 | EVT_MENU(MENU_MAP_ADD_CHILD, MapeditFrame::OnAddChild) | 47 | EVT_MENU(MENU_MAP_ADD_CHILD, MapeditFrame::OnAddChild) |
48 | EVT_MENU(MENU_EDIT_UNDO, MapeditFrame::OnUndo) | ||
49 | EVT_MENU(MENU_EDIT_REDO, MapeditFrame::OnRedo) | ||
46 | EVT_TOOL(TOOL_FILE_NEW, MapeditFrame::OnNew) | 50 | EVT_TOOL(TOOL_FILE_NEW, MapeditFrame::OnNew) |
47 | EVT_TOOL(TOOL_FILE_OPEN, MapeditFrame::OnOpen) | 51 | EVT_TOOL(TOOL_FILE_OPEN, MapeditFrame::OnOpen) |
48 | EVT_TOOL(TOOL_FILE_SAVE, MapeditFrame::OnSave) | 52 | EVT_TOOL(TOOL_FILE_SAVE, MapeditFrame::OnSave) |
@@ -51,7 +55,6 @@ wxBEGIN_EVENT_TABLE(MapeditFrame, wxFrame) | |||
51 | EVT_CLOSE(MapeditFrame::OnExit) | 55 | EVT_CLOSE(MapeditFrame::OnExit) |
52 | EVT_NOTEBOOK_PAGE_CHANGED(MAP_EDITOR_NOTEBOOK, MapeditFrame::OnTabChange) | 56 | EVT_NOTEBOOK_PAGE_CHANGED(MAP_EDITOR_NOTEBOOK, MapeditFrame::OnTabChange) |
53 | EVT_NOTEBOOK_PAGE_CHANGING(MAP_EDITOR_NOTEBOOK, MapeditFrame::OnTabChanging) | 57 | EVT_NOTEBOOK_PAGE_CHANGING(MAP_EDITOR_NOTEBOOK, MapeditFrame::OnTabChanging) |
54 | EVT_TREE_SEL_CHANGING(MAP_EDITOR_TREE, MapeditFrame::OnWillSelectMap) | ||
55 | EVT_TREE_SEL_CHANGED(MAP_EDITOR_TREE, MapeditFrame::OnDidSelectMap) | 58 | EVT_TREE_SEL_CHANGED(MAP_EDITOR_TREE, MapeditFrame::OnDidSelectMap) |
56 | EVT_TREE_BEGIN_DRAG(MAP_EDITOR_TREE, MapeditFrame::OnWillDragMap) | 59 | EVT_TREE_BEGIN_DRAG(MAP_EDITOR_TREE, MapeditFrame::OnWillDragMap) |
57 | EVT_TREE_END_DRAG(MAP_EDITOR_TREE, MapeditFrame::OnDidDragMap) | 60 | EVT_TREE_END_DRAG(MAP_EDITOR_TREE, MapeditFrame::OnDidDragMap) |
@@ -80,12 +83,18 @@ MapeditFrame::MapeditFrame(std::unique_ptr<World> world) : wxFrame(NULL, wxID_AN | |||
80 | menuFile->AppendSeparator(); | 83 | menuFile->AppendSeparator(); |
81 | menuFile->Append(wxID_EXIT); | 84 | menuFile->Append(wxID_EXIT); |
82 | 85 | ||
86 | menuEdit = new wxMenu; | ||
87 | menuEdit->Append(MENU_EDIT_UNDO, "Undo\tCtrl-Z"); | ||
88 | menuEdit->Append(MENU_EDIT_REDO, "Redo\tCtrl-Shift-Z"); | ||
89 | UpdateUndoLabels(); | ||
90 | |||
83 | wxMenu* menuView = new wxMenu; | 91 | wxMenu* menuView = new wxMenu; |
84 | menuView->Append(MENU_VIEW_ZOOM_IN, "Zoom In\tCtrl-+"); | 92 | menuView->Append(MENU_VIEW_ZOOM_IN, "Zoom In\tCtrl-+"); |
85 | menuView->Append(MENU_VIEW_ZOOM_OUT, "Zoom Out\tCtrl--"); | 93 | menuView->Append(MENU_VIEW_ZOOM_OUT, "Zoom Out\tCtrl--"); |
86 | 94 | ||
87 | wxMenuBar* menuBar = new wxMenuBar; | 95 | wxMenuBar* menuBar = new wxMenuBar; |
88 | menuBar->Append(menuFile, "&File"); | 96 | menuBar->Append(menuFile, "&File"); |
97 | menuBar->Append(menuEdit, "&Edit"); | ||
89 | menuBar->Append(menuView, "&View"); | 98 | menuBar->Append(menuView, "&View"); |
90 | 99 | ||
91 | SetMenuBar(menuBar); | 100 | SetMenuBar(menuBar); |
@@ -118,7 +127,7 @@ MapeditFrame::MapeditFrame(std::unique_ptr<World> world) : wxFrame(NULL, wxID_AN | |||
118 | 127 | ||
119 | // Set up property editor | 128 | // Set up property editor |
120 | wxPanel* propertyEditor = new wxPanel(layout3, wxID_ANY); | 129 | wxPanel* propertyEditor = new wxPanel(layout3, wxID_ANY); |
121 | titleBox = new wxTextCtrl(propertyEditor, MAP_TITLE_TEXTBOX, currentMap->getTitle()); | 130 | titleBox = new UndoableTextBox(propertyEditor, MAP_TITLE_TEXTBOX, currentMap->getTitle(), "Edit Map Title", this); |
122 | titleBox->SetMaxLength(40); | 131 | titleBox->SetMaxLength(40); |
123 | 132 | ||
124 | wxStaticText* titleLabel = new wxStaticText(propertyEditor, wxID_ANY, "Title:"); | 133 | wxStaticText* titleLabel = new wxStaticText(propertyEditor, wxID_ANY, "Title:"); |
@@ -216,8 +225,9 @@ MapeditFrame::MapeditFrame(std::unique_ptr<World> world) : wxFrame(NULL, wxID_AN | |||
216 | toolbar->EnableTool(TOOL_FILE_SAVE, this->world->getDirty()); | 225 | toolbar->EnableTool(TOOL_FILE_SAVE, this->world->getDirty()); |
217 | toolbar->Realize(); | 226 | toolbar->Realize(); |
218 | 227 | ||
219 | mapTree->SetFocusedItem(currentMap->getTreeItemId()); | 228 | dontSelectMap = true; |
220 | SelectMap(currentMap); | 229 | mapTree->SelectItem(currentMap->getTreeItemId()); |
230 | dontSelectMap = false; | ||
221 | 231 | ||
222 | Maximize(true); | 232 | Maximize(true); |
223 | } | 233 | } |
@@ -324,10 +334,12 @@ void MapeditFrame::OnQuit(wxCommandEvent&) | |||
324 | } | 334 | } |
325 | } | 335 | } |
326 | 336 | ||
327 | void MapeditFrame::OnTitleChange(wxCommandEvent&) | 337 | void MapeditFrame::OnTitleChange(wxCommandEvent& event) |
328 | { | 338 | { |
329 | currentMap->setTitle(titleBox->GetValue().ToStdString()); | 339 | currentMap->setTitle(titleBox->GetValue().ToStdString()); |
330 | mapTree->SetItemText(currentMap->getTreeItemId(), currentMap->getTitle()); | 340 | mapTree->SetItemText(currentMap->getTreeItemId(), titleBox->GetValue()); |
341 | |||
342 | event.Skip(); | ||
331 | } | 343 | } |
332 | 344 | ||
333 | void MapeditFrame::OnTabChange(wxBookCtrlEvent& event) | 345 | void MapeditFrame::OnTabChange(wxBookCtrlEvent& event) |
@@ -378,33 +390,83 @@ void MapeditFrame::OnCancelAddEntity(wxCommandEvent&) | |||
378 | void MapeditFrame::OnAddRoot(wxCommandEvent&) | 390 | void MapeditFrame::OnAddRoot(wxCommandEvent&) |
379 | { | 391 | { |
380 | auto map = world->newMap(); | 392 | auto map = world->newMap(); |
381 | wxTreeItemId node = mapTree->AppendItem(mapTree->GetItemParent(mapTree->GetSelection()), map->getTitle()); | 393 | |
382 | map->setTreeItemId(node); | 394 | commitAction(std::make_shared<Undoable>("New Map", [=] () { |
383 | mapTree->SetItemData(node, new MapPtrCtr(map.get())); | 395 | map->setHidden(false); |
384 | mapTree->SetFocusedItem(node); | 396 | |
385 | SelectMap(map.get()); | 397 | wxTreeItemId sel = mapTree->GetSelection(); |
398 | wxTreeItemId par = mapTree->GetItemParent(sel); | ||
399 | wxTreeItemId node = mapTree->AppendItem(par, map->getTitle()); | ||
400 | map->setTreeItemId(node); | ||
401 | mapTree->SetItemData(node, new MapPtrCtr(map.get())); | ||
402 | |||
403 | dontSelectMap = true; | ||
404 | mapTree->SelectItem(node); | ||
405 | dontSelectMap = false; | ||
406 | }, [=] () { | ||
407 | map->setHidden(true); | ||
408 | |||
409 | wxTreeItemId sel = mapTree->GetPrevSibling(map->getTreeItemId()); | ||
410 | mapTree->Delete(map->getTreeItemId()); | ||
411 | |||
412 | dontSelectMap = true; | ||
413 | mapTree->SelectItem(sel); | ||
414 | dontSelectMap = false; | ||
415 | })); | ||
416 | |||
386 | } | 417 | } |
387 | 418 | ||
388 | void MapeditFrame::OnAddChild(wxCommandEvent&) | 419 | void MapeditFrame::OnAddChild(wxCommandEvent&) |
389 | { | 420 | { |
390 | auto map = world->newMap(); | 421 | auto map = world->newMap(); |
391 | wxTreeItemId node = mapTree->AppendItem(mapTree->GetSelection(), map->getTitle()); | 422 | |
392 | map->setTreeItemId(node); | 423 | commitAction(std::make_shared<Undoable>("New Map", [=] () { |
393 | mapTree->SetItemData(node, new MapPtrCtr(map.get())); | 424 | map->setHidden(false); |
394 | mapTree->SetFocusedItem(node); | 425 | |
395 | mapTree->Expand(mapTree->GetSelection()); | 426 | wxTreeItemId sel = mapTree->GetSelection(); |
396 | SelectMap(map.get()); | 427 | wxTreeItemId node = mapTree->AppendItem(sel, map->getTitle()); |
428 | map->setTreeItemId(node); | ||
429 | mapTree->SetItemData(node, new MapPtrCtr(map.get())); | ||
430 | |||
431 | mapTree->Expand(sel); | ||
432 | |||
433 | dontSelectMap = true; | ||
434 | mapTree->SelectItem(node); | ||
435 | dontSelectMap = false; | ||
436 | }, [=] () { | ||
437 | map->setHidden(true); | ||
438 | |||
439 | wxTreeItemId sel = mapTree->GetItemParent(map->getTreeItemId()); | ||
440 | mapTree->Delete(map->getTreeItemId()); | ||
441 | |||
442 | dontSelectMap = true; | ||
443 | mapTree->SelectItem(sel); | ||
444 | dontSelectMap = false; | ||
445 | })); | ||
397 | } | 446 | } |
398 | 447 | ||
399 | void MapeditFrame::OnDidSelectMap(wxTreeEvent& event) | 448 | void MapeditFrame::OnDidSelectMap(wxTreeEvent& event) |
400 | { | 449 | { |
401 | MapPtrCtr* data = (MapPtrCtr*) mapTree->GetItemData(event.GetItem()); | 450 | MapPtrCtr* data = (MapPtrCtr*) mapTree->GetItemData(event.GetItem()); |
402 | SelectMap(data->map); | 451 | SelectMap(data->map); |
403 | } | 452 | |
404 | 453 | if (!dontSelectMap) | |
405 | void MapeditFrame::OnWillSelectMap(wxTreeEvent& event) | 454 | { |
406 | { | 455 | commitAfter(std::make_shared<Undoable>("Selecting " + data->map->getTitle(), [=] () { |
407 | event.Skip(); | 456 | wxTreeItemId toSelect = event.GetItem(); |
457 | dontSelectMap = true; | ||
458 | mapTree->SelectItem(toSelect); | ||
459 | dontSelectMap = false; | ||
460 | SelectMap(data->map); | ||
461 | }, [=] () { | ||
462 | wxTreeItemId toSelect = event.GetOldItem(); | ||
463 | MapPtrCtr* oldData = (MapPtrCtr*) mapTree->GetItemData(toSelect); | ||
464 | dontSelectMap = true; | ||
465 | mapTree->SelectItem(toSelect); | ||
466 | dontSelectMap = false; | ||
467 | SelectMap(oldData->map); | ||
468 | })); | ||
469 | } | ||
408 | } | 470 | } |
409 | 471 | ||
410 | void MapeditFrame::OnWillDragMap(wxTreeEvent& event) | 472 | void MapeditFrame::OnWillDragMap(wxTreeEvent& event) |
@@ -426,9 +488,24 @@ void MapeditFrame::OnDidDragMap(wxTreeEvent& event) | |||
426 | newParent = mapTree->GetRootItem(); | 488 | newParent = mapTree->GetRootItem(); |
427 | } | 489 | } |
428 | 490 | ||
429 | wxTreeItemId newChild = MoveTreeNode(dragMap, newParent); | 491 | wxTreeItemId curParent = mapTree->GetItemParent(event.GetItem()); |
492 | wxTreeItemId dragMapCopy = dragMap; | ||
430 | dragMap.Unset(); | 493 | dragMap.Unset(); |
431 | mapTree->SelectItem(newChild); | 494 | |
495 | Map* theMap = ((MapPtrCtr*) mapTree->GetItemData(dragMap))->map; | ||
496 | commitAction(std::make_shared<Undoable>("Arranging " + theMap->getTitle(), [=] () { | ||
497 | wxTreeItemId newChild = MoveTreeNode(dragMapCopy, newParent); | ||
498 | |||
499 | dontSelectMap = true; | ||
500 | mapTree->SelectItem(newChild); | ||
501 | dontSelectMap = false; | ||
502 | }, [=] () { | ||
503 | wxTreeItemId newChild = MoveTreeNode(dragMapCopy, curParent); | ||
504 | |||
505 | dontSelectMap = true; | ||
506 | mapTree->SelectItem(newChild); | ||
507 | dontSelectMap = false; | ||
508 | })); | ||
432 | } | 509 | } |
433 | 510 | ||
434 | void MapeditFrame::OnRightClickTree(wxTreeEvent& event) | 511 | void MapeditFrame::OnRightClickTree(wxTreeEvent& event) |
@@ -451,6 +528,28 @@ void MapeditFrame::OnCancelSetStartpos(wxCommandEvent&) | |||
451 | mapEditor->SetIsSettingStart(false); | 528 | mapEditor->SetIsSettingStart(false); |
452 | } | 529 | } |
453 | 530 | ||
531 | void MapeditFrame::OnUndo(wxCommandEvent&) | ||
532 | { | ||
533 | (*currentAction)->endChanges(); | ||
534 | (*currentAction)->undo(); | ||
535 | currentAction++; | ||
536 | |||
537 | UpdateUndoLabels(); | ||
538 | } | ||
539 | |||
540 | void MapeditFrame::OnRedo(wxCommandEvent&) | ||
541 | { | ||
542 | if (currentAction != end(history)) | ||
543 | { | ||
544 | (*currentAction)->endChanges(); | ||
545 | } | ||
546 | |||
547 | currentAction--; | ||
548 | (*currentAction)->apply(); | ||
549 | |||
550 | UpdateUndoLabels(); | ||
551 | } | ||
552 | |||
454 | void MapeditFrame::NewWorld() | 553 | void MapeditFrame::NewWorld() |
455 | { | 554 | { |
456 | LaunchWindow(std::unique_ptr<World>(new World())); | 555 | LaunchWindow(std::unique_ptr<World>(new World())); |
@@ -531,6 +630,10 @@ void MapeditFrame::SelectMap(Map* map) | |||
531 | { | 630 | { |
532 | currentMap = map; | 631 | currentMap = map; |
533 | mapEditor->SetMap(map); | 632 | mapEditor->SetMap(map); |
633 | |||
634 | SetIsAddingEntity(false); | ||
635 | SetIsSettingStart(false); | ||
636 | |||
534 | titleBox->ChangeValue(map->getTitle()); | 637 | titleBox->ChangeValue(map->getTitle()); |
535 | world->setLastMap(map); | 638 | world->setLastMap(map); |
536 | } | 639 | } |
@@ -592,3 +695,49 @@ void MapeditFrame::SetStartposLabel() | |||
592 | 695 | ||
593 | startposLabel->SetLabel(mappos_out.str()); | 696 | startposLabel->SetLabel(mappos_out.str()); |
594 | } | 697 | } |
698 | |||
699 | void MapeditFrame::UpdateUndoLabels() | ||
700 | { | ||
701 | if (currentAction != end(history)) | ||
702 | { | ||
703 | menuEdit->SetLabel(MENU_EDIT_UNDO, "Undo " + (*currentAction)->getTitle() + "\tCtrl-Z"); | ||
704 | menuEdit->Enable(MENU_EDIT_UNDO, true); | ||
705 | } else { | ||
706 | menuEdit->SetLabel(MENU_EDIT_UNDO, "Undo\tCtrl-Z"); | ||
707 | menuEdit->Enable(MENU_EDIT_UNDO, false); | ||
708 | } | ||
709 | |||
710 | if (currentAction != begin(history)) | ||
711 | { | ||
712 | menuEdit->SetLabel(MENU_EDIT_REDO, "Redo " + (*std::prev(currentAction))->getTitle() + "\tCtrl-Shift-Z"); | ||
713 | menuEdit->Enable(MENU_EDIT_REDO, true); | ||
714 | } else { | ||
715 | menuEdit->SetLabel(MENU_EDIT_REDO, "Redo\tCtrl-Shift-Z"); | ||
716 | menuEdit->Enable(MENU_EDIT_REDO, false); | ||
717 | } | ||
718 | } | ||
719 | |||
720 | void MapeditFrame::commitAction(std::shared_ptr<Undoable> action) | ||
721 | { | ||
722 | action->apply(); | ||
723 | |||
724 | commitAfter(action); | ||
725 | } | ||
726 | |||
727 | void MapeditFrame::commitAfter(std::shared_ptr<Undoable> action) | ||
728 | { | ||
729 | if (currentAction != end(history)) | ||
730 | { | ||
731 | (*currentAction)->endChanges(); | ||
732 | } | ||
733 | |||
734 | history.erase(begin(history), currentAction); | ||
735 | currentAction = history.insert(begin(history), action); | ||
736 | |||
737 | UpdateUndoLabels(); | ||
738 | |||
739 | if (history.size() > 100) | ||
740 | { | ||
741 | history.pop_back(); | ||
742 | } | ||
743 | } | ||
diff --git a/tools/mapedit/src/frame.h b/tools/mapedit/src/frame.h index 067c848..b0f27e9 100644 --- a/tools/mapedit/src/frame.h +++ b/tools/mapedit/src/frame.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <wx/notebook.h> | 14 | #include <wx/notebook.h> |
15 | #include <memory> | 15 | #include <memory> |
16 | #include <wx/treectrl.h> | 16 | #include <wx/treectrl.h> |
17 | #include "undo.h" | ||
17 | 18 | ||
18 | class MapPtrCtr : public wxTreeItemData { | 19 | class MapPtrCtr : public wxTreeItemData { |
19 | public: | 20 | public: |
@@ -37,7 +38,6 @@ class MapeditFrame : public wxFrame { | |||
37 | 38 | ||
38 | std::list<wxWindow*>::iterator closer; | 39 | std::list<wxWindow*>::iterator closer; |
39 | 40 | ||
40 | private: | ||
41 | static void LaunchWindow(std::unique_ptr<World> world); | 41 | static void LaunchWindow(std::unique_ptr<World> world); |
42 | void populateMapTree(wxTreeItemId node, std::list<std::shared_ptr<Map>> maps); | 42 | void populateMapTree(wxTreeItemId node, std::list<std::shared_ptr<Map>> maps); |
43 | void SelectMap(Map* map); | 43 | void SelectMap(Map* map); |
@@ -60,7 +60,6 @@ class MapeditFrame : public wxFrame { | |||
60 | void OnAddRoot(wxCommandEvent& event); | 60 | void OnAddRoot(wxCommandEvent& event); |
61 | void OnAddChild(wxCommandEvent& event); | 61 | void OnAddChild(wxCommandEvent& event); |
62 | void OnDidSelectMap(wxTreeEvent& event); | 62 | void OnDidSelectMap(wxTreeEvent& event); |
63 | void OnWillSelectMap(wxTreeEvent& event); | ||
64 | void OnWillDragMap(wxTreeEvent& event); | 63 | void OnWillDragMap(wxTreeEvent& event); |
65 | void OnDidDragMap(wxTreeEvent& event); | 64 | void OnDidDragMap(wxTreeEvent& event); |
66 | void OnRightClickTree(wxTreeEvent& event); | 65 | void OnRightClickTree(wxTreeEvent& event); |
@@ -69,25 +68,44 @@ class MapeditFrame : public wxFrame { | |||
69 | 68 | ||
70 | std::unique_ptr<World> world; | 69 | std::unique_ptr<World> world; |
71 | Map* currentMap; | 70 | Map* currentMap; |
71 | |||
72 | MapeditWidget* mapEditor; | 72 | MapeditWidget* mapEditor; |
73 | TileWidget* tileEditor; | 73 | TileWidget* tileEditor; |
74 | wxTextCtrl* titleBox; | 74 | wxToolBar* toolbar; |
75 | std::string filename; | 75 | wxMenu* menuFile; |
76 | |||
77 | // Notebook | ||
76 | wxNotebook* notebook; | 78 | wxNotebook* notebook; |
77 | wxChoice* entityTypeBox; | 79 | wxChoice* entityTypeBox; |
78 | wxButton* addEntityButton; | 80 | wxButton* addEntityButton; |
79 | wxButton* cancelEntityButton; | 81 | wxButton* cancelEntityButton; |
80 | wxToolBar* toolbar; | 82 | |
81 | wxMenu* menuFile; | 83 | // Map tree |
82 | wxTreeCtrl* mapTree; | 84 | wxTreeCtrl* mapTree; |
83 | wxTreeItemId dragMap; | 85 | wxTreeItemId dragMap; |
84 | wxMenu* mapTreePopup; | 86 | wxMenu* mapTreePopup; |
87 | bool dontSelectMap = false; | ||
88 | |||
89 | // Property editor | ||
90 | UndoableTextBox* titleBox; | ||
91 | wxString prevTitle; | ||
85 | wxStaticText* startposLabel; | 92 | wxStaticText* startposLabel; |
86 | wxButton* setStartposButton; | 93 | wxButton* setStartposButton; |
87 | wxButton* cancelStartposButton; | 94 | wxButton* cancelStartposButton; |
88 | 95 | ||
96 | // Undo stuff | ||
97 | wxMenu* menuEdit; | ||
98 | std::list<std::shared_ptr<Undoable>> history; | ||
99 | std::list<std::shared_ptr<Undoable>>::iterator currentAction {begin(history)}; | ||
100 | void OnUndo(wxCommandEvent& event); | ||
101 | void OnRedo(wxCommandEvent& event); | ||
102 | void UpdateUndoLabels(); | ||
103 | void commitAction(std::shared_ptr<Undoable> action); | ||
104 | void commitAfter(std::shared_ptr<Undoable> action); | ||
105 | |||
89 | bool addingEntity = false; | 106 | bool addingEntity = false; |
90 | 107 | ||
108 | private: | ||
91 | wxDECLARE_EVENT_TABLE(); | 109 | wxDECLARE_EVENT_TABLE(); |
92 | }; | 110 | }; |
93 | 111 | ||
diff --git a/tools/mapedit/src/map.cpp b/tools/mapedit/src/map.cpp index 0f8826c..0db7031 100644 --- a/tools/mapedit/src/map.cpp +++ b/tools/mapedit/src/map.cpp | |||
@@ -19,6 +19,7 @@ Map::Map(const Map& map) | |||
19 | world = map.world; | 19 | world = map.world; |
20 | treeItemId = map.treeItemId; | 20 | treeItemId = map.treeItemId; |
21 | children = map.children; | 21 | children = map.children; |
22 | hidden = map.hidden; | ||
22 | } | 23 | } |
23 | 24 | ||
24 | Map::Map(Map&& map) : Map(-1, map.world) | 25 | Map::Map(Map&& map) : Map(-1, map.world) |
@@ -49,6 +50,7 @@ void swap(Map& first, Map& second) | |||
49 | std::swap(first.world, second.world); | 50 | std::swap(first.world, second.world); |
50 | std::swap(first.treeItemId, second.treeItemId); | 51 | std::swap(first.treeItemId, second.treeItemId); |
51 | std::swap(first.children, second.children); | 52 | std::swap(first.children, second.children); |
53 | std::swap(first.hidden, second.hidden); | ||
52 | } | 54 | } |
53 | 55 | ||
54 | int Map::getID() const | 56 | int Map::getID() const |
@@ -118,6 +120,11 @@ World* Map::getWorld() const | |||
118 | return world; | 120 | return world; |
119 | } | 121 | } |
120 | 122 | ||
123 | bool Map::getHidden() const | ||
124 | { | ||
125 | return hidden; | ||
126 | } | ||
127 | |||
121 | void Map::setTitle(std::string title, bool dirty) | 128 | void Map::setTitle(std::string title, bool dirty) |
122 | { | 129 | { |
123 | this->title = title; | 130 | this->title = title; |
@@ -149,7 +156,7 @@ void Map::setMapdata(int* mapdata, bool dirty) | |||
149 | } | 156 | } |
150 | } | 157 | } |
151 | 158 | ||
152 | void Map::addObject(std::shared_ptr<MapObjectEntry>& obj, bool dirty) | 159 | void Map::addObject(std::shared_ptr<MapObjectEntry> obj, bool dirty) |
153 | { | 160 | { |
154 | objects.push_back(obj); | 161 | objects.push_back(obj); |
155 | 162 | ||
@@ -159,7 +166,7 @@ void Map::addObject(std::shared_ptr<MapObjectEntry>& obj, bool dirty) | |||
159 | } | 166 | } |
160 | } | 167 | } |
161 | 168 | ||
162 | void Map::removeObject(std::shared_ptr<MapObjectEntry>& obj, bool dirty) | 169 | void Map::removeObject(std::shared_ptr<MapObjectEntry> obj, bool dirty) |
163 | { | 170 | { |
164 | objects.remove(obj); | 171 | objects.remove(obj); |
165 | 172 | ||
@@ -203,3 +210,8 @@ void Map::setExpanded(bool exp) | |||
203 | { | 210 | { |
204 | expanded = exp; | 211 | expanded = exp; |
205 | } | 212 | } |
213 | |||
214 | void Map::setHidden(bool hid) | ||
215 | { | ||
216 | hidden = hid; | ||
217 | } | ||
diff --git a/tools/mapedit/src/map.h b/tools/mapedit/src/map.h index df3e237..34dcb33 100644 --- a/tools/mapedit/src/map.h +++ b/tools/mapedit/src/map.h | |||
@@ -53,7 +53,7 @@ class MapWriteException: public std::exception | |||
53 | 53 | ||
54 | struct MapObjectEntry { | 54 | struct MapObjectEntry { |
55 | MapObject* object; | 55 | MapObject* object; |
56 | std::pair<double, double> position; | 56 | std::pair<int, int> position; |
57 | 57 | ||
58 | bool operator==(MapObjectEntry& other) const | 58 | bool operator==(MapObjectEntry& other) const |
59 | { | 59 | { |
@@ -85,17 +85,19 @@ class Map { | |||
85 | std::list<std::shared_ptr<Map>> getChildren() const; | 85 | std::list<std::shared_ptr<Map>> getChildren() const; |
86 | bool getExpanded() const; | 86 | bool getExpanded() const; |
87 | World* getWorld() const; | 87 | World* getWorld() const; |
88 | bool getHidden() const; | ||
88 | 89 | ||
89 | void setTitle(std::string title, bool dirty = true); | 90 | void setTitle(std::string title, bool dirty = true); |
90 | void setTileAt(int x, int y, int tile, bool dirty = true); | 91 | void setTileAt(int x, int y, int tile, bool dirty = true); |
91 | void setMapdata(int* mapdata, bool dirty = true); | 92 | void setMapdata(int* mapdata, bool dirty = true); |
92 | void addObject(std::shared_ptr<MapObjectEntry>& obj, bool dirty = true); | 93 | void addObject(std::shared_ptr<MapObjectEntry> obj, bool dirty = true); |
93 | void removeObject(std::shared_ptr<MapObjectEntry>& obj, bool dirty = true); | 94 | void removeObject(std::shared_ptr<MapObjectEntry> obj, bool dirty = true); |
94 | void setLeftmap(int id, bool dirty = true); | 95 | void setLeftmap(int id, bool dirty = true); |
95 | void setRightmap(int id, bool dirty = true); | 96 | void setRightmap(int id, bool dirty = true); |
96 | void setTreeItemId(wxTreeItemId id); | 97 | void setTreeItemId(wxTreeItemId id); |
97 | void addChild(int id); | 98 | void addChild(int id); |
98 | void setExpanded(bool exp); | 99 | void setExpanded(bool exp); |
100 | void setHidden(bool hid); | ||
99 | 101 | ||
100 | private: | 102 | private: |
101 | int id; | 103 | int id; |
@@ -108,6 +110,7 @@ class Map { | |||
108 | int rightmap = -1; | 110 | int rightmap = -1; |
109 | wxTreeItemId treeItemId; | 111 | wxTreeItemId treeItemId; |
110 | bool expanded = false; | 112 | bool expanded = false; |
113 | bool hidden = false; | ||
111 | }; | 114 | }; |
112 | 115 | ||
113 | #endif | 116 | #endif |
diff --git a/tools/mapedit/src/undo.cpp b/tools/mapedit/src/undo.cpp new file mode 100644 index 0000000..bcf7b92 --- /dev/null +++ b/tools/mapedit/src/undo.cpp | |||
@@ -0,0 +1,95 @@ | |||
1 | #include "undo.h" | ||
2 | #include "frame.h" | ||
3 | |||
4 | Undoable::Undoable(std::string title, std::function<void ()> forward, std::function<void ()> backward) | ||
5 | { | ||
6 | this->title = title; | ||
7 | this->forward = forward; | ||
8 | this->backward = backward; | ||
9 | } | ||
10 | |||
11 | std::string Undoable::getTitle() const | ||
12 | { | ||
13 | return title; | ||
14 | } | ||
15 | |||
16 | void Undoable::apply() | ||
17 | { | ||
18 | forward(); | ||
19 | } | ||
20 | |||
21 | void Undoable::undo() | ||
22 | { | ||
23 | backward(); | ||
24 | } | ||
25 | |||
26 | wxBEGIN_EVENT_TABLE(UndoableTextBox, wxTextCtrl) | ||
27 | EVT_SET_FOCUS(UndoableTextBox::OnFocus) | ||
28 | EVT_KILL_FOCUS(UndoableTextBox::OnKillFocus) | ||
29 | wxEND_EVENT_TABLE() | ||
30 | |||
31 | UndoableTextBox::UndoableTextBox(wxWindow* parent, wxWindowID id, wxString startText, std::string undoType, MapeditFrame* realParent, wxPoint pos, wxSize size, long style) : wxTextCtrl(parent, id, startText, pos, size, style) | ||
32 | { | ||
33 | this->undoText = undoType; | ||
34 | this->realParent = realParent; | ||
35 | |||
36 | Init(); | ||
37 | } | ||
38 | |||
39 | void UndoableTextBox::Init() | ||
40 | { | ||
41 | Bind(wxEVT_TEXT, &UndoableTextBox::OnTextChange, this); | ||
42 | |||
43 | curText = GetValue(); | ||
44 | } | ||
45 | |||
46 | void UndoableTextBox::OnFocus(wxFocusEvent& event) | ||
47 | { | ||
48 | curText = GetValue(); | ||
49 | |||
50 | event.Skip(); | ||
51 | } | ||
52 | |||
53 | void UndoableTextBox::OnKillFocus(wxFocusEvent& event) | ||
54 | { | ||
55 | undo.reset(); | ||
56 | |||
57 | event.Skip(); | ||
58 | } | ||
59 | |||
60 | void UndoableTextBox::OnTextChange(wxCommandEvent& event) | ||
61 | { | ||
62 | if (!undo) | ||
63 | { | ||
64 | auto tempUndo = std::make_shared<Undo>(undoText, curText, *this); | ||
65 | |||
66 | realParent->commitAfter(tempUndo); | ||
67 | |||
68 | undo = tempUndo; | ||
69 | } | ||
70 | |||
71 | undo->newText = GetValue(); | ||
72 | curText = GetValue(); | ||
73 | |||
74 | event.Skip(); | ||
75 | } | ||
76 | |||
77 | UndoableTextBox::Undo::Undo(std::string title, wxString origText, UndoableTextBox& parent) : origText(origText), parent(parent) | ||
78 | { | ||
79 | this->title = title; | ||
80 | } | ||
81 | |||
82 | void UndoableTextBox::Undo::apply() | ||
83 | { | ||
84 | parent.ChangeValue(newText); | ||
85 | } | ||
86 | |||
87 | void UndoableTextBox::Undo::undo() | ||
88 | { | ||
89 | parent.ChangeValue(origText); | ||
90 | } | ||
91 | |||
92 | void UndoableTextBox::Undo::endChanges() | ||
93 | { | ||
94 | parent.undo.reset(); | ||
95 | } | ||
diff --git a/tools/mapedit/src/undo.h b/tools/mapedit/src/undo.h new file mode 100644 index 0000000..794f993 --- /dev/null +++ b/tools/mapedit/src/undo.h | |||
@@ -0,0 +1,63 @@ | |||
1 | #ifndef UNDO_H | ||
2 | #define UNDO_H | ||
3 | |||
4 | #include <wx/wxprec.h> | ||
5 | |||
6 | #ifndef WX_PRECOMP | ||
7 | #include <wx/wx.h> | ||
8 | #endif | ||
9 | |||
10 | #include <functional> | ||
11 | #include <string> | ||
12 | #include <list> | ||
13 | |||
14 | class MapeditFrame; | ||
15 | |||
16 | class Undoable { | ||
17 | public: | ||
18 | Undoable(std::string title, std::function<void ()> forward, std::function<void ()> backward); | ||
19 | virtual std::string getTitle() const; | ||
20 | virtual void apply(); | ||
21 | virtual void undo(); | ||
22 | virtual void endChanges() {} | ||
23 | |||
24 | protected: | ||
25 | Undoable() {} | ||
26 | |||
27 | std::string title; | ||
28 | std::function<void ()> forward; | ||
29 | std::function<void ()> backward; | ||
30 | }; | ||
31 | |||
32 | class UndoableTextBox : public wxTextCtrl { | ||
33 | public: | ||
34 | UndoableTextBox(); | ||
35 | UndoableTextBox(wxWindow* parent, wxWindowID id, wxString startText, std::string undoType, MapeditFrame* realParent, wxPoint pos = wxDefaultPosition, wxSize size = wxDefaultSize, long style = 0); | ||
36 | |||
37 | private: | ||
38 | class Undo : public Undoable { | ||
39 | public: | ||
40 | Undo(std::string title, wxString origText, UndoableTextBox& parent); | ||
41 | void apply(); | ||
42 | void undo(); | ||
43 | void endChanges(); | ||
44 | |||
45 | wxString origText; | ||
46 | wxString newText; | ||
47 | UndoableTextBox& parent; | ||
48 | }; | ||
49 | |||
50 | void Init(); | ||
51 | void OnFocus(wxFocusEvent& event); | ||
52 | void OnKillFocus(wxFocusEvent& event); | ||
53 | void OnTextChange(wxCommandEvent& event); | ||
54 | |||
55 | MapeditFrame* realParent; | ||
56 | std::string undoText; | ||
57 | wxString curText; | ||
58 | std::shared_ptr<Undo> undo; | ||
59 | |||
60 | wxDECLARE_EVENT_TABLE(); | ||
61 | }; | ||
62 | |||
63 | #endif | ||
diff --git a/tools/mapedit/src/widget.cpp b/tools/mapedit/src/widget.cpp index 6cbedcd..61a8d65 100644 --- a/tools/mapedit/src/widget.cpp +++ b/tools/mapedit/src/widget.cpp | |||
@@ -55,6 +55,11 @@ void MapeditWidget::OnPaint(wxPaintEvent&) | |||
55 | for (int x=0; x<MAP_WIDTH; x++) | 55 | for (int x=0; x<MAP_WIDTH; x++) |
56 | { | 56 | { |
57 | int tile = map->getTileAt(x, y); | 57 | int tile = map->getTileAt(x, y); |
58 | if (changeBuffer.find({x,y}) != end(changeBuffer)) | ||
59 | { | ||
60 | tile = tileWidget->getSelected(); | ||
61 | } | ||
62 | |||
58 | 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); | 63 | 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); |
59 | } | 64 | } |
60 | } | 65 | } |
@@ -151,6 +156,21 @@ void MapeditWidget::OnPaint(wxPaintEvent&) | |||
151 | dc.SetPen(pen); | 156 | dc.SetPen(pen); |
152 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | 157 | dc.SetBrush(*wxTRANSPARENT_BRUSH); |
153 | dc.DrawRectangle(pos.x, pos.y, size.GetWidth(), size.GetHeight()); | 158 | dc.DrawRectangle(pos.x, pos.y, size.GetWidth(), size.GetHeight()); |
159 | } else if ((editMode == EditEntities) && (movingEntity != nullptr)) | ||
160 | { | ||
161 | wxBitmap sprite = movingEntity->object->getSprite(); | ||
162 | tiles_dc.SelectObject(wxNullBitmap); | ||
163 | tiles_dc.SelectObject(sprite); | ||
164 | |||
165 | wxPoint pos {mousePos.x - movingEntity->object->getWidth()/2*scale, mousePos.y - movingEntity->object->getHeight()/2*scale}; | ||
166 | wxSize size {movingEntity->object->getWidth()*scale, movingEntity->object->getHeight()*scale}; | ||
167 | |||
168 | dc.StretchBlit(pos.x, pos.y, size.GetWidth(), size.GetHeight(), &tiles_dc, 0, 0, movingEntity->object->getWidth(), movingEntity->object->getHeight()); | ||
169 | |||
170 | wxPen pen(*wxGREEN, 2); | ||
171 | dc.SetPen(pen); | ||
172 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | ||
173 | dc.DrawRectangle(pos.x, pos.y, size.GetWidth(), size.GetHeight()); | ||
154 | } | 174 | } |
155 | } | 175 | } |
156 | } | 176 | } |
@@ -167,7 +187,8 @@ void MapeditWidget::SetTile(wxPoint pos) | |||
167 | int x = (pos.x + vX) / (TILE_WIDTH * scale); | 187 | int x = (pos.x + vX) / (TILE_WIDTH * scale); |
168 | int y = (pos.y + vY) / (TILE_HEIGHT * scale); | 188 | int y = (pos.y + vY) / (TILE_HEIGHT * scale); |
169 | 189 | ||
170 | map->setTileAt(x, y, tileWidget->getSelected()); | 190 | changeBuffer.insert({x,y}); |
191 | |||
171 | Refresh(); | 192 | Refresh(); |
172 | } | 193 | } |
173 | 194 | ||
@@ -191,17 +212,42 @@ void MapeditWidget::OnClick(wxMouseEvent& event) | |||
191 | { | 212 | { |
192 | int x = (event.GetPosition().x + vX) / scale - (addingEntity->getWidth() / 2); | 213 | int x = (event.GetPosition().x + vX) / scale - (addingEntity->getWidth() / 2); |
193 | int y = (event.GetPosition().y + vY) / scale - (addingEntity->getHeight() / 2); | 214 | int y = (event.GetPosition().y + vY) / scale - (addingEntity->getHeight() / 2); |
194 | 215 | ||
195 | auto data = std::make_shared<MapObjectEntry>(); | 216 | auto data = std::make_shared<MapObjectEntry>(); |
196 | data->object = addingEntity; | 217 | data->object = addingEntity; |
197 | data->position = std::make_pair(x,y); | 218 | data->position = std::make_pair(x,y); |
198 | map->addObject(data); | ||
199 | 219 | ||
200 | addingEntity = nullptr; | 220 | frame->commitAction(std::make_shared<Undoable>("Add " + addingEntity->getType(), [=] () { |
221 | map->addObject(data); | ||
222 | |||
223 | Refresh(); | ||
224 | }, [=] () { | ||
225 | map->removeObject(data); | ||
226 | |||
227 | Refresh(); | ||
228 | })); | ||
201 | 229 | ||
202 | frame->SetIsAddingEntity(false); | 230 | frame->SetIsAddingEntity(false); |
231 | addingEntity = nullptr; | ||
232 | } else if (movingEntity != nullptr) | ||
233 | { | ||
234 | int x = (event.GetPosition().x + vX) / scale - (movingEntity->object->getWidth() / 2); | ||
235 | int y = (event.GetPosition().y + vY) / scale - (movingEntity->object->getHeight() / 2); | ||
236 | auto oldPos = movingEntity->position; | ||
237 | MapObjectEntry* me = movingEntity; | ||
203 | 238 | ||
204 | Refresh(); | 239 | frame->commitAction(std::make_shared<Undoable>("Move " + movingEntity->object->getType(), [=] () { |
240 | me->position = std::make_pair(x,y); | ||
241 | |||
242 | Refresh(); | ||
243 | }, [=] () { | ||
244 | me->position = oldPos; | ||
245 | |||
246 | Refresh(); | ||
247 | })); | ||
248 | |||
249 | frame->SetIsAddingEntity(false); | ||
250 | movingEntity = nullptr; | ||
205 | } else { | 251 | } else { |
206 | int x = (event.GetPosition().x + vX) / scale; | 252 | int x = (event.GetPosition().x + vX) / scale; |
207 | int y = (event.GetPosition().y + vY) / scale; | 253 | int y = (event.GetPosition().y + vY) / scale; |
@@ -211,9 +257,7 @@ void MapeditWidget::OnClick(wxMouseEvent& event) | |||
211 | if ((x > selectedEntity->position.first) && (x < selectedEntity->position.first + selectedEntity->object->getWidth()) | 257 | if ((x > selectedEntity->position.first) && (x < selectedEntity->position.first + selectedEntity->object->getWidth()) |
212 | && (y > selectedEntity->position.second) && (y < selectedEntity->position.second + selectedEntity->object->getHeight())) | 258 | && (y > selectedEntity->position.second) && (y < selectedEntity->position.second + selectedEntity->object->getHeight())) |
213 | { | 259 | { |
214 | addingEntity = selectedEntity->object; | 260 | movingEntity = selectedEntity.get(); |
215 | map->removeObject(selectedEntity); | ||
216 | selectedEntity.reset(); | ||
217 | frame->SetIsAddingEntity(true); | 261 | frame->SetIsAddingEntity(true); |
218 | } else { | 262 | } else { |
219 | selectedEntity.reset(); | 263 | selectedEntity.reset(); |
@@ -241,12 +285,23 @@ void MapeditWidget::OnClick(wxMouseEvent& event) | |||
241 | { | 285 | { |
242 | int x = (event.GetPosition().x + vX) / scale - (PLAYER_WIDTH[currentPlayer] / 2); | 286 | int x = (event.GetPosition().x + vX) / scale - (PLAYER_WIDTH[currentPlayer] / 2); |
243 | int y = (event.GetPosition().y + vY) / scale - (PLAYER_HEIGHT[currentPlayer] / 2); | 287 | int y = (event.GetPosition().y + vY) / scale - (PLAYER_HEIGHT[currentPlayer] / 2); |
288 | auto oldPos = map->getWorld()->getStartingPosition(); | ||
289 | auto oldSMap = map->getWorld()->getStartingMap(); | ||
290 | |||
291 | frame->commitAction(std::make_shared<Undoable>("Set Starting Position", [=] () { | ||
292 | map->getWorld()->setStart(map, {x, y}); | ||
293 | frame->SetStartposLabel(); | ||
294 | |||
295 | Refresh(); | ||
296 | }, [=] () { | ||
297 | map->getWorld()->setStart(oldSMap, oldPos); | ||
298 | frame->SetStartposLabel(); | ||
299 | |||
300 | Refresh(); | ||
301 | })); | ||
244 | 302 | ||
245 | map->getWorld()->setStart(map, {x, y}); | ||
246 | isSettingPos = false; | 303 | isSettingPos = false; |
247 | frame->SetIsSettingStart(false); | 304 | frame->SetIsSettingStart(false); |
248 | |||
249 | Refresh(); | ||
250 | } | 305 | } |
251 | 306 | ||
252 | event.Skip(); | 307 | event.Skip(); |
@@ -299,6 +354,34 @@ void MapeditWidget::OnMouseMove(wxMouseEvent& event) | |||
299 | void MapeditWidget::OnMouseUp(wxMouseEvent&) | 354 | void MapeditWidget::OnMouseUp(wxMouseEvent&) |
300 | { | 355 | { |
301 | mouseIsDown = false; | 356 | mouseIsDown = false; |
357 | |||
358 | if (editMode == EditTiles) | ||
359 | { | ||
360 | std::map<std::pair<int, int>, int> localChangeBuffer; | ||
361 | for (auto assign : changeBuffer) | ||
362 | { | ||
363 | localChangeBuffer[assign] = map->getTileAt(assign.first, assign.second); | ||
364 | } | ||
365 | |||
366 | int localSelection = tileWidget->getSelected(); | ||
367 | frame->commitAction(std::make_shared<Undoable>("Paint Map", [=] () { | ||
368 | for (auto assign : localChangeBuffer) | ||
369 | { | ||
370 | map->setTileAt(assign.first.first, assign.first.second, localSelection); | ||
371 | } | ||
372 | |||
373 | Refresh(); | ||
374 | }, [=] () { | ||
375 | for (auto assign : localChangeBuffer) | ||
376 | { | ||
377 | map->setTileAt(assign.first.first, assign.first.second, assign.second); | ||
378 | } | ||
379 | |||
380 | Refresh(); | ||
381 | })); | ||
382 | |||
383 | changeBuffer.clear(); | ||
384 | } | ||
302 | } | 385 | } |
303 | 386 | ||
304 | void MapeditWidget::OnMouseOut(wxMouseEvent&) | 387 | void MapeditWidget::OnMouseOut(wxMouseEvent&) |
@@ -350,6 +433,7 @@ void MapeditWidget::StartAddingEntity(MapObject* object) | |||
350 | void MapeditWidget::CancelAddingEntity() | 433 | void MapeditWidget::CancelAddingEntity() |
351 | { | 434 | { |
352 | addingEntity = nullptr; | 435 | addingEntity = nullptr; |
436 | movingEntity = nullptr; | ||
353 | } | 437 | } |
354 | 438 | ||
355 | void MapeditWidget::SetIsSettingStart(bool isSetting) | 439 | void MapeditWidget::SetIsSettingStart(bool isSetting) |
@@ -369,6 +453,10 @@ void MapeditWidget::SetIsSettingStart(bool isSetting) | |||
369 | void MapeditWidget::SetMap(Map* map) | 453 | void MapeditWidget::SetMap(Map* map) |
370 | { | 454 | { |
371 | this->map = map; | 455 | this->map = map; |
456 | selectedEntity = nullptr; | ||
457 | addingEntity = nullptr; | ||
458 | movingEntity = nullptr; | ||
459 | isSettingPos = false; | ||
372 | 460 | ||
373 | Refresh(); | 461 | Refresh(); |
374 | } | 462 | } |
diff --git a/tools/mapedit/src/widget.h b/tools/mapedit/src/widget.h index 67ebc01..4ae22c7 100644 --- a/tools/mapedit/src/widget.h +++ b/tools/mapedit/src/widget.h | |||
@@ -11,6 +11,8 @@ | |||
11 | #include "tile_widget.h" | 11 | #include "tile_widget.h" |
12 | #include <list> | 12 | #include <list> |
13 | #include <memory> | 13 | #include <memory> |
14 | #include <utility> | ||
15 | #include <set> | ||
14 | 16 | ||
15 | class MapeditFrame; | 17 | class MapeditFrame; |
16 | 18 | ||
@@ -58,8 +60,10 @@ class MapeditWidget : public wxScrolledWindow { | |||
58 | EditMode editMode = EditTiles; | 60 | EditMode editMode = EditTiles; |
59 | int currentPlayer = 0; | 61 | int currentPlayer = 0; |
60 | bool isSettingPos = false; | 62 | bool isSettingPos = false; |
63 | std::set<std::pair<int,int>> changeBuffer; | ||
61 | 64 | ||
62 | MapObject* addingEntity = nullptr; | 65 | MapObject* addingEntity = nullptr; |
66 | MapObjectEntry* movingEntity = nullptr; | ||
63 | std::shared_ptr<MapObjectEntry> selectedEntity; | 67 | std::shared_ptr<MapObjectEntry> selectedEntity; |
64 | 68 | ||
65 | DECLARE_DYNAMIC_CLASS(MapeditWidget) | 69 | DECLARE_DYNAMIC_CLASS(MapeditWidget) |
diff --git a/tools/mapedit/src/world.cpp b/tools/mapedit/src/world.cpp index 3145e4e..db1201e 100644 --- a/tools/mapedit/src/world.cpp +++ b/tools/mapedit/src/world.cpp | |||
@@ -135,7 +135,7 @@ World::World(std::string filename) | |||
135 | } else if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-position")) | 135 | } else if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-position")) |
136 | { | 136 | { |
137 | xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1); | 137 | xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1); |
138 | sscanf((char*) key, "%lf,%lf", &data->position.first, &data->position.second); | 138 | sscanf((char*) key, "%d,%d", &data->position.first, &data->position.second); |
139 | xmlFree(key); | 139 | xmlFree(key); |
140 | } | 140 | } |
141 | } | 141 | } |
@@ -268,6 +268,8 @@ void World::save(std::string name, wxTreeCtrl* mapTree) | |||
268 | { | 268 | { |
269 | Map& map = *mapPair.second; | 269 | Map& map = *mapPair.second; |
270 | 270 | ||
271 | if (map.getHidden()) continue; | ||
272 | |||
271 | // <map> | 273 | // <map> |
272 | rc = xmlTextWriterStartElement(writer, (xmlChar*) "map"); | 274 | rc = xmlTextWriterStartElement(writer, (xmlChar*) "map"); |
273 | if (rc < 0) throw MapWriteException(name); | 275 | if (rc < 0) throw MapWriteException(name); |