mirror of
https://github.com/AdAstra-LD/DS-Pokemon-Rom-Editor.git
synced 2026-05-12 06:54:33 -05:00
993 lines
41 KiB
C#
993 lines
41 KiB
C#
using DSPRE.ROMFiles;
|
|
using MKDS_Course_Editor.Export3DTools;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using static DSPRE.RomInfo;
|
|
using static Tao.Platform.Windows.Winmm;
|
|
|
|
namespace DSPRE.Editors
|
|
{
|
|
public partial class MatrixEditor : UserControl
|
|
{
|
|
MainProgram _parent;
|
|
public bool matrixEditorIsReady { get; set; } = false;
|
|
|
|
public MatrixEditor()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
#region Matrix Editor
|
|
|
|
public GameMatrix currentMatrix;
|
|
|
|
#region Subroutines
|
|
private void ClearMatrixTables()
|
|
{
|
|
headersGridView.Rows.Clear();
|
|
headersGridView.Columns.Clear();
|
|
heightsGridView.Rows.Clear();
|
|
heightsGridView.Columns.Clear();
|
|
mapFilesGridView.Rows.Clear();
|
|
mapFilesGridView.Columns.Clear();
|
|
matrixTabControl.TabPages.Remove(headersTabPage);
|
|
matrixTabControl.TabPages.Remove(heightsTabPage);
|
|
}
|
|
private (Color background, Color foreground) FormatMapCell(uint cellValue)
|
|
{
|
|
foreach (KeyValuePair<List<uint>, (Color background, Color foreground)> entry in _parent.romInfo.MapCellsColorDictionary)
|
|
{
|
|
if (entry.Key.Contains(cellValue))
|
|
return entry.Value;
|
|
}
|
|
return (Color.White, Color.Black);
|
|
}
|
|
private void GenerateMatrixTables()
|
|
{
|
|
/* Generate table columns */
|
|
if (currentMatrix is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < currentMatrix.width; i++)
|
|
{
|
|
headersGridView.Columns.Add("Column" + i, i.ToString("D"));
|
|
headersGridView.Columns[i].Width = 32; // Set column size
|
|
headersGridView.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
|
|
headersGridView.Columns[i].Frozen = false;
|
|
|
|
heightsGridView.Columns.Add("Column" + i, i.ToString("D"));
|
|
heightsGridView.Columns[i].Width = 21; // Set column size
|
|
heightsGridView.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
|
|
heightsGridView.Columns[i].Frozen = false;
|
|
|
|
mapFilesGridView.Columns.Add("Column" + i, i.ToString("D"));
|
|
mapFilesGridView.Columns[i].Width = 32; // Set column size
|
|
mapFilesGridView.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
|
|
mapFilesGridView.Columns[i].Frozen = false;
|
|
}
|
|
|
|
/* Generate table rows */
|
|
for (int i = 0; i < currentMatrix.height; i++)
|
|
{
|
|
mapFilesGridView.Rows.Add();
|
|
mapFilesGridView.Rows[i].HeaderCell.Value = i.ToString();
|
|
|
|
headersGridView.Rows.Add();
|
|
headersGridView.Rows[i].HeaderCell.Value = i.ToString();
|
|
|
|
heightsGridView.Rows.Add();
|
|
heightsGridView.Rows[i].HeaderCell.Value = i.ToString();
|
|
}
|
|
|
|
/* Fill tables */
|
|
for (int i = 0; i < currentMatrix.height; i++)
|
|
{
|
|
for (int j = 0; j < currentMatrix.width; j++)
|
|
{
|
|
headersGridView.Rows[i].Cells[j].Value = currentMatrix.headers[i, j];
|
|
heightsGridView.Rows[i].Cells[j].Value = currentMatrix.altitudes[i, j];
|
|
mapFilesGridView.Rows[i].Cells[j].Value = currentMatrix.maps[i, j];
|
|
}
|
|
}
|
|
|
|
if (currentMatrix.hasHeadersSection)
|
|
{
|
|
matrixTabControl.TabPages.Add(headersTabPage);
|
|
}
|
|
|
|
if (currentMatrix.hasHeightsSection)
|
|
{
|
|
matrixTabControl.TabPages.Add(heightsTabPage);
|
|
}
|
|
}
|
|
#endregion
|
|
public void SetupMatrixEditor(MainProgram parent, bool force=false)
|
|
{
|
|
if (matrixEditorIsReady && !force) { return; }
|
|
matrixEditorIsReady = true;
|
|
this._parent = parent;
|
|
|
|
Helpers.statusLabelMessage("Setting up Matrix Editor...");
|
|
Update();
|
|
|
|
DSUtils.TryUnpackNarcs(new List<DirNames> { DirNames.matrices });
|
|
|
|
Helpers.DisableHandlers();
|
|
|
|
/* Add matrix entries to ComboBox */
|
|
selectMatrixComboBox.Items.Clear();
|
|
selectMatrixComboBox.Items.Add("Matrix 0 - Main");
|
|
for (int i = 1; i < _parent.romInfo.GetMatrixCount(); i++)
|
|
{
|
|
selectMatrixComboBox.Items.Add(new GameMatrix(i));
|
|
}
|
|
|
|
if (!ReadColorTable(SettingsManager.Settings.lastColorTablePath, silent: true))
|
|
{
|
|
_parent.romInfo.ResetMapCellsColorDictionary();
|
|
}
|
|
RomInfo.SetupSpawnSettings();
|
|
|
|
Helpers.EnableHandlers();
|
|
selectMatrixComboBox.SelectedIndex = 0;
|
|
Helpers.statusLabelMessage();
|
|
}
|
|
private void addHeaderSectionButton_Click(object sender, EventArgs e)
|
|
{
|
|
if (!currentMatrix.hasHeadersSection)
|
|
{
|
|
currentMatrix.hasHeadersSection = true;
|
|
matrixTabControl.TabPages.Add(headersTabPage);
|
|
}
|
|
}
|
|
private void addHeightsButton_Click(object sender, EventArgs e)
|
|
{
|
|
if (!currentMatrix.hasHeightsSection)
|
|
{
|
|
currentMatrix.hasHeightsSection = true;
|
|
matrixTabControl.TabPages.Add(heightsTabPage);
|
|
}
|
|
}
|
|
private void addMatrixButton_Click(object sender, EventArgs e)
|
|
{
|
|
GameMatrix blankMatrix = new GameMatrix();
|
|
|
|
/* Add new matrix file to matrix folder */
|
|
blankMatrix.SaveToFile(RomInfo.gameDirs[DirNames.matrices].unpackedDir + "\\" + _parent.romInfo.GetMatrixCount().ToString("D4"), false);
|
|
|
|
/* Update ComboBox*/
|
|
selectMatrixComboBox.Items.Add(selectMatrixComboBox.Items.Count.ToString() + blankMatrix);
|
|
selectMatrixComboBox.SelectedIndex = selectMatrixComboBox.Items.Count - 1;
|
|
|
|
if (EditorPanels.eventEditor.eventEditorIsReady)
|
|
{
|
|
EditorPanels.eventEditor.eventMatrixUpDown.Maximum++;
|
|
}
|
|
}
|
|
private void exportMatrixButton_Click(object sender, EventArgs e)
|
|
{
|
|
currentMatrix.SaveToFileExplorePath("Matrix " + selectMatrixComboBox.SelectedIndex);
|
|
}
|
|
private void saveMatrixButton_Click(object sender, EventArgs e)
|
|
{
|
|
currentMatrix.SaveToFileDefaultDir(selectMatrixComboBox.SelectedIndex);
|
|
GameMatrix saved = new GameMatrix(selectMatrixComboBox.SelectedIndex);
|
|
selectMatrixComboBox.Items[selectMatrixComboBox.SelectedIndex] = saved.ToString();
|
|
EditorPanels.eventEditor.eventMatrix = saved;
|
|
}
|
|
private void headersGridView_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
DisplaySelection(headersGridView.SelectedCells);
|
|
}
|
|
|
|
private void heightsGridView_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
DisplaySelection(heightsGridView.SelectedCells);
|
|
}
|
|
|
|
private void mapFilesGridView_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
DisplaySelection(mapFilesGridView.SelectedCells);
|
|
}
|
|
private void DisplaySelection(DataGridViewSelectedCellCollection selectedCells)
|
|
{
|
|
if (selectedCells.Count > 0)
|
|
{
|
|
Helpers.statusLabelMessage("Selection: " + selectedCells[0].ColumnIndex + ", " + selectedCells[0].RowIndex);
|
|
}
|
|
}
|
|
private void headersGridView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
|
|
{
|
|
if (EditorPanels.headerEditor.headerListBox.Items.Count < EditorPanels.headerEditor.internalNames.Count)
|
|
{
|
|
HeaderSearch.ResetResults(EditorPanels.headerEditor.headerListBox, EditorPanels.headerEditor.headerListBoxNames, prependNumbers: false);
|
|
}
|
|
|
|
if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
|
|
{
|
|
int headerNumber = Convert.ToInt32(headersGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value);
|
|
EditorPanels.headerEditor.headerListBox.SelectedIndex = headerNumber;
|
|
EditorPanels.mainTabControl.SelectedTab = EditorPanels.headerEditorTabPage;
|
|
}
|
|
}
|
|
private void headersGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
if (e.RowIndex > -1 && e.ColumnIndex > -1)
|
|
{
|
|
/* If input is junk, use 0000 as placeholder value */
|
|
ushort cellValue;
|
|
try
|
|
{
|
|
if (!ushort.TryParse(headersGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString(), out cellValue))
|
|
{
|
|
throw new NullReferenceException();
|
|
}
|
|
}
|
|
catch (NullReferenceException)
|
|
{
|
|
cellValue = 0;
|
|
}
|
|
/* Change value in matrix object */
|
|
currentMatrix.headers[e.RowIndex, e.ColumnIndex] = cellValue;
|
|
}
|
|
}
|
|
private void headersGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
|
{
|
|
if (e.Value is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Helpers.DisableHandlers();
|
|
|
|
/* Format table cells corresponding to border maps or void */
|
|
if (!ushort.TryParse(mapFilesGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString(), out ushort colorValue))
|
|
{
|
|
colorValue = GameMatrix.EMPTY;
|
|
}
|
|
|
|
(Color back, Color fore) = FormatMapCell(colorValue);
|
|
e.CellStyle.BackColor = back;
|
|
e.CellStyle.ForeColor = fore;
|
|
|
|
/* If invalid input is entered, show 00 */
|
|
if (!ushort.TryParse(headersGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString(), out _))
|
|
{
|
|
e.Value = 0;
|
|
}
|
|
|
|
Helpers.EnableHandlers();
|
|
|
|
}
|
|
private void heightsGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
if (e.RowIndex > -1 && e.ColumnIndex > -1)
|
|
{
|
|
/* If input is junk, use 00 as placeholder value */
|
|
byte cellValue = 0;
|
|
try
|
|
{
|
|
cellValue = byte.Parse(heightsGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
|
|
}
|
|
catch { }
|
|
|
|
/* Change value in matrix object */
|
|
currentMatrix.altitudes[e.RowIndex, e.ColumnIndex] = cellValue;
|
|
}
|
|
}
|
|
private void widthUpDown_ValueChanged(object sender, EventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
Helpers.DisableHandlers();
|
|
|
|
/* Add or remove rows in DataGridView control */
|
|
int delta = (int)widthUpDown.Value - currentMatrix.width;
|
|
for (int i = 0; i < Math.Abs(delta); i++)
|
|
{
|
|
if (delta < 0)
|
|
{
|
|
headersGridView.Columns.RemoveAt(currentMatrix.width - 1 - i);
|
|
heightsGridView.Columns.RemoveAt(currentMatrix.width - 1 - i);
|
|
mapFilesGridView.Columns.RemoveAt(currentMatrix.width - 1 - i);
|
|
}
|
|
else
|
|
{
|
|
/* Add columns */
|
|
int index = currentMatrix.width + i;
|
|
headersGridView.Columns.Add(" ", (index).ToString());
|
|
heightsGridView.Columns.Add(" ", (index).ToString());
|
|
mapFilesGridView.Columns.Add(" ", (index).ToString());
|
|
|
|
/* Adjust column width */
|
|
headersGridView.Columns[index].Width = 34;
|
|
heightsGridView.Columns[index].Width = 22;
|
|
mapFilesGridView.Columns[index].Width = 34;
|
|
|
|
/* Fill new rows */
|
|
for (int j = 0; j < currentMatrix.height; j++)
|
|
{
|
|
headersGridView.Rows[j].Cells[index].Value = 0;
|
|
heightsGridView.Rows[j].Cells[index].Value = 0;
|
|
mapFilesGridView.Rows[j].Cells[index].Value = GameMatrix.EMPTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Modify matrix object */
|
|
currentMatrix.ResizeMatrix((int)heightUpDown.Value, (int)widthUpDown.Value);
|
|
Helpers.EnableHandlers();
|
|
}
|
|
private void heightUpDown_ValueChanged(object sender, EventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
Helpers.DisableHandlers();
|
|
|
|
/* Add or remove rows in DataGridView control */
|
|
int delta = (int)heightUpDown.Value - currentMatrix.height;
|
|
for (int i = 0; i < Math.Abs(delta); i++)
|
|
{
|
|
if (delta < 0)
|
|
{ // Remove rows
|
|
headersGridView.Rows.RemoveAt(currentMatrix.height - 1 - i);
|
|
heightsGridView.Rows.RemoveAt(currentMatrix.height - 1 - i);
|
|
mapFilesGridView.Rows.RemoveAt(currentMatrix.height - 1 - i);
|
|
}
|
|
else
|
|
{
|
|
/* Add row in DataGridView */
|
|
headersGridView.Rows.Add();
|
|
heightsGridView.Rows.Add();
|
|
mapFilesGridView.Rows.Add();
|
|
|
|
int index = currentMatrix.height + i;
|
|
headersGridView.Rows[index].HeaderCell.Value = (index).ToString();
|
|
heightsGridView.Rows[index].HeaderCell.Value = (index).ToString();
|
|
mapFilesGridView.Rows[index].HeaderCell.Value = (index).ToString();
|
|
|
|
/* Fill new rows */
|
|
for (int j = 0; j < currentMatrix.width; j++)
|
|
{
|
|
headersGridView.Rows[index].Cells[j].Value = 0;
|
|
heightsGridView.Rows[index].Cells[j].Value = 0;
|
|
mapFilesGridView.Rows[index].Cells[j].Value = GameMatrix.EMPTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Modify matrix object */
|
|
currentMatrix.ResizeMatrix((int)heightUpDown.Value, (int)widthUpDown.Value);
|
|
Helpers.EnableHandlers();
|
|
}
|
|
private void heightsGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
|
{
|
|
if (e.Value is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Helpers.DisableHandlers();
|
|
|
|
/* Format table cells corresponding to border maps or void */
|
|
ushort colorValue = 0;
|
|
try
|
|
{
|
|
colorValue = ushort.Parse(mapFilesGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
|
|
}
|
|
catch { }
|
|
|
|
(Color back, Color fore) = FormatMapCell(colorValue);
|
|
e.CellStyle.BackColor = back;
|
|
e.CellStyle.ForeColor = fore;
|
|
|
|
/* If invalid input is entered, show 00 */
|
|
byte cellValue = 0;
|
|
try
|
|
{
|
|
cellValue = byte.Parse(heightsGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
|
|
}
|
|
catch { }
|
|
|
|
e.Value = cellValue;
|
|
Helpers.EnableHandlers();
|
|
}
|
|
private void importMatrixButton_Click(object sender, EventArgs e)
|
|
{
|
|
/* Prompt user to select .mtx file */
|
|
if (selectMatrixComboBox.SelectedIndex == 0)
|
|
{
|
|
Helpers.statusLabelMessage("Awaiting user response...");
|
|
DialogResult d = MessageBox.Show("Replacing a matrix - especially Matrix 0 - with a new file is risky.\n" +
|
|
"Do not do it unless you are absolutely sure.\nProceed?", "Risky operation", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
|
|
|
if (d == DialogResult.No)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
OpenFileDialog importMatrix = new OpenFileDialog
|
|
{
|
|
Filter = GameMatrix.DefaultFilter
|
|
};
|
|
if (importMatrix.ShowDialog(this) != DialogResult.OK)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Update matrix object in memory */
|
|
currentMatrix = new GameMatrix(new FileStream(importMatrix.FileName, FileMode.Open));
|
|
|
|
/* Refresh DataGridView tables */
|
|
ClearMatrixTables();
|
|
GenerateMatrixTables();
|
|
|
|
/* Setup matrix editor controls */
|
|
Helpers.DisableHandlers();
|
|
matrixNameTextBox.Text = currentMatrix.name;
|
|
widthUpDown.Value = currentMatrix.width;
|
|
heightUpDown.Value = currentMatrix.height;
|
|
Helpers.EnableHandlers();
|
|
|
|
/* Display success message */
|
|
MessageBox.Show("Matrix imported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
Helpers.statusLabelMessage();
|
|
}
|
|
|
|
private void mapFilesGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
|
|
{
|
|
/* If input is junk, use '\' (FF FF) as placeholder value */
|
|
ushort cellValue = GameMatrix.EMPTY;
|
|
try
|
|
{
|
|
cellValue = ushort.Parse(mapFilesGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
|
|
}
|
|
catch { }
|
|
|
|
/* Change value in matrix object */
|
|
currentMatrix.maps[e.RowIndex, e.ColumnIndex] = cellValue;
|
|
}
|
|
}
|
|
private void mapFilesGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
|
{
|
|
Helpers.DisableHandlers();
|
|
|
|
/* Format table cells corresponding to border maps or void */
|
|
ushort colorValue = GameMatrix.EMPTY;
|
|
try
|
|
{
|
|
if (mapFilesGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value == null) return;
|
|
colorValue = ushort.Parse(mapFilesGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
|
|
}
|
|
catch { }
|
|
|
|
(Color backColor, Color foreColor) cellColors = FormatMapCell(colorValue);
|
|
e.CellStyle.BackColor = cellColors.backColor;
|
|
e.CellStyle.ForeColor = cellColors.foreColor;
|
|
|
|
if (colorValue == GameMatrix.EMPTY)
|
|
e.Value = '-';
|
|
|
|
Helpers.EnableHandlers();
|
|
}
|
|
private void matrixNameTextBox_TextChanged(object sender, EventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
currentMatrix.name = matrixNameTextBox.Text;
|
|
}
|
|
private void removeHeadersButton_Click(object sender, EventArgs e)
|
|
{
|
|
matrixTabControl.TabPages.Remove(headersTabPage);
|
|
currentMatrix.hasHeadersSection = false;
|
|
}
|
|
private void removeHeightsButton_Click(object sender, EventArgs e)
|
|
{
|
|
matrixTabControl.TabPages.Remove(heightsTabPage);
|
|
currentMatrix.hasHeightsSection = false;
|
|
}
|
|
private void removeMatrixButton_Click(object sender, EventArgs e)
|
|
{
|
|
if (selectMatrixComboBox.Items.Count > 1)
|
|
{
|
|
DialogResult d = MessageBox.Show("Are you sure you want to delete the last matrix?", "Confirm deletion", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
|
if (d.Equals(DialogResult.Yes))
|
|
{
|
|
/* Delete matrix file */
|
|
int matrixToDelete = _parent.romInfo.GetMatrixCount() - 1;
|
|
|
|
string matrixPath = RomInfo.gameDirs[DirNames.matrices].unpackedDir + "\\" + matrixToDelete.ToString("D4");
|
|
File.Delete(matrixPath);
|
|
|
|
/* Change selected index if the matrix to be deleted is currently selected */
|
|
if (selectMatrixComboBox.SelectedIndex == matrixToDelete)
|
|
{
|
|
selectMatrixComboBox.SelectedIndex--;
|
|
}
|
|
|
|
if (EditorPanels.eventEditor.eventEditorIsReady)
|
|
{
|
|
EditorPanels.eventEditor.eventMatrixUpDown.Maximum--;
|
|
}
|
|
|
|
/* Remove entry from ComboBox, and decrease matrix count */
|
|
selectMatrixComboBox.Items.RemoveAt(matrixToDelete);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("At least one matrix must be kept.", "Can't delete Matrix", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
}
|
|
}
|
|
private void setSpawnPointButton_Click(object sender, EventArgs e)
|
|
{
|
|
DataGridViewCell selectedCell = null;
|
|
switch (matrixTabControl.SelectedIndex)
|
|
{
|
|
case 0: //Maps
|
|
selectedCell = mapFilesGridView.SelectedCells[0];
|
|
selectedCell = headersGridView.Rows[selectedCell.RowIndex].Cells[selectedCell.ColumnIndex];
|
|
break;
|
|
case 1: //Headers
|
|
selectedCell = headersGridView.SelectedCells[0];
|
|
break;
|
|
case 2: //Altitudes
|
|
selectedCell = heightsGridView.SelectedCells[0];
|
|
selectedCell = headersGridView.Rows[selectedCell.RowIndex].Cells[selectedCell.ColumnIndex];
|
|
break;
|
|
}
|
|
|
|
ushort headerNumber = 0;
|
|
HashSet<string> result = null;
|
|
if (currentMatrix.hasHeadersSection)
|
|
{
|
|
headerNumber = Convert.ToUInt16(selectedCell.Value);
|
|
}
|
|
else
|
|
{
|
|
DialogResult d;
|
|
d = MessageBox.Show("This Matrix doesn't have a Header Tab. " +
|
|
Environment.NewLine + "Do you want to check if any Header uses this Matrix and choose that one as your Spawn Header? " +
|
|
Environment.NewLine + "\nChoosing 'No' will pick the last selected Header.", "Couldn't find Header Tab", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
|
if (d == DialogResult.Yes)
|
|
{
|
|
result = HeaderSearch.AdvancedSearch(0, (ushort)EditorPanels.headerEditor.internalNames.Count, EditorPanels.headerEditor.internalNames, (int)MapHeader.SearchableFields.MatrixID, (int)HeaderSearch.NumOperators.Equal, selectMatrixComboBox.SelectedIndex.ToString());
|
|
if (result.Count < 1)
|
|
{
|
|
MessageBox.Show("The current Matrix isn't assigned to any Header.\nThe default choice has been set to the last selected Header.", "No result", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
|
headerNumber = EditorPanels.headerEditor.currentHeader.ID;
|
|
}
|
|
else if (result.Count == 1)
|
|
{
|
|
headerNumber = ushort.Parse(result.First().Split()[0]);
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Multiple Headers are using this Matrix.\nPick one from the list or reset the filter results to choose a different Header.", "Multiple results", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
headerNumber = EditorPanels.headerEditor.currentHeader.ID;
|
|
}
|
|
}
|
|
|
|
int matrixX = selectedCell.ColumnIndex;
|
|
int matrixY = selectedCell.RowIndex;
|
|
|
|
using (SpawnEditor ed = new SpawnEditor(result, EditorPanels.headerEditor.headerListBoxNames, headerNumber, matrixX, matrixY))
|
|
{
|
|
ed.ShowDialog();
|
|
}
|
|
}
|
|
private void selectMatrixComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
ClearMatrixTables();
|
|
currentMatrix = new GameMatrix(selectMatrixComboBox.SelectedIndex);
|
|
GenerateMatrixTables();
|
|
|
|
/* Setup matrix editor controls */
|
|
Helpers.DisableHandlers();
|
|
matrixNameTextBox.Text = currentMatrix.name;
|
|
widthUpDown.Value = currentMatrix.width;
|
|
heightUpDown.Value = currentMatrix.height;
|
|
Helpers.EnableHandlers();
|
|
}
|
|
private void importColorTableButton_Click(object sender, EventArgs e)
|
|
{
|
|
OpenFileDialog of = new OpenFileDialog
|
|
{
|
|
Filter = "DSPRE Color Table File (*.ctb)|*.ctb"
|
|
};
|
|
if (of.ShowDialog(this) != DialogResult.OK)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ReadColorTable(of.FileName, silent: false);
|
|
}
|
|
|
|
private bool ReadColorTable(string fileName, bool silent)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(fileName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string[] fileTableContent = File.ReadAllLines(fileName);
|
|
|
|
if (fileTableContent.Length > 0)
|
|
{
|
|
const string mapKeyword = "[Maplist]";
|
|
const string colorKeyword = "[Color]";
|
|
const string textColorKeyword = "[TextColor]";
|
|
const string dashSeparator = "-";
|
|
string problematicSegment = "incomplete line";
|
|
|
|
Dictionary<List<uint>, (Color background, Color foreground)> colorsDict = new Dictionary<List<uint>, (Color background, Color foreground)>();
|
|
List<string> linesWithErrors = new List<string>();
|
|
|
|
for (int i = 0; i < fileTableContent.Length; i++)
|
|
{
|
|
if (fileTableContent[i].Length > 0)
|
|
{
|
|
string[] lineParts = fileTableContent[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
try
|
|
{
|
|
int j = 0;
|
|
if (!lineParts[j].Equals(mapKeyword))
|
|
{
|
|
problematicSegment = nameof(mapKeyword);
|
|
throw new FormatException();
|
|
}
|
|
j++;
|
|
|
|
List<uint> mapList = new List<uint>();
|
|
while (!lineParts[j].Equals(dashSeparator))
|
|
{
|
|
|
|
if (lineParts[j].Equals("and"))
|
|
{
|
|
j++;
|
|
}
|
|
uint firstValue = uint.Parse(lineParts[j++]);
|
|
mapList.Add(firstValue);
|
|
|
|
if (lineParts[j].Equals("to"))
|
|
{
|
|
j++;
|
|
uint finalValue = uint.Parse(lineParts[j++]);
|
|
//Add all numbers ranging from maplist[0] to finalValue
|
|
if (firstValue > finalValue)
|
|
Swap(ref firstValue, ref finalValue);
|
|
|
|
for (uint k = firstValue + 1; k <= finalValue; k++)
|
|
{
|
|
mapList.Add(k);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!lineParts[j].Equals(dashSeparator))
|
|
{
|
|
problematicSegment = nameof(dashSeparator);
|
|
throw new FormatException();
|
|
}
|
|
j++;
|
|
|
|
if (!lineParts[j].Equals(colorKeyword))
|
|
{
|
|
problematicSegment = nameof(colorKeyword);
|
|
throw new FormatException();
|
|
}
|
|
j++;
|
|
|
|
int r = Int32.Parse(lineParts[j++]);
|
|
int g = Int32.Parse(lineParts[j++]);
|
|
int b = Int32.Parse(lineParts[j++]);
|
|
|
|
if (!lineParts[j].Equals(dashSeparator))
|
|
{
|
|
problematicSegment = nameof(dashSeparator);
|
|
throw new FormatException();
|
|
}
|
|
j++;
|
|
|
|
if (!lineParts[j].Equals(textColorKeyword))
|
|
{
|
|
problematicSegment = nameof(textColorKeyword);
|
|
throw new FormatException();
|
|
}
|
|
j++;
|
|
|
|
colorsDict.Add(mapList, (Color.FromArgb(r, g, b), Color.FromName(lineParts[j++])));
|
|
}
|
|
catch
|
|
{
|
|
if (!silent)
|
|
{
|
|
linesWithErrors.Add(i + 1 + " (err. " + problematicSegment + ")\n");
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
colorsDict.Add(new List<uint> { GameMatrix.EMPTY }, (Color.Black, Color.White));
|
|
|
|
string errorMsg = "";
|
|
MessageBoxIcon iconType = MessageBoxIcon.Information;
|
|
|
|
if (!silent)
|
|
{
|
|
if (linesWithErrors.Count > 0)
|
|
{
|
|
errorMsg = "\nHowever, the following lines couldn't be parsed correctly:\n";
|
|
|
|
foreach (string s in linesWithErrors)
|
|
{
|
|
errorMsg += "- Line " + s;
|
|
}
|
|
|
|
iconType = MessageBoxIcon.Warning;
|
|
}
|
|
}
|
|
_parent.romInfo.MapCellsColorDictionary = colorsDict;
|
|
ClearMatrixTables();
|
|
GenerateMatrixTables();
|
|
|
|
SettingsManager.Settings.lastColorTablePath = fileName;
|
|
|
|
if (!silent)
|
|
{
|
|
MessageBox.Show("Color file has been read." + errorMsg, "Operation completed", MessageBoxButtons.OK, iconType);
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if (!silent)
|
|
{
|
|
MessageBox.Show("No readable content was found in this file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void Swap(ref uint a, ref uint b)
|
|
{
|
|
uint temp = a;
|
|
a = b;
|
|
b = temp;
|
|
}
|
|
private void resetColorTableButton_Click(object sender, EventArgs e)
|
|
{
|
|
_parent.romInfo.ResetMapCellsColorDictionary();
|
|
ClearMatrixTables();
|
|
GenerateMatrixTables();
|
|
|
|
SettingsManager.Settings.lastColorTablePath = "";
|
|
}
|
|
|
|
/*
|
|
private void ExportAllMovePermissionsInMatrix(object sender, EventArgs e) {
|
|
CommonOpenFileDialog romFolder = new CommonOpenFileDialog();
|
|
romFolder.IsFolderPicker = true;
|
|
romFolder.Multiselect = false;
|
|
|
|
if (romFolder.ShowDialog() != CommonFileDialogResult.Ok) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < currentMatrix.height; i++) {
|
|
for (int j = 0; j < currentMatrix.width; j++) {
|
|
ushort val = currentMatrix.maps[i, j];
|
|
if (val < ushort.MaxValue) {
|
|
string path = romFolder.FileName + "\\" + currentMatrix.id + j.ToString("D2") + "_" + i.ToString("D2") + ".per";
|
|
File.WriteAllBytes(path, new MapFile(val).CollisionsToByteArray());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
#endregion
|
|
|
|
private void mapFilesGridView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
|
|
{
|
|
if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
|
|
{
|
|
if (currentMatrix.maps[e.RowIndex, e.ColumnIndex] == GameMatrix.EMPTY)
|
|
{
|
|
MessageBox.Show("You can't load an empty map.\nSelect a valid map and try again.\n\n" +
|
|
"If you only meant to change the value of this cell, wait some time between one mouse click and the other.\n" +
|
|
"Alternatively, highlight the cell and press F2 on your keyboard.",
|
|
"User attempted to load VOID", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
EditorPanels.mapEditor.SetupMapEditor(_parent);
|
|
|
|
int mapCount = _parent.romInfo.GetMapCount();
|
|
if (currentMatrix.maps[e.RowIndex, e.ColumnIndex] >= mapCount)
|
|
{
|
|
MessageBox.Show("This matrix cell points to a map file that doesn't exist.",
|
|
"There " + ((mapCount > 1) ? "are only " + mapCount + " map files." : "is only 1 map file."), MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
/* Determine area data */
|
|
ushort headerID = 0;
|
|
if (currentMatrix.hasHeadersSection)
|
|
{
|
|
headerID = currentMatrix.headers[e.RowIndex, e.ColumnIndex];
|
|
}
|
|
else
|
|
{
|
|
ushort[] result = HeaderSearch.AdvancedSearch(0, (ushort)EditorPanels.headerEditor.internalNames.Count, EditorPanels.headerEditor.internalNames, (int)MapHeader.SearchableFields.MatrixID, (int)HeaderSearch.NumOperators.Equal, selectMatrixComboBox.SelectedIndex.ToString())
|
|
.Select(x => ushort.Parse(x.Split()[0]))
|
|
.ToArray();
|
|
|
|
if (result.Length < 1)
|
|
{
|
|
headerID = EditorPanels.headerEditor.currentHeader.ID;
|
|
Helpers.statusLabelMessage("This Matrix is not linked to any Header. DSPRE can't determine the most appropriate AreaData (and textures) to use.\nDisplaying Textures from the last selected Header (" + headerID + ")'s AreaData...");
|
|
}
|
|
else
|
|
{
|
|
if (result.Length > 1)
|
|
{
|
|
if (result.Contains(EditorPanels.headerEditor.currentHeader.ID))
|
|
{
|
|
headerID = EditorPanels.headerEditor.currentHeader.ID;
|
|
|
|
Helpers.statusLabelMessage("Multiple Headers are associated to this Matrix, including the last selected one [Header " + headerID + "]. Now using its textures.");
|
|
}
|
|
else
|
|
{
|
|
if (gameFamily.Equals(GameFamilies.DP))
|
|
{
|
|
foreach (ushort r in result)
|
|
{
|
|
HeaderDP hdp;
|
|
hdp = (HeaderDP)MapHeader.LoadFromARM9(r);
|
|
|
|
if (hdp.locationName != 0)
|
|
{
|
|
headerID = hdp.ID;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (gameFamily.Equals(GameFamilies.Plat))
|
|
{
|
|
foreach (ushort r in result)
|
|
{
|
|
HeaderPt hpt;
|
|
if (PatchToolboxDialog.flag_DynamicHeadersPatchApplied || PatchToolboxDialog.CheckFilesDynamicHeadersPatchApplied())
|
|
{
|
|
hpt = (HeaderPt)MapHeader.LoadFromFile(RomInfo.gameDirs[DirNames.dynamicHeaders].unpackedDir + "\\" + r.ToString("D4"), r, 0);
|
|
}
|
|
else
|
|
{
|
|
hpt = (HeaderPt)MapHeader.LoadFromARM9(r);
|
|
}
|
|
|
|
if (hpt.locationName != 0)
|
|
{
|
|
headerID = hpt.ID;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (ushort r in result)
|
|
{
|
|
HeaderHGSS hgss;
|
|
if (PatchToolboxDialog.flag_DynamicHeadersPatchApplied || PatchToolboxDialog.CheckFilesDynamicHeadersPatchApplied())
|
|
{
|
|
hgss = (HeaderHGSS)MapHeader.LoadFromFile(RomInfo.gameDirs[DirNames.dynamicHeaders].unpackedDir + "\\" + r.ToString("D4"), r, 0);
|
|
}
|
|
else
|
|
{
|
|
hgss = (HeaderHGSS)MapHeader.LoadFromARM9(r);
|
|
}
|
|
|
|
if (hgss.locationName != 0)
|
|
{
|
|
headerID = hgss.ID;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Helpers.statusLabelMessage("Multiple Headers are using this Matrix. Header " + headerID + "'s textures are currently being displayed.");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
headerID = result[0];
|
|
Helpers.statusLabelMessage("Loading Header " + headerID + "'s textures.");
|
|
}
|
|
}
|
|
}
|
|
Update();
|
|
|
|
if (headerID > EditorPanels.headerEditor.internalNames.Count)
|
|
{
|
|
MessageBox.Show("This map is associated to a non-existent header.\nThis will lead to unpredictable behaviour and, possibily, problems, if you attempt to load it in game.",
|
|
"Invalid header", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
headerID = 0;
|
|
}
|
|
|
|
/* get texture file numbers from area data */
|
|
MapHeader h;
|
|
if (PatchToolboxDialog.flag_DynamicHeadersPatchApplied || PatchToolboxDialog.CheckFilesDynamicHeadersPatchApplied())
|
|
{
|
|
h = MapHeader.LoadFromFile(RomInfo.gameDirs[DirNames.dynamicHeaders].unpackedDir + "\\" + headerID.ToString("D4"), headerID, 0);
|
|
}
|
|
else
|
|
{
|
|
h = MapHeader.LoadFromARM9(headerID);
|
|
}
|
|
|
|
/* Load Map File and switch to Map Editor tab */
|
|
Helpers.DisableHandlers();
|
|
|
|
AreaData areaData = new AreaData(h.areaDataID);
|
|
EditorPanels.mapEditor.selectMapComboBox.SelectedIndex = currentMatrix.maps[e.RowIndex, e.ColumnIndex];
|
|
EditorPanels.mapEditor.mapTextureComboBox.SelectedIndex = areaData.mapTileset + 1;
|
|
EditorPanels.mapEditor.buildTextureComboBox.SelectedIndex = areaData.buildingsTileset + 1;
|
|
_parent.mainTabControl.SelectedTab = EditorPanels.mapEditorTabPage;
|
|
|
|
if (areaData.areaType == AreaData.TYPE_INDOOR)
|
|
{
|
|
EditorPanels.mapEditor.interiorbldRadioButton.Checked = true;
|
|
}
|
|
else
|
|
{
|
|
EditorPanels.mapEditor.exteriorbldRadioButton.Checked = true;
|
|
}
|
|
|
|
Helpers.EnableHandlers();
|
|
EditorPanels.mapEditor.selectMapComboBox_SelectedIndexChanged(null, null);
|
|
}
|
|
}
|
|
}
|
|
}
|