mirror of
https://github.com/CorsixTH/CorsixTH.git
synced 2025-07-23 04:13:01 +02:00
* Hand formatted changes before automatic formatting * Break up / shorten some long lines * Add some missing braces for clarity * Multiline strings are merged to let clang-format split them appropriately. * sdl_core's frame_count changed from a C style array to std::array which made the length checks simpler. * Add includes and forward declairs to avoid transitive dependencies * Remove th_gfx_font.h include from th_gfx.h - circular dependencies * using to shorten lines in th_map.cpp * Avoid non-portable reinterpret_cast for parcels in th_map. * Use more constants in th_map. * Use class initializer for th_map classes * Add clang files to ignore list * Add clang-format file * Reformat all files with clang-format Also includes some manual braces. * Disable clang-format for backdrop.h * Clang-format AnimView src files * clang-format common code * Fix anonymous struct in union warning Anonymous structs in anonymous unions are not supported by the standard. * Check clang-format in travis * Bin pack parameters * Bin pack arguments too * Full Google style 2 space indent, no forced break on braces. * A couple format overrides Order of usings in config.h.in since 8 is smaller than 16. Table layout, since 0x80 nicely fits in 8 columns.
814 lines
31 KiB
C++
814 lines
31 KiB
C++
/*
|
|
Copyright (c) 2009 Peter "Corsix" Cawley
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
this software and associated documentation files (the "Software"), to deal in
|
|
the Software without restriction, including without limitation the rights to
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
of the Software, and to permit persons to whom the Software is furnished to do
|
|
so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
|
|
#include "frmMain.h"
|
|
#include "config.h"
|
|
#include <wx/bitmap.h>
|
|
#include <wx/dcclient.h>
|
|
#include <wx/dcmemory.h>
|
|
#include <wx/dir.h>
|
|
#include <wx/dirdlg.h>
|
|
#include <wx/filename.h>
|
|
#include <wx/image.h>
|
|
#include <wx/msgdlg.h>
|
|
#include <wx/numdlg.h>
|
|
#include <wx/radiobut.h>
|
|
#include <wx/sizer.h>
|
|
#include <wx/stattext.h>
|
|
#include <wx/tokenzr.h>
|
|
#include <wx/wfstream.h>
|
|
#include "backdrop.h"
|
|
|
|
BEGIN_EVENT_TABLE(frmMain, wxFrame)
|
|
EVT_BUTTON(ID_LOAD, frmMain::_onLoad)
|
|
EVT_BUTTON(ID_BROWSE, frmMain::_onBrowse)
|
|
EVT_BUTTON(ID_FIRST_ANIM, frmMain::_onFirstAnim)
|
|
EVT_BUTTON(ID_PREV_ANIM, frmMain::_onPrevAnim)
|
|
EVT_BUTTON(ID_NEXT_ANIM, frmMain::_onNextAnim)
|
|
EVT_BUTTON(ID_LAST_ANIM, frmMain::_onLastAnim)
|
|
EVT_BUTTON(ID_PREV_FRAME, frmMain::_onPrevFrame)
|
|
EVT_BUTTON(ID_NEXT_FRAME, frmMain::_onNextFrame)
|
|
EVT_BUTTON(ID_PLAY_PAUSE, frmMain::_onPlayPause)
|
|
EVT_BUTTON(ID_SEARCH_LAYER_ID, frmMain::_onSearchLayerId)
|
|
EVT_BUTTON(ID_SEARCH_FRAME, frmMain::_onSearchFrame)
|
|
EVT_BUTTON(ID_SEARCH_SOUND, frmMain::_onSearchSoundIndex)
|
|
EVT_LISTBOX(ID_SEARCH_RESULTS, frmMain::_onGotoSearchResult)
|
|
EVT_RADIOBUTTON(ID_GHOST_0, frmMain::_onGhostFileChange)
|
|
EVT_RADIOBUTTON(ID_GHOST_1, frmMain::_onGhostFileChange)
|
|
EVT_RADIOBUTTON(ID_GHOST_2, frmMain::_onGhostFileChange)
|
|
EVT_RADIOBUTTON(ID_GHOST_3, frmMain::_onGhostFileChange)
|
|
EVT_SPINCTRL(wxID_ANY, frmMain::_onGhostIndexChange)
|
|
EVT_TEXT(ID_ANIM_INDEX, frmMain::_onAnimChar)
|
|
EVT_TIMER(ID_TIMER_ANIMATE, frmMain::_onTimer)
|
|
EVT_CHECKBOX(ID_DRAW_MOOD, frmMain::_onToggleDrawMood)
|
|
EVT_CHECKBOX(ID_DRAW_COORDINATES, frmMain::_onToggleDrawCoordinates)
|
|
END_EVENT_TABLE()
|
|
|
|
frmMain::frmMain()
|
|
: wxFrame(NULL, wxID_ANY, L"Theme Hospital Animation Viewer") {
|
|
wxSizer* pMainSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
wxSizer* pSidebarSizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
#define def wxDefaultPosition, wxDefaultSize
|
|
wxStaticBoxSizer* pThemeHospital =
|
|
new wxStaticBoxSizer(wxHORIZONTAL, this, L"Theme Hospital");
|
|
pThemeHospital->Add(new wxStaticText(this, wxID_ANY, L"Directory:"), 0,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pThemeHospital->Add(
|
|
m_txtTHPath = new wxTextCtrl(this, wxID_ANY, L"", def, wxTE_CENTRE), 1,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pThemeHospital->Add(new wxButton(this, ID_BROWSE, L"Browse..."), 0,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pThemeHospital->Add(new wxButton(this, ID_LOAD, L"Load"), 0,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pSidebarSizer->Add(pThemeHospital, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pPalette =
|
|
new wxStaticBoxSizer(wxVERTICAL, this, L"Palette");
|
|
wxBoxSizer* pPaletteTop = new wxBoxSizer(wxHORIZONTAL);
|
|
pPaletteTop->Add(new wxRadioButton(this, ID_GHOST_0, L"Standard"), 1);
|
|
pPaletteTop->Add(new wxRadioButton(this, ID_GHOST_1, L"Ghost 1"), 1);
|
|
pPaletteTop->Add(new wxRadioButton(this, ID_GHOST_2, L"Ghost 2"), 1);
|
|
pPaletteTop->Add(new wxRadioButton(this, ID_GHOST_3, L"Ghost 66"), 1);
|
|
m_iGhostFile = 0;
|
|
m_iGhostIndex = 0;
|
|
pPalette->Add(pPaletteTop, 0, wxEXPAND | wxALL, 1);
|
|
pPalette->Add(new wxSpinCtrl(this, wxID_ANY, wxEmptyString, def,
|
|
wxSP_ARROW_KEYS | wxSP_WRAP, 0, 255),
|
|
0, wxALIGN_CENTER | wxALL, 1);
|
|
pSidebarSizer->Add(pPalette, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pAnimation =
|
|
new wxStaticBoxSizer(wxHORIZONTAL, this, L"Animation");
|
|
pAnimation->Add(new wxButton(this, ID_FIRST_ANIM, L"<<", def, wxBU_EXACTFIT),
|
|
0, wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pAnimation->Add(new wxButton(this, ID_PREV_ANIM, L"<", def, wxBU_EXACTFIT), 0,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pAnimation->Add(m_txtAnimIndex = new wxTextCtrl(this, ID_ANIM_INDEX, L"0",
|
|
def, wxTE_CENTRE),
|
|
1, wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pAnimation->Add(new wxStaticText(this, wxID_ANY, L"of"), 0,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pAnimation->Add(m_txtAnimCount = new wxTextCtrl(this, wxID_ANY, L"?", def,
|
|
wxTE_CENTRE | wxTE_READONLY),
|
|
1, wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pAnimation->Add(new wxButton(this, ID_NEXT_ANIM, L">", def, wxBU_EXACTFIT), 0,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pAnimation->Add(new wxButton(this, ID_LAST_ANIM, L">>", def, wxBU_EXACTFIT),
|
|
0, wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pSidebarSizer->Add(pAnimation, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pFrame = new wxStaticBoxSizer(wxHORIZONTAL, this, L"Frame");
|
|
pFrame->Add(new wxButton(this, ID_PREV_FRAME, L"<", def, wxBU_EXACTFIT), 0,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pFrame->Add(
|
|
m_txtFrameIndex = new wxTextCtrl(this, wxID_ANY, L"0", def, wxTE_CENTRE),
|
|
1, wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pFrame->Add(new wxStaticText(this, wxID_ANY, L"of", def, wxALIGN_CENTRE), 0,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pFrame->Add(m_txtFrameCount = new wxTextCtrl(this, wxID_ANY, L"?", def,
|
|
wxTE_CENTRE | wxTE_READONLY),
|
|
1, wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pFrame->Add(new wxButton(this, ID_NEXT_FRAME, L">", def, wxBU_EXACTFIT), 0,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
pFrame->Add(m_btnPlayPause = new wxButton(this, ID_PLAY_PAUSE, L"Pause"), 1,
|
|
wxALIGN_CENTER_VERTICAL | wxALL, 1);
|
|
m_bPlayingAnimation = true;
|
|
// m_bPlayingAnimation = false;
|
|
pSidebarSizer->Add(pFrame, 0, wxEXPAND | wxALL, 0);
|
|
|
|
#define ID(layer, id) (ID_LAYER_CHECKS + (layer)*25 + (id))
|
|
wxStaticBoxSizer* pLayer0 =
|
|
new wxStaticBoxSizer(wxHORIZONTAL, this, L"Layer 0 (Patient Head)");
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 0), L"0"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 2), L"2"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 4), L"4"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 6), L"6"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 8), L"8"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 10), L"10"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 12), L"12"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 14), L"14"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 16), L"16"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 18), L"18"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 20), L"20"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer0->Add(new wxCheckBox(this, ID(0, 22), L"22"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pSidebarSizer->Add(pLayer0, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pLayer1 =
|
|
new wxStaticBoxSizer(wxHORIZONTAL, this, L"Layer 1 (Patient Clothes)");
|
|
pLayer1->Add(new wxCheckBox(this, ID(1, 0), L"0"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer1->Add(new wxCheckBox(this, ID(1, 2), L"2 (A)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer1->Add(new wxCheckBox(this, ID(1, 4), L"4 (B)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer1->Add(new wxCheckBox(this, ID(1, 6), L"6 (C)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer1->Add(new wxCheckBox(this, ID(1, 8), L"8"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer1->Add(new wxCheckBox(this, ID(1, 10), L"10"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pSidebarSizer->Add(pLayer1, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pLayer2 = new wxStaticBoxSizer(
|
|
wxHORIZONTAL, this, L"Layer 2 (Bandages / Patient Accessory)");
|
|
pLayer2->Add(new wxCheckBox(this, ID(2, 2), L"2 (Head / Alt Shoes)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer2->Add(new wxCheckBox(this, ID(2, 4), L"4 (Arm / Hat)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer2->Add(new wxCheckBox(this, ID(2, 6), L"6"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pSidebarSizer->Add(pLayer2, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pLayer3 =
|
|
new wxStaticBoxSizer(wxHORIZONTAL, this, L"Layer 3 (Bandages / Colour)");
|
|
pLayer3->Add(new wxCheckBox(this, ID(3, 0), L"0"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer3->Add(new wxCheckBox(this, ID(3, 2), L"2 (? / Yellow)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer3->Add(new wxCheckBox(this, ID(3, 4), L"4 (L Foot / Blue)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer3->Add(new wxCheckBox(this, ID(3, 6), L"6 (? / White)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer3->Add(new wxCheckBox(this, ID(3, 8), L"8 (R Arm)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer3->Add(new wxCheckBox(this, ID(3, 10), L"10 (R Foot)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pSidebarSizer->Add(pLayer3, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pLayer4 =
|
|
new wxStaticBoxSizer(wxHORIZONTAL, this, L"Layer 4 (Bandages / Repair)");
|
|
pLayer4->Add(new wxCheckBox(this, ID(4, 0), L"0"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer4->Add(new wxCheckBox(this, ID(4, 2), L"2 (Head / Repair)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer4->Add(new wxCheckBox(this, ID(4, 4), L"4 (L Root)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer4->Add(new wxCheckBox(this, ID(4, 6), L"6"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer4->Add(new wxCheckBox(this, ID(4, 8), L"8 (R Arm)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer4->Add(new wxCheckBox(this, ID(4, 10), L"10 (R Foot)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pSidebarSizer->Add(pLayer4, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pLayer5 =
|
|
new wxStaticBoxSizer(wxHORIZONTAL, this, L"Layer 5 (Staff Head)");
|
|
pLayer5->Add(new wxCheckBox(this, ID(5, 0), L"0"), 0, wxALIGN_CENTER | wxALL,
|
|
1);
|
|
pLayer5->Add(new wxCheckBox(this, ID(5, 2), L"2 (W1)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer5->Add(new wxCheckBox(this, ID(5, 4), L"4 (B1)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer5->Add(new wxCheckBox(this, ID(5, 6), L"6 (W2)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer5->Add(new wxCheckBox(this, ID(5, 8), L"8 (B2)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer5->Add(new wxCheckBox(this, ID(5, 10), L"10"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pSidebarSizer->Add(pLayer5, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pLayer10 = new wxStaticBoxSizer(
|
|
wxHORIZONTAL, this, L"Layer 10 (Wall Colour / Smoke)");
|
|
pLayer10->Add(new wxCheckBox(this, ID(10, 2), L"2 (Yellow / Smoke)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer10->Add(new wxCheckBox(this, ID(10, 4), L"4 (Blue)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer10->Add(new wxCheckBox(this, ID(10, 6), L"6 (White)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pSidebarSizer->Add(pLayer10, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pLayer11 = new wxStaticBoxSizer(
|
|
wxHORIZONTAL, this, L"Layer 11 (Wall Colour / Smoke / Screen)");
|
|
pLayer11->Add(new wxCheckBox(this, ID(11, 2), L"2 (Yellow / Smoke / On)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer11->Add(new wxCheckBox(this, ID(11, 4), L"4 (Blue)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pLayer11->Add(new wxCheckBox(this, ID(11, 6), L"6 (Green)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pSidebarSizer->Add(pLayer11, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pLayer12 =
|
|
new wxStaticBoxSizer(wxHORIZONTAL, this, L"Layer 12 (Smoke)");
|
|
pLayer12->Add(new wxCheckBox(this, ID(12, 2), L"2 (Smoke)"), 0,
|
|
wxALIGN_CENTER | wxALL, 1);
|
|
pSidebarSizer->Add(pLayer12, 0, wxEXPAND | wxALL, 0);
|
|
|
|
wxStaticBoxSizer* pMoodOverlay =
|
|
new wxStaticBoxSizer(wxVERTICAL, this, L"Overlays");
|
|
pMoodOverlay->Add(new wxCheckBox(this, ID_DRAW_MOOD, L"Draw mood overlay"), 0,
|
|
wxEXPAND | wxALL, 1);
|
|
wxBoxSizer* pMoodRow = new wxBoxSizer(wxHORIZONTAL);
|
|
pMoodRow->Add(
|
|
new wxStaticText(this, wxID_ANY, L"Marker position (click to move it):"),
|
|
0, wxEXPAND | wxRIGHT, 2);
|
|
pMoodRow->Add(
|
|
m_txtMoodPosition[0] = new wxTextCtrl(this, wxID_ANY, L"{0, 0}"), 1,
|
|
wxEXPAND | wxRIGHT, 1);
|
|
pMoodRow->Add(
|
|
m_txtMoodPosition[1] = new wxTextCtrl(this, wxID_ANY, L"{0, 0, \"px\"}"),
|
|
1, wxEXPAND);
|
|
pMoodOverlay->Add(pMoodRow, 1, wxEXPAND | wxALL, 2);
|
|
pMoodOverlay->Add(
|
|
new wxCheckBox(this, ID_DRAW_COORDINATES, L"Draw tile coodinates"), 0,
|
|
wxEXPAND | wxALL, 0);
|
|
pSidebarSizer->Add(pMoodOverlay, 0, wxEXPAND | wxALL, 0);
|
|
m_bDrawMood = false;
|
|
m_bDrawCoordinates = false;
|
|
m_iMoodDrawX = 0;
|
|
m_iMoodDrawY = 0;
|
|
|
|
for (int iLayer = 0; iLayer < 13; ++iLayer) {
|
|
wxCheckBox* pCheck = wxDynamicCast(FindWindow(ID(iLayer, 0)), wxCheckBox);
|
|
if (pCheck != NULL) {
|
|
pCheck->SetValue(true);
|
|
m_mskLayers.set(iLayer, 0);
|
|
}
|
|
}
|
|
|
|
Connect(ID(0, 0), ID(12, 24), wxEVT_COMMAND_CHECKBOX_CLICKED,
|
|
(wxObjectEventFunction)&frmMain::_onToggleMask);
|
|
#undef ID
|
|
|
|
wxStaticBoxSizer* pSearch = new wxStaticBoxSizer(wxVERTICAL, this, L"Search");
|
|
wxBoxSizer* pSearchButtons = new wxBoxSizer(wxHORIZONTAL);
|
|
pSearchButtons->Add(new wxButton(this, ID_SEARCH_LAYER_ID, L"Layer/ID"), 0,
|
|
wxALL, 1);
|
|
pSearchButtons->Add(new wxButton(this, ID_SEARCH_FRAME, L"Frame"), 0, wxALL,
|
|
1);
|
|
pSearchButtons->Add(new wxButton(this, ID_SEARCH_SOUND, L"Sound"), 0, wxALL,
|
|
1);
|
|
pSearch->Add(pSearchButtons, 0);
|
|
pSearch->Add(m_lstSearchResults = new wxListBox(this, ID_SEARCH_RESULTS), 1,
|
|
wxEXPAND | wxALL, 1);
|
|
|
|
wxStaticBoxSizer* pFrameFlags =
|
|
new wxStaticBoxSizer(wxHORIZONTAL, this, L"Frame Flags");
|
|
wxBoxSizer* pFlags1 = new wxBoxSizer(wxVERTICAL);
|
|
pFlags1->Add(m_txtFrameFlags[0] = new wxTextCtrl(this, wxID_ANY), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags1->Add(m_chkFrameFlags[0] = new wxCheckBox(this, wxID_ANY, L"2^0"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags1->Add(m_chkFrameFlags[1] = new wxCheckBox(this, wxID_ANY, L"2^1"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags1->Add(m_chkFrameFlags[2] = new wxCheckBox(this, wxID_ANY, L"2^2"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags1->Add(m_chkFrameFlags[3] = new wxCheckBox(this, wxID_ANY, L"2^3"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags1->Add(m_chkFrameFlags[4] = new wxCheckBox(this, wxID_ANY, L"2^4"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags1->Add(m_chkFrameFlags[5] = new wxCheckBox(this, wxID_ANY, L"2^5"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags1->Add(m_chkFrameFlags[6] = new wxCheckBox(this, wxID_ANY, L"2^6"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags1->Add(m_chkFrameFlags[7] = new wxCheckBox(this, wxID_ANY, L"2^7"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFrameFlags->Add(pFlags1, 1, wxEXPAND);
|
|
wxBoxSizer* pFlags2 = new wxBoxSizer(wxVERTICAL);
|
|
pFlags2->Add(m_txtFrameFlags[1] = new wxTextCtrl(this, wxID_ANY), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags2->Add(m_chkFrameFlags[8] =
|
|
new wxCheckBox(this, wxID_ANY, L"2^8 (Animation Start)"),
|
|
0, wxEXPAND | wxALL, 2);
|
|
pFlags2->Add(m_chkFrameFlags[9] = new wxCheckBox(this, wxID_ANY, L"2^9"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags2->Add(m_chkFrameFlags[10] = new wxCheckBox(this, wxID_ANY, L"2^10"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags2->Add(m_chkFrameFlags[11] = new wxCheckBox(this, wxID_ANY, L"2^11"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags2->Add(m_chkFrameFlags[12] = new wxCheckBox(this, wxID_ANY, L"2^12"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags2->Add(m_chkFrameFlags[13] = new wxCheckBox(this, wxID_ANY, L"2^13"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags2->Add(m_chkFrameFlags[14] = new wxCheckBox(this, wxID_ANY, L"2^14"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFlags2->Add(m_chkFrameFlags[15] = new wxCheckBox(this, wxID_ANY, L"2^15"), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
pFrameFlags->Add(pFlags2, 1, wxEXPAND);
|
|
|
|
pMainSizer->Add(pSidebarSizer, 0, wxEXPAND | wxALL, 2);
|
|
|
|
wxSizer* pRightHandSizer = new wxBoxSizer(wxVERTICAL);
|
|
pRightHandSizer->AddSpacer(1);
|
|
|
|
pRightHandSizer->Add(
|
|
m_panFrame = new wxPanel(this, wxID_ANY, def, wxBORDER_SIMPLE), 0,
|
|
wxEXPAND | wxALL, 2);
|
|
m_panFrame->Connect(
|
|
wxEVT_PAINT, (wxObjectEventFunction)&frmMain::_onPanelPaint, NULL, this);
|
|
m_panFrame->Connect(wxEVT_LEFT_UP,
|
|
(wxObjectEventFunction)&frmMain::_onPanelClick, NULL,
|
|
this);
|
|
m_panFrame->SetMinSize(m_panFrame->ClientToWindowSize(wxSize(402, 402)));
|
|
|
|
pRightHandSizer->AddSpacer(1);
|
|
pRightHandSizer->Add(pSearch, 1, wxEXPAND | wxALL, 0);
|
|
pRightHandSizer->Add(pFrameFlags, 0, wxEXPAND | wxALL, 0);
|
|
pMainSizer->Add(pRightHandSizer, 1, wxEXPAND | wxALL, 0);
|
|
|
|
SetBackgroundColour(m_btnPlayPause->GetBackgroundColour());
|
|
SetSizer(pMainSizer);
|
|
|
|
SetMinSize(ClientToWindowSize(pMainSizer->CalcMin()));
|
|
SetSize(GetMinSize());
|
|
|
|
load();
|
|
|
|
m_tmrAnimate.SetOwner(this, ID_TIMER_ANIMATE);
|
|
m_tmrAnimate.Start(100);
|
|
}
|
|
|
|
void frmMain::_onBrowse(wxCommandEvent& WXUNUSED(evt)) {
|
|
m_txtTHPath->SetValue(::wxDirSelector(L"Choose Theme Hospital root folder",
|
|
m_txtTHPath->GetValue(), 0,
|
|
wxDefaultPosition, this));
|
|
}
|
|
|
|
void frmMain::_onLoad(wxCommandEvent& WXUNUSED(evt)) {
|
|
::wxInitAllImageHandlers();
|
|
load();
|
|
}
|
|
|
|
void frmMain::load() {
|
|
wxBusyCursor oBusy;
|
|
wxString sPath = m_txtTHPath->GetValue();
|
|
if (sPath.IsEmpty()) return;
|
|
if (sPath.Mid(sPath.Len() - 1) != wxFileName::GetPathSeparator()) {
|
|
sPath += wxFileName::GetPathSeparator();
|
|
}
|
|
if (!wxFileName::DirExists(sPath)) {
|
|
::wxMessageBox(L"Theme Hospital path non-existant", L"Load Animations",
|
|
wxOK | wxICON_ERROR, this);
|
|
return;
|
|
}
|
|
sPath = _getCaseSensitivePath(L"DATA", sPath);
|
|
sPath += wxFileName::GetPathSeparator();
|
|
wxString aPath = _getCaseSensitivePath(L"VSPR-0", sPath);
|
|
aPath += wxFileName::GetPathSeparator();
|
|
m_oAnims.setSpritePath(aPath);
|
|
|
|
if (!m_oAnims.loadAnimationFile(
|
|
_getCaseSensitivePath(L"VSTART-1.ANI", sPath)) ||
|
|
!m_oAnims.loadFrameFile(_getCaseSensitivePath(L"VFRA-1.ANI", sPath)) ||
|
|
!m_oAnims.loadListFile(_getCaseSensitivePath(L"VLIST-1.ANI", sPath)) ||
|
|
!m_oAnims.loadElementFile(_getCaseSensitivePath(L"VELE-1.ANI", sPath)) ||
|
|
!m_oAnims.loadTableFile(_getCaseSensitivePath(L"VSPR-0.TAB", sPath)) ||
|
|
!m_oAnims.loadSpriteFile(_getCaseSensitivePath(L"VSPR-0.DAT", sPath)) ||
|
|
!m_oAnims.loadPaletteFile(
|
|
_getCaseSensitivePath(L"MPALETTE.DAT", sPath)) ||
|
|
!m_oAnims.loadGhostFile(
|
|
_getCaseSensitivePath(L"../QDATA/GHOST1.DAT", sPath), 1) ||
|
|
!m_oAnims.loadGhostFile(
|
|
_getCaseSensitivePath(L"../QDATA/GHOST2.DAT", sPath), 2) ||
|
|
!m_oAnims.loadGhostFile(
|
|
_getCaseSensitivePath(L"../QDATA/GHOST66.DAT", sPath), 3)) {
|
|
::wxMessageBox(L"Cannot load one or more data files", L"Load Animations",
|
|
wxOK | wxICON_ERROR, this);
|
|
}
|
|
m_oAnims.markDuplicates();
|
|
|
|
m_txtAnimCount->SetValue(
|
|
wxString::Format(L"%u", (int)m_oAnims.getAnimationCount()));
|
|
|
|
m_imgBackground.Create(400, 400);
|
|
{
|
|
unsigned char* pData = m_imgBackground.GetData();
|
|
unsigned char cPrimary = 0xFF;
|
|
unsigned char cSecondary = 0xE0;
|
|
for (int y = 0; y < 400; ++y) {
|
|
for (int x = 0; x < 400; x += 8) {
|
|
memset(pData, cPrimary, 4 * 3);
|
|
pData += 4 * 3;
|
|
memset(pData, cSecondary, 4 * 3);
|
|
pData += 4 * 3;
|
|
}
|
|
if (y % 4 == 3) {
|
|
cPrimary ^= cSecondary;
|
|
cSecondary ^= cPrimary;
|
|
cPrimary ^= cSecondary;
|
|
}
|
|
}
|
|
wxBitmap bmpBackdrop(backdrop_xpm);
|
|
wxBitmap bmpBackground(m_imgBackground);
|
|
{
|
|
wxMemoryDC dcBlit;
|
|
dcBlit.SelectObject(bmpBackground);
|
|
dcBlit.DrawBitmap(bmpBackdrop, 78, 170, true);
|
|
}
|
|
m_imgBackground = bmpBackground.ConvertToImage();
|
|
}
|
|
|
|
_onAnimChange(0);
|
|
}
|
|
|
|
void frmMain::_onToggleMask(wxCommandEvent& evt) {
|
|
int iID = evt.GetId() - ID_LAYER_CHECKS;
|
|
int iLayer = iID / 25;
|
|
iID %= 25;
|
|
|
|
if (evt.IsChecked())
|
|
m_mskLayers.set(iLayer, iID);
|
|
else
|
|
m_mskLayers.clear(iLayer, iID);
|
|
|
|
m_panFrame->Refresh(false);
|
|
}
|
|
|
|
frmMain::~frmMain() {}
|
|
|
|
void frmMain::_onFirstAnim(wxCommandEvent& evt) {
|
|
if (m_iCurrentAnim > 0) _onAnimChange(0);
|
|
}
|
|
|
|
void frmMain::_onPrevAnim(wxCommandEvent& evt) {
|
|
size_t iAnim = m_iCurrentAnim;
|
|
while (iAnim > 0) {
|
|
--iAnim;
|
|
if (!m_oAnims.isAnimationDuplicate(iAnim)) {
|
|
_onAnimChange(iAnim);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void frmMain::_onNextAnim(wxCommandEvent& evt) {
|
|
size_t iAnim = m_iCurrentAnim + 1;
|
|
while (iAnim < m_oAnims.getAnimationCount()) {
|
|
if (!m_oAnims.isAnimationDuplicate(iAnim)) {
|
|
_onAnimChange(iAnim);
|
|
break;
|
|
}
|
|
iAnim++;
|
|
}
|
|
}
|
|
|
|
void frmMain::_onLastAnim(wxCommandEvent& evt) {
|
|
if (m_iCurrentAnim < m_oAnims.getAnimationCount() - 1)
|
|
_onAnimChange(m_oAnims.getAnimationCount() - 1);
|
|
}
|
|
|
|
void frmMain::_onAnimChar(wxCommandEvent& evt) {
|
|
long iAnim;
|
|
if (evt.GetString().ToLong(&iAnim)) {
|
|
if (iAnim >= 0 && iAnim < (long)m_oAnims.getAnimationCount()) {
|
|
_onAnimChange((size_t)iAnim);
|
|
}
|
|
}
|
|
}
|
|
|
|
void frmMain::_onGhostFileChange(wxCommandEvent& evt) {
|
|
m_iGhostFile = evt.GetId() - ID_GHOST_0;
|
|
m_oAnims.setGhost(m_iGhostFile, m_iGhostIndex);
|
|
m_panFrame->Refresh(false);
|
|
}
|
|
|
|
void frmMain::_onGhostIndexChange(wxSpinEvent& evt) {
|
|
m_iGhostIndex = evt.GetPosition();
|
|
m_oAnims.setGhost(m_iGhostFile, m_iGhostIndex);
|
|
m_panFrame->Refresh(false);
|
|
}
|
|
|
|
void frmMain::_onAnimChange(size_t iIndex) {
|
|
m_iCurrentAnim = iIndex;
|
|
m_txtAnimIndex->ChangeValue(wxString::Format(L"%u", (int)iIndex));
|
|
m_iCurrentFrame = 0;
|
|
|
|
THLayerMask oMask;
|
|
m_oAnims.getAnimationMask(iIndex, oMask);
|
|
for (int iLayer = 0; iLayer < 13; ++iLayer) {
|
|
for (int iId = 0; iId < 32; ++iId) {
|
|
wxCheckBox* pCheck = wxDynamicCast(
|
|
FindWindow(ID_LAYER_CHECKS + iLayer * 25 + iId), wxCheckBox);
|
|
if (pCheck) {
|
|
pCheck->Enable(oMask.isSet(iLayer, iId));
|
|
}
|
|
}
|
|
}
|
|
|
|
m_panFrame->Refresh(false);
|
|
m_txtFrameIndex->SetValue(wxString::Format(L"0"));
|
|
m_txtFrameCount->SetValue(
|
|
wxString::Format(L"%u", (int)m_oAnims.getFrameCount(iIndex)));
|
|
}
|
|
|
|
void frmMain::_onPlayPause(wxCommandEvent& evt) {
|
|
m_bPlayingAnimation = !m_bPlayingAnimation;
|
|
if (m_bPlayingAnimation)
|
|
m_btnPlayPause->SetLabel(L"Pause");
|
|
else
|
|
m_btnPlayPause->SetLabel(L"Play");
|
|
}
|
|
|
|
void frmMain::_onPrevFrame(wxCommandEvent& evt) {
|
|
if (m_oAnims.getAnimationCount() == 0) return;
|
|
|
|
if (m_iCurrentFrame == 0)
|
|
m_iCurrentFrame = m_oAnims.getFrameCount(m_iCurrentAnim) - 1;
|
|
else
|
|
m_iCurrentFrame =
|
|
(m_iCurrentFrame - 1) % m_oAnims.getFrameCount(m_iCurrentAnim);
|
|
m_txtFrameIndex->SetValue(wxString::Format(L"%u", m_iCurrentFrame));
|
|
m_panFrame->Refresh(false);
|
|
}
|
|
|
|
void frmMain::_onNextFrame(wxCommandEvent& evt) {
|
|
if (m_oAnims.getAnimationCount() == 0) return;
|
|
|
|
m_iCurrentFrame =
|
|
(m_iCurrentFrame + 1) % m_oAnims.getFrameCount(m_iCurrentAnim);
|
|
m_txtFrameIndex->SetValue(wxString::Format(L"%u", m_iCurrentFrame));
|
|
m_panFrame->Refresh(false);
|
|
}
|
|
|
|
void frmMain::_onTimer(wxTimerEvent& evt) {
|
|
if (m_bPlayingAnimation) {
|
|
if (m_oAnims.getAnimationCount() == 0) return;
|
|
|
|
m_iCurrentFrame =
|
|
(m_iCurrentFrame + 1) % m_oAnims.getFrameCount(m_iCurrentAnim);
|
|
m_txtFrameIndex->SetValue(wxString::Format(L"%u", (int)m_iCurrentFrame));
|
|
m_panFrame->Refresh(false);
|
|
}
|
|
}
|
|
|
|
void frmMain::_onToggleDrawMood(wxCommandEvent& evt) {
|
|
m_bDrawMood = evt.IsChecked();
|
|
m_panFrame->Refresh(false);
|
|
}
|
|
|
|
void frmMain::_onToggleDrawCoordinates(wxCommandEvent& evt) {
|
|
m_bDrawCoordinates = evt.IsChecked();
|
|
m_panFrame->Refresh(false);
|
|
}
|
|
|
|
void frmMain::_onPanelPaint(wxPaintEvent& evt) {
|
|
wxPaintDC DC(m_panFrame);
|
|
|
|
wxImage imgCanvas(400, 400, false);
|
|
if (m_imgBackground.IsOk()) {
|
|
memcpy(imgCanvas.GetData(), m_imgBackground.GetData(), 400 * 400 * 3);
|
|
} else {
|
|
memset(imgCanvas.GetData(), 0xFF, 400 * 400 * 3);
|
|
}
|
|
if (!imgCanvas.HasAlpha()) {
|
|
imgCanvas.InitAlpha();
|
|
}
|
|
for (int iX = 0; iX < 400; ++iX) {
|
|
for (int iY = 0; iY < 400; ++iY) {
|
|
// set completely opaque
|
|
imgCanvas.SetAlpha(iX, iY, (unsigned char)255);
|
|
}
|
|
}
|
|
wxSize oSize;
|
|
m_oAnims.drawFrame(imgCanvas, m_iCurrentAnim, m_iCurrentFrame, &m_mskLayers,
|
|
oSize);
|
|
if (m_bDrawMood) {
|
|
m_oAnims.drawFrame(imgCanvas, 4048, 0, &m_mskLayers, oSize,
|
|
m_iMoodDrawX - 1, m_iMoodDrawY - 80);
|
|
}
|
|
th_frame_t* pFrame = m_oAnims.getFrameStruct(m_iCurrentAnim, m_iCurrentFrame);
|
|
uint16_t iFlags = 0;
|
|
if (pFrame) {
|
|
iFlags = pFrame->flags;
|
|
}
|
|
int iFlags1 = (int)(iFlags & 0xFF);
|
|
int iFlags2 = (int)(iFlags >> 8);
|
|
m_txtFrameFlags[0]->SetValue(
|
|
wxString::Format(L"0x%02x (%03i)", iFlags1, iFlags1));
|
|
m_txtFrameFlags[1]->SetValue(
|
|
wxString::Format(L"0x%02x00 (256 * %03i)", iFlags2, iFlags2));
|
|
for (int i = 0; i < 16; ++i)
|
|
m_chkFrameFlags[i]->SetValue((iFlags & (1 << i)) != 0);
|
|
|
|
wxBitmap bmpCanvas(imgCanvas);
|
|
|
|
DC.DrawBitmap(bmpCanvas, 1, 1, false);
|
|
|
|
// Draw relative tile coordinates
|
|
if (m_bDrawCoordinates) {
|
|
for (int i = -1; i <= 1; ++i) {
|
|
for (int j = -1; j <= 1; ++j) {
|
|
_drawCoordinates(DC, i, j);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void frmMain::_onPanelClick(wxMouseEvent& evt) {
|
|
m_iMoodDrawX = evt.GetX() - 143;
|
|
m_iMoodDrawY = evt.GetY() - 203;
|
|
{
|
|
double fX = (double)m_iMoodDrawX;
|
|
double fY = (double)m_iMoodDrawY;
|
|
fY = fY / 32.0;
|
|
fX = fX / 64.0;
|
|
fY -= fX;
|
|
fX *= 2.0;
|
|
fX += fY;
|
|
m_txtMoodPosition[0]->SetValue(wxString::Format(L"{%.2f, %.2f}", fX, fY));
|
|
}
|
|
m_txtMoodPosition[1]->SetValue(
|
|
wxString::Format(L"{%i, %i, \"px\"}", m_iMoodDrawX, m_iMoodDrawY));
|
|
if (m_bDrawMood) m_panFrame->Refresh(false);
|
|
}
|
|
|
|
void frmMain::_onSearchLayerId(wxCommandEvent& evt) {
|
|
int iLayer = ::wxGetNumberFromUser(
|
|
L"Enter the layer number to search in (0 - 12)", L"Layer:",
|
|
L"Search for Layer / ID Combo", 0, 0, 13, this);
|
|
if (iLayer == -1) return;
|
|
int iID = ::wxGetNumberFromUser(L"Enter the ID number to search for (0 - 24)",
|
|
L"ID:", L"Search for Layer / ID Combo", 0, 0,
|
|
24, this);
|
|
if (iID == -1) return;
|
|
|
|
m_lstSearchResults->Clear();
|
|
wxBusyCursor oBusy;
|
|
for (size_t i = 0; i < m_oAnims.getAnimationCount(); ++i) {
|
|
if (m_oAnims.isAnimationDuplicate(i)) continue;
|
|
|
|
THLayerMask mskAnim;
|
|
m_oAnims.getAnimationMask(i, mskAnim);
|
|
if (mskAnim.isSet(iLayer, iID)) {
|
|
m_lstSearchResults->Append(wxString::Format(L"%i", (int)i));
|
|
}
|
|
}
|
|
}
|
|
|
|
void frmMain::_onSearchFrame(wxCommandEvent& evt) {
|
|
int iFrame =
|
|
::wxGetNumberFromUser(L"Enter the frame number to search for.", L"Frame:",
|
|
L"Search for frame", 0, 0, 20000, this);
|
|
if (iFrame == -1) return;
|
|
|
|
m_lstSearchResults->Clear();
|
|
wxBusyCursor oBusy;
|
|
for (size_t i = 0; i < m_oAnims.getAnimationCount(); ++i) {
|
|
if (m_oAnims.isAnimationDuplicate(i)) continue;
|
|
if (m_oAnims.doesAnimationIncludeFrame(i, iFrame)) {
|
|
m_lstSearchResults->Append(wxString::Format(L"%i", (int)i));
|
|
}
|
|
}
|
|
}
|
|
|
|
void frmMain::_onSearchSoundIndex(wxCommandEvent& evt) {
|
|
int iFrame = ::wxGetNumberFromUser(L"Enter the sound index to search for.",
|
|
L"Sound index:", L"Search for sound", 0, 0,
|
|
256, this);
|
|
if (iFrame == -1) return;
|
|
|
|
m_lstSearchResults->Clear();
|
|
wxBusyCursor oBusy;
|
|
for (size_t i = 0; i < m_oAnims.getAnimationCount(); ++i) {
|
|
if (m_oAnims.isAnimationDuplicate(i)) continue;
|
|
size_t iCount = m_oAnims.getFrameCount(i);
|
|
for (size_t j = 0; j < iCount; ++j) {
|
|
if ((m_oAnims.getFrameStruct(i, j)->flags & 0xFF) == iFrame) {
|
|
m_lstSearchResults->Append(wxString::Format(L"%i", (int)i));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void frmMain::_onGotoSearchResult(wxCommandEvent& evt) {
|
|
long iAnim;
|
|
evt.GetString().ToLong(&iAnim);
|
|
_onAnimChange(iAnim);
|
|
}
|
|
|
|
void frmMain::_drawCoordinates(wxPaintDC& DC, int i, int j) {
|
|
int x = 122; // tile (0, 0) text start x-coordinate
|
|
int y = 226; // tile (0, 0) text start y-coordinate
|
|
wxString s;
|
|
s.Printf(_T("(%2d,%2d)"), i, j);
|
|
DC.DrawText(s, 32 * (i - j) + x, 16 * (i + j - 2) + y);
|
|
}
|
|
|
|
wxString frmMain::_getCaseSensitivePath(const wxString& sInsensitivePathPart,
|
|
const wxString& sPath) {
|
|
bool found;
|
|
bool cont;
|
|
|
|
if (!wxFileName::IsCaseSensitive()) {
|
|
return sPath + sInsensitivePathPart;
|
|
}
|
|
|
|
wxString retStr(sPath);
|
|
|
|
wxStringTokenizer pathTokenizer(sInsensitivePathPart,
|
|
wxFileName::GetPathSeparator());
|
|
while (pathTokenizer.HasMoreTokens()) {
|
|
wxDir dir(retStr);
|
|
if (!dir.IsOpened()) {
|
|
break;
|
|
}
|
|
|
|
wxString pathPart = pathTokenizer.GetNextToken();
|
|
|
|
wxString realName;
|
|
cont = dir.GetFirst(&realName, wxEmptyString,
|
|
wxDIR_DIRS | wxDIR_FILES | wxDIR_HIDDEN | wxDIR_DOTDOT);
|
|
found = false;
|
|
while (cont) {
|
|
if (realName.Upper() == pathPart.Upper()) {
|
|
if (retStr.Last() != wxFileName::GetPathSeparator()) {
|
|
retStr += wxFileName::GetPathSeparator();
|
|
}
|
|
retStr += realName;
|
|
found = true;
|
|
break;
|
|
}
|
|
cont = dir.GetNext(&realName);
|
|
}
|
|
|
|
if (!found) {
|
|
retStr += wxFileName::GetPathSeparator();
|
|
retStr += pathPart;
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (pathTokenizer.HasMoreTokens()) {
|
|
wxString pathPart = pathTokenizer.GetNextToken();
|
|
if (retStr.Last() != wxFileName::GetPathSeparator()) {
|
|
retStr += wxFileName::GetPathSeparator();
|
|
}
|
|
retStr += pathPart;
|
|
}
|
|
|
|
return retStr;
|
|
}
|