DS-Pokemon-Rom-Editor/DS_Map/Editors/MapEditor.cs
2025-09-02 09:17:38 +02:00

2215 lines
91 KiB
C#

using DSPRE.Resources;
using DSPRE.ROMFiles;
using LibNDSFormats.NSBMD;
using LibNDSFormats.NSBTX;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Tao.OpenGl;
using static DSPRE.RomInfo;
using static Tao.Platform.Windows.Winmm;
namespace DSPRE.Editors
{
public partial class MapEditor : UserControl
{
MainProgram _parent;
public bool mapEditorIsReady { get; set; } = false;
public MapEditor()
{
InitializeComponent();
}
#region Map Editor
#region Variables & Constants
public const int mapEditorSquareSize = 19;
/* Map Rotation vars */
public bool lRot;
public bool rRot;
public bool uRot;
public bool dRot;
/* Screenshot Interpolation mode */
public InterpolationMode intMode;
/* Camera settings */
public bool hideBuildings = new bool();
public bool mapTexturesOn = true;
public bool bldTexturesOn = true;
public static float ang = 0.0f;
public static float dist = 12.8f;
public static float elev = 50.0f;
public float perspective = 45f;
private byte bldDecimalPositions = 1;
/* Renderers */
public static NSBMDGlRenderer mapRenderer = new NSBMDGlRenderer();
public static NSBMDGlRenderer buildingsRenderer = new NSBMDGlRenderer();
/* Map file */
MapFile currentMapFile;
/* Permission painters */
public Pen paintPen;
public int Transparency = 128;
public SolidBrush paintBrush;
public SolidBrush textBrush;
public byte paintByte;
StringFormat sf;
public Rectangle mainCell;
public Rectangle smallCell;
public Rectangle painterBox = new Rectangle(0, 0, 100, 100);
public Font textFont;
#endregion
#region Subroutines
private void FillBuildingsBox()
{
buildingsListBox.Items.Clear();
uint id = 0;
for (int i = 0; i < currentMapFile.buildings.Count; i++)
{
id = currentMapFile.buildings[i].modelID;
string baseName = (i + 1).ToString("D2") + MapHeader.nameSeparator;
try
{
buildingsListBox.Items.Add(baseName + buildIndexComboBox.Items[(int)id]);
}
catch (ArgumentOutOfRangeException)
{
DialogResult d = MessageBox.Show("Building #" + id + " couldn't be found in the Building List.\n" +
"Do you want to load Building 0 in its place?\n" +
"(Choosing \"Cancel\" will discard this building altogether.)", "Building not found", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Error);
if (d == DialogResult.Yes)
{
buildingsListBox.Items.Add(baseName + buildIndexComboBox.Items[0]);
}
else if (d == DialogResult.No)
{
buildingsListBox.Items.Add(baseName + "MISSING " + (int)id + '!');
} // else do nothing
}
}
}
private void MW_LoadModelTextures(NSBMD model, string textureFolder, int fileID)
{
if (fileID < 0)
{
return;
}
string texturePath = textureFolder + "\\" + fileID.ToString("D4");
model.materials = NSBTXLoader.LoadNsbtx(new MemoryStream(File.ReadAllBytes(texturePath)), out model.Textures, out model.Palettes);
try
{
model.MatchTextures();
}
catch { }
}
private void ScaleTranslateRotateBuilding(Building building)
{
float fullXcoord = building.xPosition + building.xFraction / 65536f;
float fullYcoord = building.yPosition + building.yFraction / 65536f;
float fullZcoord = building.zPosition + building.zFraction / 65536f;
float scaleFactor = building.NSBMDFile.models[0].modelScale / 1024;
float translateFactor = 256 / building.NSBMDFile.models[0].modelScale;
Gl.glScalef(scaleFactor * building.width, scaleFactor * building.height, scaleFactor * building.length);
Gl.glTranslatef(fullXcoord * translateFactor / building.width, fullYcoord * translateFactor / building.height, fullZcoord * translateFactor / building.length);
Gl.glRotatef(Building.U16ToDeg(building.xRotation), 1, 0, 0);
Gl.glRotatef(Building.U16ToDeg(building.yRotation), 0, 1, 0);
Gl.glRotatef(Building.U16ToDeg(building.zRotation), 0, 0, 1);
}
private void SetupRenderer(float ang, float dist, float elev, float perspective, int width, int height)
{
//TODO: improve this
Gl.glEnable(Gl.GL_RESCALE_NORMAL);
Gl.glEnable(Gl.GL_COLOR_MATERIAL);
Gl.glEnable(Gl.GL_DEPTH_TEST);
Gl.glEnable(Gl.GL_NORMALIZE);
Gl.glDisable(Gl.GL_CULL_FACE);
Gl.glFrontFace(Gl.GL_CCW);
Gl.glClearDepth(1);
Gl.glEnable(Gl.GL_ALPHA_TEST);
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
Gl.glEnable(Gl.GL_BLEND);
Gl.glAlphaFunc(Gl.GL_GREATER, 0f);
Gl.glClearColor(51f / 255f, 51f / 255f, 51f / 255f, 1f);
float aspect;
Gl.glViewport(0, 0, width, height);
aspect = mapOpenGlControl.Width / mapOpenGlControl.Height;//(vp[2] - vp[0]) / (vp[3] - vp[1]);
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
Glu.gluPerspective(perspective, aspect, 0.2f, 500.0f);//0.02f, 32.0f);
Gl.glTranslatef(0, 0, -dist);
Gl.glRotatef(elev, 1, 0, 0);
Gl.glRotatef(ang, 0, 1, 0);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();
Gl.glTranslatef(0, 0, -dist);
Gl.glRotatef(elev, 1, 0, 0);
Gl.glRotatef(-ang, 0, 1, 0);
Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
Gl.glLightfv(Gl.GL_LIGHT2, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
Gl.glLightfv(Gl.GL_LIGHT3, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
Gl.glLoadIdentity();
Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0);
Gl.glColor3f(1.0f, 1.0f, 1.0f);
Gl.glDepthMask(Gl.GL_TRUE);
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
}
#endregion
public void SetupMapEditor(MainProgram parent, bool force=false)
{
mapOpenGlControl.InitializeContexts();
mapOpenGlControl.MakeCurrent();
mapOpenGlControl.MouseWheel += new MouseEventHandler(mapOpenGlControl_MouseWheel);
if (mapEditorIsReady && !force) { return; }
mapEditorIsReady = true;
this._parent = parent;
if (selectMapComboBox.SelectedIndex > -1)
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
/* Extract essential NARCs sub-archives*/
_parent.toolStripProgressBar.Visible = true;
_parent.toolStripProgressBar.Maximum = 9;
_parent.toolStripProgressBar.Value = 0;
Helpers.statusLabelMessage("Attempting to unpack Map Editor NARCs... Please wait.");
Update();
DSUtils.TryUnpackNarcs(new List<DirNames> { DirNames.maps,
DirNames.exteriorBuildingModels,
DirNames.buildingConfigFiles,
DirNames.buildingTextures,
DirNames.mapTextures,
DirNames.areaData,
});
if (RomInfo.gameFamily == GameFamilies.HGSS)
{
DSUtils.TryUnpackNarcs(new List<DirNames> { DirNames.interiorBuildingModels });
}
Helpers.DisableHandlers();
collisionPainterPictureBox.Image = new Bitmap(100, 100);
typePainterPictureBox.Image = new Bitmap(100, 100);
switch (RomInfo.gameFamily)
{
case GameFamilies.DP:
case GameFamilies.Plat:
mapPartsTabControl.TabPages.Remove(bgsTabPage);
break;
default:
interiorbldRadioButton.Enabled = true;
exteriorbldRadioButton.Enabled = true;
break;
}
;
/* Add map names to box */
selectMapComboBox.Items.Clear();
int mapCount = _parent.romInfo.GetMapCount();
for (int i = 0; i < mapCount; i++)
{
using (DSUtils.EasyReader reader = new DSUtils.EasyReader(RomInfo.gameDirs[DirNames.maps].unpackedDir + "\\" + i.ToString("D4")))
{
switch (RomInfo.gameFamily)
{
case GameFamilies.DP:
case GameFamilies.Plat:
reader.BaseStream.Position = 0x10 + reader.ReadUInt32() + reader.ReadUInt32();
break;
default:
reader.BaseStream.Position = 0x12;
short bgsSize = reader.ReadInt16();
long backupPos = reader.BaseStream.Position;
reader.BaseStream.Position = 0;
reader.BaseStream.Position = backupPos + bgsSize + reader.ReadUInt32() + reader.ReadUInt32();
break;
}
;
reader.BaseStream.Position += 0x14;
selectMapComboBox.Items.Add(i.ToString("D3") + MapHeader.nameSeparator + NSBUtils.ReadNSBMDname(reader));
}
}
_parent.toolStripProgressBar.Value++;
/* Fill building models list */
updateBuildingListComboBox(false);
/* Fill map textures list */
mapTextureComboBox.Items.Clear();
mapTextureComboBox.Items.Add("Untextured");
for (int i = 0; i < _parent.romInfo.GetMapTexturesCount(); i++)
{
mapTextureComboBox.Items.Add("Map Texture Pack [" + i.ToString("D2") + "]");
}
_parent.toolStripProgressBar.Value++;
/* Fill building textures list */
buildTextureComboBox.Items.Clear();
buildTextureComboBox.Items.Add("Untextured");
for (int i = 0; i < _parent.romInfo.GetBuildingTexturesCount(); i++)
{
buildTextureComboBox.Items.Add("Building Texture Pack [" + i.ToString("D2") + "]");
}
_parent.toolStripProgressBar.Value++;
collisionPainterComboBox.Items.Clear();
foreach (string s in PokeDatabase.System.MapCollisionPainters.Values)
{
collisionPainterComboBox.Items.Add(s);
}
collisionTypePainterComboBox.Items.Clear();
foreach (string s in PokeDatabase.System.MapCollisionTypePainters.Values)
{
collisionTypePainterComboBox.Items.Add(s);
}
_parent.toolStripProgressBar.Value++;
/* Set controls' initial values */
selectCollisionPanel.BackColor = Color.MidnightBlue;
collisionTypePainterComboBox.SelectedIndex = 0;
collisionPainterComboBox.SelectedIndex = 1;
_parent.toolStripProgressBar.Value = 0;
_parent.toolStripProgressBar.Visible = false;
Helpers.EnableHandlers();
//Default selections
selectMapComboBox.SelectedIndex = 0;
exteriorbldRadioButton.Checked = true;
switch (RomInfo.gameFamily)
{
case GameFamilies.DP:
case GameFamilies.Plat:
mapTextureComboBox.SelectedIndex = 7;
buildTextureComboBox.SelectedIndex = 1;
break;
case GameFamilies.HGSS:
mapTextureComboBox.SelectedIndex = 3;
buildTextureComboBox.SelectedIndex = 1;
break;
default:
mapTextureComboBox.SelectedIndex = 2;
buildTextureComboBox.SelectedIndex = 1;
break;
}
;
Helpers.statusLabelMessage();
}
private void addMapFileButton_Click(object sender, EventArgs e)
{
/* Add new map file to map folder */
new MapFile(0, RomInfo.gameFamily, discardMoveperms: true).SaveToFileDefaultDir(selectMapComboBox.Items.Count);
/* Update ComboBox and select new file */
selectMapComboBox.Items.Add(selectMapComboBox.Items.Count.ToString("D3") + MapHeader.nameSeparator + "newmap");
selectMapComboBox.SelectedIndex = selectMapComboBox.Items.Count - 1;
}
private void replaceMapBinButton_Click(object sender, EventArgs e)
{
/* Prompt user to select .bin file */
OpenFileDialog of = new OpenFileDialog
{
Filter = "Map BIN File (*.bin)|*.bin"
};
if (of.ShowDialog(this) != DialogResult.OK)
{
return;
}
MapFile temp = new MapFile(of.FileName, RomInfo.gameFamily, false);
if (temp.correctnessFlag)
{
UpdateMapBinAndRefresh(temp, "Map BIN imported successfully!");
return;
}
else
{
if (RomInfo.gameFamily == GameFamilies.HGSS)
{
//If HGSS didn't work try reading as Platinum Map
temp = new MapFile(of.FileName, GameFamilies.Plat, false);
}
else
{
//If Plat didn't work try reading as HGSS Map
temp = new MapFile(of.FileName, GameFamilies.HGSS, false);
}
if (temp.correctnessFlag)
{
UpdateMapBinAndRefresh(temp, "Map BIN imported and adapted successfully!");
return;
}
}
MessageBox.Show("The BIN file you imported is corrupted!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
private void UpdateMapBinAndRefresh(MapFile newerVersion, string message)
{
currentMapFile = newerVersion;
/* Update map BIN file */
currentMapFile.SaveToFileDefaultDir(selectMapComboBox.SelectedIndex, showSuccessMessage: false);
/* Refresh controls */
selectMapComboBox_SelectedIndexChanged(null, null);
/* Display success message */
MessageBox.Show(message, "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void buildTextureComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
int btIndex = buildTextureComboBox.SelectedIndex;
if (Helpers.HandlersDisabled || btIndex < 0)
{
return;
}
if (btIndex == 0)
{
bldTexturesOn = false;
}
else
{
string texturePath = RomInfo.gameDirs[DirNames.buildingTextures].unpackedDir + "\\" + (btIndex - 1).ToString("D4");
byte[] textureFile = File.ReadAllBytes(texturePath);
Stream str = new MemoryStream(textureFile);
foreach (Building building in currentMapFile.buildings)
{
str.Position = 0;
NSBMD file = building.NSBMDFile;
if (file != null)
{
file.materials = NSBTXLoader.LoadNsbtx(str, out file.Textures, out file.Palettes);
try
{
file.MatchTextures();
bldTexturesOn = true;
}
catch
{
string itemAtIndex = buildTextureComboBox.Items[btIndex].ToString();
if (!itemAtIndex.StartsWith("Error!"))
{
Helpers.DisableHandlers();
buildTextureComboBox.Items[btIndex] = itemAtIndex.Insert(0, "Error! - ");
Helpers.EnableHandlers();
}
bldTexturesOn = false;
}
}
}
//buildTextureComboBox.Items[buildTextureComboBox.SelectedIndex] = "Error - Building Texture Pack too small [" + (buildTextureComboBox.SelectedIndex - 1).ToString("D2") + "]";
}
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
private void mapTextureComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (Helpers.HandlersDisabled)
{
return;
}
if (mapTextureComboBox.SelectedIndex == 0)
mapTexturesOn = false;
else
{
mapTexturesOn = true;
string texturePath = RomInfo.gameDirs[DirNames.mapTextures].unpackedDir + "\\" + (mapTextureComboBox.SelectedIndex - 1).ToString("D4");
currentMapFile.mapModel.materials = NSBTXLoader.LoadNsbtx(new MemoryStream(File.ReadAllBytes(texturePath)), out currentMapFile.mapModel.Textures, out currentMapFile.mapModel.Palettes);
try
{
currentMapFile.mapModel.MatchTextures();
}
catch { }
}
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
public void mapOpenGlControl_MouseWheel(object sender, MouseEventArgs e)
{
if (mapPartsTabControl.SelectedTab == buildingsTabPage && bldPlaceWithMouseCheckbox.Checked)
{
return;
}
dist -= (float)e.Delta / 200;
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
private void mapOpenGlControl_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
byte multiplier = 2;
if (e.Modifiers == Keys.Shift)
{
multiplier = 1;
}
else if (e.Modifiers == Keys.Control)
{
multiplier = 4;
}
switch (e.KeyCode)
{
case Keys.Right:
rRot = true;
lRot = false;
break;
case Keys.Left:
rRot = false;
lRot = true;
break;
case Keys.Up:
dRot = false;
uRot = true;
break;
case Keys.Down:
dRot = true;
uRot = false;
break;
}
if (rRot ^ lRot)
{
if (rRot)
{
ang += 1 * multiplier;
}
else if (lRot)
{
ang -= 1 * multiplier;
}
}
if (uRot ^ dRot)
{
if (uRot)
{
elev -= 1 * multiplier;
}
else if (dRot)
{
elev += 1 * multiplier;
}
}
mapOpenGlControl.Invalidate();
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
private void mapOpenGlControl_KeyUp(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Right:
rRot = false;
break;
case Keys.Left:
lRot = false;
break;
case Keys.Up:
uRot = false;
break;
case Keys.Down:
dRot = false;
break;
}
}
private void mapOpenGlControl_Click(object sender, EventArgs e)
{
if (radio2D.Checked && bldPlaceWithMouseCheckbox.Checked)
{
PointF coordinates = mapRenderPanel.PointToClient(Cursor.Position);
PointF mouseTilePos = new PointF(coordinates.X / mapEditorSquareSize, coordinates.Y / mapEditorSquareSize);
if (buildingsListBox.SelectedIndex > -1)
{
if (!bldPlaceLockXcheckbox.Checked)
xBuildUpDown.Value = (decimal)(Math.Round(mouseTilePos.X, bldDecimalPositions) - 16);
if (!bldPlaceLockZcheckbox.Checked)
zBuildUpDown.Value = (decimal)(Math.Round(mouseTilePos.Y, bldDecimalPositions) - 16);
}
}
}
private void bldRoundWhole_CheckedChanged(object sender, EventArgs e)
{
bldDecimalPositions = 0;
}
private void bldRoundDec_CheckedChanged(object sender, EventArgs e)
{
bldDecimalPositions = 1;
}
private void bldRoundCent_CheckedChanged(object sender, EventArgs e)
{
bldDecimalPositions = 2;
}
private void bldRoundMil_CheckedChanged(object sender, EventArgs e)
{
bldDecimalPositions = 3;
}
private void bldRoundDecmil_CheckedChanged(object sender, EventArgs e)
{
bldDecimalPositions = 4;
}
private void bldRoundCentMil_CheckedChanged(object sender, EventArgs e)
{
bldDecimalPositions = 5;
}
private void bldPlaceWithMouseCheckbox_CheckedChanged(object sender, EventArgs e)
{
bool status = bldPlaceWithMouseCheckbox.Checked && radio2D.Checked;
bldPlaceLockXcheckbox.Enabled = status;
bldPlaceLockZcheckbox.Enabled = status;
bldRoundGroupbox.Enabled = status;
lockXZgroupbox.Enabled = status;
if (status)
{
SetCam2D();
}
}
private void bldPlaceLockXcheckbox_CheckedChanged(object sender, EventArgs e)
{
Helpers.ExclusiveCBInvert(bldPlaceLockZcheckbox);
}
private void bldPlaceLockZcheckbox_CheckedChanged(object sender, EventArgs e)
{
Helpers.ExclusiveCBInvert(bldPlaceLockXcheckbox);
}
private void mapPartsTabControl_SelectedIndexChanged(object sender, EventArgs e)
{
if (mapPartsTabControl.SelectedTab == buildingsTabPage)
{
radio2D.Checked = false;
hideBuildings = false;
radio3D.Enabled = true;
radio2D.Enabled = true;
wireframeCheckBox.Enabled = true;
mapOpenGlControl.BringToFront();
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile,
ang, dist, elev, perspective,
mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
else if (mapPartsTabControl.SelectedTab == permissionsTabPage)
{
radio2D.Checked = true;
hideBuildings = false;
radio3D.Enabled = false;
radio2D.Enabled = false;
wireframeCheckBox.Enabled = false;
SetCam2D();
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile,
ang, dist, elev, perspective,
mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
movPictureBox.BackgroundImage = GrabMapScreenshot(movPictureBox.Width, movPictureBox.Height);
movPictureBox.BringToFront();
}
else if (mapPartsTabControl.SelectedTab == modelTabPage)
{
radio2D.Checked = false;
hideBuildings = true;
radio3D.Enabled = true;
radio2D.Enabled = true;
wireframeCheckBox.Enabled = true;
mapOpenGlControl.BringToFront();
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile,
ang, dist, elev, perspective,
mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
else
{ // Terrain and BGS
radio2D.Checked = true;
hideBuildings = false;
radio3D.Enabled = false;
radio2D.Enabled = false;
wireframeCheckBox.Enabled = false;
mapOpenGlControl.BringToFront();
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile,
ang, dist, elev, perspective,
mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
}
private void radio2D_CheckedChanged(object sender, EventArgs e)
{
bool _2dmodeSelected = radio2D.Checked;
if (_2dmodeSelected)
{
SetCam2D();
}
else
{
SetCam3D();
}
bldPlaceWithMouseCheckbox.Enabled = _2dmodeSelected;
radio3D.Checked = !_2dmodeSelected;
bldPlaceWithMouseCheckbox_CheckedChanged(null, null);
}
private void SetCam2D()
{
perspective = 4f;
ang = 0f;
dist = 115.2f;
elev = 90f;
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile,
ang, dist, elev, perspective,
mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
private void SetCam3D()
{
perspective = 45f;
ang = 0f;
dist = 12.8f;
elev = 50.0f;
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile,
ang, dist, elev, perspective,
mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
private void mapScreenshotButton_Click(object sender, EventArgs e)
{
MessageBox.Show("Choose where to save the map screenshot.", "Choose destination path", MessageBoxButtons.OK, MessageBoxIcon.Information);
SaveFileDialog imageSFD = new SaveFileDialog
{
Filter = "PNG File(*.png)|*.png",
};
if (imageSFD.ShowDialog() != DialogResult.OK)
{
return;
}
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile,
ang, dist, elev, perspective,
mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
int newW = 512, newH = 512;
Bitmap newImage = new Bitmap(newW, newH);
using (var graphCtr = Graphics.FromImage(newImage))
{
graphCtr.SmoothingMode = SmoothingMode.HighQuality;
graphCtr.InterpolationMode = InterpolationMode.NearestNeighbor;
graphCtr.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphCtr.DrawImage(GrabMapScreenshot(mapOpenGlControl.Width, mapOpenGlControl.Height), 0, 0, newW, newH);
}
newImage.Save(imageSFD.FileName);
MessageBox.Show("Screenshot saved.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void removeLastMapFileButton_Click(object sender, EventArgs e)
{
DialogResult d = MessageBox.Show("Are you sure you want to delete the last Map BIN File?", "Confirm deletion", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (d.Equals(DialogResult.Yes))
{
/* Delete last map file */
File.Delete(RomInfo.gameDirs[DirNames.maps].unpackedDir + "\\" + (selectMapComboBox.Items.Count - 1).ToString("D4"));
/* Check if currently selected file is the last one, and in that case select the one before it */
int lastIndex = selectMapComboBox.Items.Count - 1;
if (selectMapComboBox.SelectedIndex == lastIndex)
selectMapComboBox.SelectedIndex--;
/* Remove item from ComboBox */
selectMapComboBox.Items.RemoveAt(lastIndex);
}
}
private void saveMapButton_Click(object sender, EventArgs e)
{
currentMapFile.SaveToFileDefaultDir(selectMapComboBox.SelectedIndex);
}
private void exportCurrentMapBinButton_Click(object sender, EventArgs e)
{
currentMapFile.SaveToFileExplorePath(selectMapComboBox.SelectedItem.ToString());
}
public void selectMapComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (Helpers.HandlersDisabled)
{
return;
}
/* Load map data into MapFile class instance */
currentMapFile = new MapFile(selectMapComboBox.SelectedIndex, RomInfo.gameFamily);
/* Load map textures for renderer */
if (mapTextureComboBox.SelectedIndex > 0)
{
MW_LoadModelTextures(currentMapFile.mapModel, RomInfo.gameDirs[DirNames.mapTextures].unpackedDir, mapTextureComboBox.SelectedIndex - 1);
}
/* Load buildings nsbmd and textures for renderer into MapFile's building objects */
for (int i = 0; i < currentMapFile.buildings.Count; i++)
{
currentMapFile.buildings[i].LoadModelData(_parent.romInfo.GetBuildingModelsDirPath(interiorbldRadioButton.Checked)); // Load building nsbmd
if (buildTextureComboBox.SelectedIndex > 0)
{
MW_LoadModelTextures(currentMapFile.buildings[i].NSBMDFile, RomInfo.gameDirs[DirNames.buildingTextures].unpackedDir, buildTextureComboBox.SelectedIndex - 1); // Load building textures
}
}
/* Render the map */
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
/* Draw permissions in the small selection boxes */
DrawSmallCollision();
DrawSmallTypeCollision();
/* Draw selected permissions category */
if (selectCollisionPanel.BackColor == Color.MidnightBlue)
{
DrawCollisionGrid();
}
else
{
DrawTypeGrid();
}
/* Set map screenshot as background picture in permissions editor PictureBox */
movPictureBox.BackgroundImage = GrabMapScreenshot(movPictureBox.Width, movPictureBox.Height);
RestorePainter();
/* Fill buildings ListBox, and if not empty select first item */
FillBuildingsBox();
if (buildingsListBox.Items.Count > 0)
{
buildingsListBox.SelectedIndex = 0;
}
modelSizeLBL.Text = currentMapFile.mapModelData.Length.ToString() + " B";
terrainSizeLBL.Text = currentMapFile.bdhc.Length.ToString() + " B";
if (RomInfo.gameFamily == GameFamilies.HGSS)
{
BGSSizeLBL.Text = currentMapFile.bgs.Length.ToString() + " B";
}
}
private void wireframeCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (wireframeCheckBox.Checked)
{
Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_LINE);
}
else
{
Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_FILL);
}
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
private void transparencyBar_Scroll(object sender, EventArgs e)
{
Transparency = transparencyBar.Value;
if (selectCollisionPanel.BackColor == Color.MidnightBlue)
{
DrawCollisionGrid();
}
else
{
DrawTypeGrid();
}
}
#region Building Editor
private void addBuildingButton_Click(object sender, EventArgs e)
{
AddBuildingToMap(new Building());
}
private void duplicateBuildingButton_Click(object sender, EventArgs e)
{
if (buildingsListBox.SelectedIndex > -1)
{
AddBuildingToMap(new Building(currentMapFile.buildings[buildingsListBox.SelectedIndex]));
}
}
private void AddBuildingToMap(Building b)
{
currentMapFile.buildings.Add(b);
/* Load new building's model and textures for the renderer */
b.LoadModelData(_parent.romInfo.GetBuildingModelsDirPath(interiorbldRadioButton.Checked));
MW_LoadModelTextures(b.NSBMDFile, RomInfo.gameDirs[DirNames.buildingTextures].unpackedDir, buildTextureComboBox.SelectedIndex - 1);
currentMapFile.buildings[currentMapFile.buildings.Count - 1] = b;
/* Add new entry to buildings ListBox */
buildingsListBox.Items.Add((buildingsListBox.Items.Count + 1).ToString("D2") + MapHeader.nameSeparator + buildIndexComboBox.Items[(int)b.modelID]);
buildingsListBox.SelectedIndex = buildingsListBox.Items.Count - 1;
/* Redraw scene with new building */
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
private void buildIndexComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (Helpers.HandlersDisabled || buildingsListBox.SelectedIndex < 0)
{
return;
}
Helpers.DisableHandlers();
buildingsListBox.Items[buildingsListBox.SelectedIndex] = (buildingsListBox.SelectedIndex + 1).ToString("D2") + MapHeader.nameSeparator + buildIndexComboBox.SelectedItem;
Helpers.EnableHandlers();
currentMapFile.buildings[buildingsListBox.SelectedIndex].modelID = (uint)buildIndexComboBox.SelectedIndex;
currentMapFile.buildings[buildingsListBox.SelectedIndex].LoadModelData(_parent.romInfo.GetBuildingModelsDirPath(interiorbldRadioButton.Checked));
MW_LoadModelTextures(currentMapFile.buildings[buildingsListBox.SelectedIndex].NSBMDFile, RomInfo.gameDirs[DirNames.buildingTextures].unpackedDir, buildTextureComboBox.SelectedIndex - 1);
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
private void buildingsListBox_SelectedIndexChanged(object sender, EventArgs e)
{
int buildingNumber = buildingsListBox.SelectedIndex;
if (Helpers.HandlersDisabled || buildingNumber < 0)
{
return;
}
Helpers.BackUpDisableHandler();
Helpers.DisableHandlers();
Building selected = currentMapFile.buildings[buildingNumber];
if (selected.NSBMDFile != null)
{
buildIndexComboBox.SelectedIndex = (int)selected.modelID;
xBuildUpDown.Value = selected.xPosition + (decimal)selected.xFraction / 65535;
yBuildUpDown.Value = selected.yPosition + (decimal)selected.yFraction / 65535;
zBuildUpDown.Value = selected.zPosition + (decimal)selected.zFraction / 65535;
xRotBuildUpDown.Value = selected.xRotation;
yRotBuildUpDown.Value = selected.yRotation;
zRotBuildUpDown.Value = selected.zRotation;
xRotDegBldUpDown.Value = (decimal)Building.U16ToDeg((ushort)xRotBuildUpDown.Value);
yRotDegBldUpDown.Value = (decimal)Building.U16ToDeg((ushort)yRotBuildUpDown.Value);
zRotDegBldUpDown.Value = (decimal)Building.U16ToDeg((ushort)zRotBuildUpDown.Value);
buildingWidthUpDown.Value = selected.width;
buildingHeightUpDown.Value = selected.height;
buildingLengthUpDown.Value = selected.length;
}
Helpers.RestoreDisableHandler();
}
private void xRotBuildUpDown_ValueChanged(object sender, EventArgs e)
{
int selection = buildingsListBox.SelectedIndex;
if (selection <= -1 || Helpers.HandlersDisabled)
{
return;
}
Helpers.DisableHandlers();
currentMapFile.buildings[selection].xRotation = (ushort)((int)xRotBuildUpDown.Value & ushort.MaxValue);
xRotDegBldUpDown.Value = (decimal)Building.U16ToDeg(currentMapFile.buildings[selection].xRotation);
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
Helpers.EnableHandlers();
}
private void yRotBuildUpDown_ValueChanged(object sender, EventArgs e)
{
int selection = buildingsListBox.SelectedIndex;
if (selection <= -1 || Helpers.HandlersDisabled)
{
return;
}
Helpers.DisableHandlers();
yRotDegBldUpDown.Value = (decimal)Building.U16ToDeg(currentMapFile.buildings[selection].yRotation = (ushort)((int)yRotBuildUpDown.Value & ushort.MaxValue));
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
Helpers.EnableHandlers();
}
private void zRotBuildUpDown_ValueChanged(object sender, EventArgs e)
{
int selection = buildingsListBox.SelectedIndex;
if (selection <= -1 || Helpers.HandlersDisabled)
{
return;
}
Helpers.DisableHandlers();
zRotDegBldUpDown.Value = (decimal)Building.U16ToDeg(currentMapFile.buildings[selection].zRotation = (ushort)((int)zRotBuildUpDown.Value & ushort.MaxValue));
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
Helpers.EnableHandlers();
}
private void xRotDegBldUpDown_ValueChanged(object sender, EventArgs e)
{
if (buildingsListBox.SelectedIndex <= -1 || Helpers.HandlersDisabled)
{
return;
}
Helpers.DisableHandlers();
currentMapFile.buildings[buildingsListBox.SelectedIndex].xRotation = (ushort)(xRotBuildUpDown.Value =
Building.DegToU16((float)xRotDegBldUpDown.Value));
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
Helpers.EnableHandlers();
}
private void yRotDegBldUpDown_ValueChanged(object sender, EventArgs e)
{
if (buildingsListBox.SelectedIndex <= -1 || Helpers.HandlersDisabled)
{
return;
}
Helpers.DisableHandlers();
currentMapFile.buildings[buildingsListBox.SelectedIndex].yRotation = (ushort)(yRotBuildUpDown.Value =
Building.DegToU16((float)yRotDegBldUpDown.Value));
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
Helpers.EnableHandlers();
}
private void zRotDegBldUpDown_ValueChanged(object sender, EventArgs e)
{
if (buildingsListBox.SelectedIndex <= -1 || Helpers.HandlersDisabled)
{
return;
}
Helpers.DisableHandlers();
currentMapFile.buildings[buildingsListBox.SelectedIndex].zRotation = (ushort)(zRotBuildUpDown.Value =
Building.DegToU16((float)zRotDegBldUpDown.Value));
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
Helpers.EnableHandlers();
}
private void buildingHeightUpDown_ValueChanged(object sender, EventArgs e)
{
if (buildingsListBox.SelectedIndex > -1)
{
currentMapFile.buildings[buildingsListBox.SelectedIndex].height = (uint)buildingHeightUpDown.Value;
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
}
private void buildingLengthUpDown_ValueChanged(object sender, EventArgs e)
{
if (buildingsListBox.SelectedIndex > -1)
{
currentMapFile.buildings[buildingsListBox.SelectedIndex].length = (uint)buildingLengthUpDown.Value;
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
}
private void buildingWidthUpDown_ValueChanged(object sender, EventArgs e)
{
if (buildingsListBox.SelectedIndex > -1)
{
currentMapFile.buildings[buildingsListBox.SelectedIndex].width = (uint)buildingWidthUpDown.Value;
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
}
private void exportBuildingsButton_Click(object sender, EventArgs e)
{
SaveFileDialog sf = new SaveFileDialog
{
Filter = MapFile.BuildingsFilter,
FileName = selectMapComboBox.SelectedItem.ToString()
};
if (sf.ShowDialog(this) != DialogResult.OK)
{
return;
}
File.WriteAllBytes(sf.FileName, currentMapFile.BuildingsToByteArray());
MessageBox.Show("Buildings exported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void importBuildingsButton_Click(object sender, EventArgs e)
{
OpenFileDialog ib = new OpenFileDialog
{
Filter = MapFile.BuildingsFilter
};
if (ib.ShowDialog(this) != DialogResult.OK)
{
return;
}
currentMapFile.ImportBuildings(File.ReadAllBytes(ib.FileName));
FillBuildingsBox();
if (buildingsListBox.Items.Count > 0) { buildingsListBox.SelectedIndex = 0; }
for (int i = 0; i < currentMapFile.buildings.Count; i++)
{
currentMapFile.buildings[i].LoadModelData(_parent.romInfo.GetBuildingModelsDirPath(interiorbldRadioButton.Checked)); // Load building nsbmd
MW_LoadModelTextures(currentMapFile.buildings[i].NSBMDFile, RomInfo.gameDirs[DirNames.buildingTextures].unpackedDir, buildTextureComboBox.SelectedIndex - 1); // Load building textures
}
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
MessageBox.Show("Buildings imported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void interiorRadioButton_CheckedChanged(object sender, EventArgs e)
{
Helpers.DisableHandlers();
int index = buildIndexComboBox.SelectedIndex;
buildIndexComboBox.Items.Clear();
/* Fill building models list */
updateBuildingListComboBox(interiorbldRadioButton.Checked);
FillBuildingsBox();
try
{
buildIndexComboBox.SelectedIndex = index;
}
catch (ArgumentOutOfRangeException)
{
buildIndexComboBox.SelectedIndex = 0;
currentMapFile.buildings[buildIndexComboBox.SelectedIndex].modelID = 0;
}
/* Load buildings nsbmd and textures for renderer into MapFile's building objects */
for (int i = 0; i < currentMapFile.buildings.Count; i++)
{
currentMapFile.buildings[i].LoadModelData(_parent.romInfo.GetBuildingModelsDirPath(interiorbldRadioButton.Checked)); // Load building nsbmd
MW_LoadModelTextures(currentMapFile.buildings[i].NSBMDFile, RomInfo.gameDirs[DirNames.buildingTextures].unpackedDir, buildTextureComboBox.SelectedIndex - 1); // Load building textures
}
/* Render the map */
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
Helpers.EnableHandlers();
}
private void removeBuildingButton_Click(object sender, EventArgs e)
{
int toRemoveListBoxID = buildingsListBox.SelectedIndex;
if (toRemoveListBoxID > -1)
{
Helpers.DisableHandlers();
/* Remove building object from list and the corresponding entry in the ListBox */
currentMapFile.buildings.RemoveAt(toRemoveListBoxID);
buildingsListBox.Items.RemoveAt(toRemoveListBoxID);
FillBuildingsBox(); // Update ListBox
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
Helpers.EnableHandlers();
if (buildingsListBox.Items.Count > 0)
{
if (toRemoveListBoxID > 0)
{
buildingsListBox.SelectedIndex = toRemoveListBoxID - 1;
}
else
{
buildingsListBox.SelectedIndex = 0;
}
}
}
}
private void xBuildUpDown_ValueChanged(object sender, EventArgs e)
{
if (Helpers.HandlersDisabled || buildingsListBox.SelectedIndex < 0)
{
return;
}
var wholePart = Math.Truncate(xBuildUpDown.Value);
var decPart = xBuildUpDown.Value - wholePart;
if (decPart < 0)
{
decPart += 1;
wholePart -= 1;
}
currentMapFile.buildings[buildingsListBox.SelectedIndex].xPosition = (short)wholePart;
currentMapFile.buildings[buildingsListBox.SelectedIndex].xFraction = (ushort)(decPart * 65535);
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
private void zBuildUpDown_ValueChanged(object sender, EventArgs e)
{
if (Helpers.HandlersDisabled || buildingsListBox.SelectedIndex < 0)
return;
var wholePart = Math.Truncate(zBuildUpDown.Value);
var decPart = zBuildUpDown.Value - wholePart;
if (decPart < 0)
{
decPart += 1;
wholePart -= 1;
}
currentMapFile.buildings[buildingsListBox.SelectedIndex].zPosition = (short)wholePart;
currentMapFile.buildings[buildingsListBox.SelectedIndex].zFraction = (ushort)(decPart * 65535);
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
private void yBuildUpDown_ValueChanged(object sender, EventArgs e)
{
if (Helpers.HandlersDisabled || buildingsListBox.SelectedIndex < 0)
return;
var wholePart = Math.Truncate(yBuildUpDown.Value);
var decPart = yBuildUpDown.Value - wholePart;
if (decPart < 0)
{
decPart += 1;
wholePart -= 1;
}
currentMapFile.buildings[buildingsListBox.SelectedIndex].yPosition = (short)wholePart;
currentMapFile.buildings[buildingsListBox.SelectedIndex].yFraction = (ushort)(decPart * 65535);
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
}
#endregion
#region Movement Permissions Editor
#region Subroutines
private Bitmap GrabMapScreenshot(int width, int height)
{
Bitmap bmp = new Bitmap(width, height);
System.Drawing.Imaging.BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
Gl.glReadPixels(0, 0, width, height, Gl.GL_BGR, Gl.GL_UNSIGNED_BYTE, data.Scan0);
bmp.UnlockBits(data);
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
return bmp;
}
private void DrawCollisionGrid()
{
Bitmap mainBm = new Bitmap(608, 608);
using (Graphics gMain = Graphics.FromImage(mainBm))
{
for (int i = 0; i < 32; i++)
{
for (int j = 0; j < 32; j++)
{
PrepareCollisionPainterGraphics(currentMapFile.collisions[i, j]);
/* Draw collision on the main grid */
mainCell = new Rectangle(19 * j, 19 * i, 19, 19);
gMain.DrawRectangle(paintPen, mainCell);
gMain.FillRectangle(paintBrush, mainCell);
}
}
}
movPictureBox.Image = mainBm;
movPictureBox.Invalidate();
}
private void DrawSmallCollision()
{
Bitmap smallBm = new Bitmap(100, 100);
using (Graphics gSmall = Graphics.FromImage(smallBm))
{
for (int i = 0; i < 32; i++)
{
for (int j = 0; j < 32; j++)
{
PrepareCollisionPainterGraphics(currentMapFile.collisions[i, j]);
/* Draw collision on the small image */
smallCell = new Rectangle(3 * j, 3 * i, 3, 3);
gSmall.DrawRectangle(paintPen, smallCell);
gSmall.FillRectangle(paintBrush, smallCell);
}
}
}
collisionPictureBox.Image = smallBm;
collisionPictureBox.Invalidate();
}
private void DrawTypeGrid()
{
Bitmap mainBm = new Bitmap(608, 608);
using (Graphics gMain = Graphics.FromImage(mainBm))
{
for (int i = 0; i < 32; i++)
{
for (int j = 0; j < 32; j++)
{
PrepareTypePainterGraphics(currentMapFile.types[i, j]);
/* Draw cell with color */
mainCell = new Rectangle(19 * j, 19 * i, 19, 19);
gMain.DrawRectangle(paintPen, mainCell);
gMain.FillRectangle(paintBrush, mainCell);
/* Draw byte on cell */
StringFormat sf = new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
};
gMain.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
gMain.DrawString(currentMapFile.types[i, j].ToString("X2"), textFont, textBrush, mainCell, sf);
}
}
}
movPictureBox.Image = mainBm;
movPictureBox.Invalidate();
}
private void DrawSmallTypeCollision()
{
Bitmap smallBm = new Bitmap(100, 100);
using (Graphics gSmall = Graphics.FromImage(smallBm))
{
for (int i = 0; i < 32; i++)
{
for (int j = 0; j < 32; j++)
{
PrepareTypePainterGraphics(currentMapFile.types[i, j]);
/* Draw collision on the small image */
smallCell = new Rectangle(3 * j, 3 * i, 3, 3);
gSmall.DrawRectangle(paintPen, smallCell);
gSmall.FillRectangle(paintBrush, smallCell);
}
}
}
typePictureBox.Image = smallBm;
typePictureBox.Invalidate();
}
private void scanUsedCollisionTypesButton_Click(object sender, EventArgs e)
{
SortedSet<byte> allUsed = FindUsedCollisions();
List<byte> lst = allUsed.ToList();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < allUsed.Count; i++)
{
sb.Append("0x");
sb.Append(lst[i].ToString("X2"));
if (i != allUsed.Count - 1)
{
sb.Append(", ");
}
}
string report = sb.ToString();
MessageBox.Show($"This report has been copied to the clipboard as well, for your convenience.\n\nUsed types (in all Map BINs): \n{report}", "Used collision types report", MessageBoxButtons.OK, MessageBoxIcon.Information);
Clipboard.SetText(report);
}
private SortedSet<byte> FindUsedCollisions()
{
int mapCount = _parent.romInfo.GetMapCount();
SortedSet<byte> allUsedTypes = new SortedSet<byte>();
for (int i = 0; i < mapCount; i++)
{
allUsedTypes.UnionWith(new MapFile(i, gameFamily, false, false).GetUsedTypes());
}
return allUsedTypes;
}
private SortedSet<byte> FindUnusedCollisions()
{
int mapCount = _parent.romInfo.GetMapCount();
SortedSet<byte> allUnusedTypes = new SortedSet<byte>();
for (int i = 0; i <= byte.MaxValue; i++)
{
allUnusedTypes.Add((byte)i);
}
allUnusedTypes.ExceptWith(FindUsedCollisions());
return allUnusedTypes;
}
private void EditCell(int xPosition, int yPosition)
{
try
{
mainCell = new Rectangle(xPosition * mapEditorSquareSize, yPosition * mapEditorSquareSize, mapEditorSquareSize, mapEditorSquareSize);
smallCell = new Rectangle(xPosition * 3, yPosition * 3, 3, 3);
using (Graphics mainG = Graphics.FromImage(movPictureBox.Image))
{
/* Draw new cell on main grid */
mainG.SetClip(mainCell);
mainG.Clear(Color.Transparent);
mainG.DrawRectangle(paintPen, mainCell);
mainG.FillRectangle(paintBrush, mainCell);
if (selectTypePanel.BackColor == Color.MidnightBlue)
{
sf = new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
};
mainG.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
mainG.DrawString(paintByte.ToString("X2"), textFont, textBrush, mainCell, sf);
}
}
if (selectCollisionPanel.BackColor == Color.MidnightBlue)
{
using (Graphics smallG = Graphics.FromImage(collisionPictureBox.Image))
{
/* Draw new cell on small grid */
smallG.SetClip(smallCell);
smallG.Clear(Color.Transparent);
smallG.DrawRectangle(paintPen, smallCell);
smallG.FillRectangle(paintBrush, smallCell);
}
currentMapFile.collisions[yPosition, xPosition] = paintByte;
collisionPictureBox.Invalidate();
}
else
{
using (Graphics smallG = Graphics.FromImage(typePictureBox.Image))
{
/* Draw new cell on small grid */
smallG.SetClip(smallCell);
smallG.Clear(Color.Transparent);
smallG.DrawRectangle(paintPen, smallCell);
smallG.FillRectangle(paintBrush, smallCell);
}
currentMapFile.types[yPosition, xPosition] = paintByte;
typePictureBox.Invalidate();
}
movPictureBox.Invalidate();
}
catch { return; }
}
private void FloodFillUtil(byte[,] screen, int x, int y, byte prevC, byte newC, int sizeX, int sizeY)
{
// Base cases
if (x < 0 || x >= sizeX || y < 0 || y >= sizeY)
{
return;
}
if (screen[y, x] != prevC)
{
return;
}
// Replace the color at (x, y)
screen[y, x] = newC;
// Recur for north, east, south and west
FloodFillUtil(screen, x + 1, y, prevC, newC, sizeX, sizeY);
FloodFillUtil(screen, x - 1, y, prevC, newC, sizeX, sizeY);
FloodFillUtil(screen, x, y + 1, prevC, newC, sizeX, sizeY);
FloodFillUtil(screen, x, y - 1, prevC, newC, sizeX, sizeY);
}
private void FloodFillCell(int x, int y)
{
byte toPaint = paintByte;
if (selectCollisionPanel.BackColor == Color.MidnightBlue)
{
if (currentMapFile.collisions[y, x] != paintByte)
{
FloodFillUtil(currentMapFile.collisions, x, y, currentMapFile.collisions[y, x], paintByte, 32, 32);
DrawCollisionGrid();
DrawSmallCollision();
PrepareCollisionPainterGraphics(paintByte);
}
}
else
{
if (currentMapFile.types[y, x] != paintByte)
{
FloodFillUtil(currentMapFile.types, x, y, currentMapFile.types[y, x], paintByte, 32, 32);
DrawTypeGrid();
DrawSmallTypeCollision();
PrepareTypePainterGraphics(paintByte);
}
}
/* Draw permissions in the small selection boxes */
}
private void RestorePainter()
{
if (selectCollisionPanel.BackColor == Color.MidnightBlue)
{
collisionPainterComboBox_SelectedIndexChange(null, null);
}
else if (collisionTypePainterComboBox.Enabled)
{
typePainterComboBox_SelectedIndexChanged(null, null);
}
else
{
typePainterUpDown_ValueChanged(null, null);
}
}
private void PrepareCollisionPainterGraphics(byte collisionValue)
{
switch (collisionValue)
{
case 0x01: // Snow
paintPen = new Pen(Color.FromArgb(Transparency, Color.Lavender));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Lavender));
break;
case 0x02: // Leaves
paintPen = new Pen(Color.FromArgb(Transparency, Color.ForestGreen));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.ForestGreen));
break;
case 0x04: // Grass
paintPen = new Pen(Color.FromArgb(Transparency, Color.LimeGreen));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.LimeGreen));
break;
case 0x06: // Stairs and ice
paintPen = new Pen(Color.FromArgb(Transparency, Color.PowderBlue));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.PowderBlue));
break;
case 0x07: // Metal
paintPen = new Pen(Color.FromArgb(Transparency, Color.Silver));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Silver));
break;
case 0x0A: // Stone
paintPen = new Pen(Color.FromArgb(Transparency, Color.DimGray));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.DimGray));
break;
case 0x0D: // Wood
paintPen = new Pen(Color.FromArgb(Transparency, Color.SaddleBrown));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.SaddleBrown));
break;
case 0x80:
paintPen = new Pen(Color.FromArgb(Transparency, Color.Red));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Red));
break;
default: // 0x00 - Walkeable
paintPen = new Pen(Color.FromArgb(32, Color.White));
paintBrush = new SolidBrush(Color.FromArgb(32, Color.White));
break;
}
}
private void PrepareTypePainterGraphics(byte typeValue)
{
switch (typeValue)
{
case 0x0:
paintPen = new Pen(Color.FromArgb(32, Color.White));
paintBrush = new SolidBrush(Color.FromArgb(32, Color.White));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x2:
paintPen = new Pen(Color.FromArgb(Transparency, Color.LimeGreen));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.LimeGreen));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x3:
paintPen = new Pen(Color.FromArgb(Transparency, Color.Green));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Green));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x6:
paintPen = new Pen(Color.FromArgb(128, Color.YellowGreen));
paintBrush = new SolidBrush(Color.FromArgb(128, Color.YellowGreen));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x7:
paintPen = new Pen(Color.FromArgb(128, Color.DarkGreen));
paintBrush = new SolidBrush(Color.FromArgb(128, Color.DarkGreen));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x8:
paintPen = new Pen(Color.FromArgb(128, Color.BurlyWood));
paintBrush = new SolidBrush(Color.FromArgb(128, Color.BurlyWood));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 8.65f);
break;
case 0x9:
paintPen = new Pen(Color.FromArgb(128, Color.SlateBlue));
paintBrush = new SolidBrush(Color.FromArgb(128, Color.SlateBlue));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0xA:
paintPen = new Pen(Color.FromArgb(128, Color.Tomato));
paintBrush = new SolidBrush(Color.FromArgb(128, Color.Tomato));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0xC:
paintPen = new Pen(Color.FromArgb(Transparency, Color.BurlyWood));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.BurlyWood));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 8.65f);
break;
case 0x10:
paintPen = new Pen(Color.FromArgb(Transparency, Color.SkyBlue));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.SkyBlue));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x13:
paintPen = new Pen(Color.FromArgb(Transparency, Color.SteelBlue));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.SteelBlue));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x15:
paintPen = new Pen(Color.FromArgb(Transparency, Color.RoyalBlue));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.RoyalBlue));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x16:
paintPen = new Pen(Color.FromArgb(Transparency, Color.LightSlateGray));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.LightSlateGray));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x20:
paintPen = new Pen(Color.FromArgb(Transparency, Color.Cyan));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Cyan));
textBrush = new SolidBrush(Color.Black);
textFont = new Font("Arial", 9.0f);
break;
case 0x21:
paintPen = new Pen(Color.FromArgb(Transparency, Color.PeachPuff));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.PeachPuff));
textBrush = new SolidBrush(Color.Black);
textFont = new Font("Arial", 9.0f);
break;
case 0x30:
case 0x31:
case 0x32:
case 0x33:
paintPen = new Pen(Color.FromArgb(Transparency, Color.Red));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Red));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x3C:
case 0x3D:
case 0x3E:
paintPen = new Pen(Color.FromArgb(0x7F654321));
paintBrush = new SolidBrush(Color.FromArgb(0x7F654321));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 8.65f);
break;
case 0x38:
case 0x39:
case 0x3A:
case 0x3B:
paintPen = new Pen(Color.FromArgb(Transparency, Color.Maroon));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Maroon));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 8.65f);
break;
case 0x40:
case 0x41:
case 0x42:
case 0x43:
paintPen = new Pen(Color.FromArgb(Transparency, Color.Gold));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Gold));
textBrush = new SolidBrush(Color.Black);
textFont = new Font("Arial", 9.0f);
break;
case 0x4B:
case 0x4C:
paintPen = new Pen(Color.FromArgb(Transparency, Color.Sienna));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Sienna));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 9.0f);
break;
case 0x5E:
paintPen = new Pen(Color.FromArgb(Transparency, Color.DarkOrchid));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.DarkOrchid));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 8.65f);
break;
case 0x5F:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x69:
paintPen = new Pen(Color.FromArgb(Transparency, Color.DarkOrchid));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.DarkOrchid));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 8.65f);
break;
case 0x6C:
case 0x6D:
case 0x6E:
case 0x6F:
paintPen = new Pen(Color.FromArgb(Transparency, Color.DarkOrchid));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.DarkOrchid));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 8.65f);
break;
case 0xA1:
case 0xA2:
case 0xA3:
paintPen = new Pen(Color.FromArgb(Transparency, Color.Honeydew));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Honeydew));
textBrush = new SolidBrush(Color.Black);
textFont = new Font("Arial", 8.65f);
break;
case 0xA4:
paintPen = new Pen(Color.FromArgb(Transparency, Color.Peru));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.Peru));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 8.65f);
break;
case 0xA6:
paintPen = new Pen(Color.FromArgb(Transparency, Color.SeaGreen));
paintBrush = new SolidBrush(Color.FromArgb(Transparency, Color.SeaGreen));
textBrush = new SolidBrush(Color.White);
textFont = new Font("Arial", 8.65f);
break;
default:
paintPen = new Pen(Color.FromArgb(32, Color.White));
paintBrush = new SolidBrush(Color.FromArgb(32, Color.White));
textBrush = new SolidBrush(Color.Black);
textFont = new Font("Arial", 8.65f);
break;
}
}
#endregion
private void clearCurrentButton_Click(object sender, EventArgs e)
{
PictureBox smallBox = selectCollisionPanel.BackColor == Color.MidnightBlue ? collisionPictureBox : typePictureBox;
using (Graphics smallG = Graphics.FromImage(smallBox.Image))
{
using (Graphics mainG = Graphics.FromImage(movPictureBox.Image))
{
smallG.Clear(Color.Transparent);
mainG.Clear(Color.Transparent);
PrepareCollisionPainterGraphics(0x0);
for (int i = 0; i < 32; i++)
{
for (int j = 0; j < 32; j++)
{
mainCell = new Rectangle(19 * j, 19 * i, 19, 19);
mainG.DrawRectangle(paintPen, mainCell);
mainG.FillRectangle(paintBrush, mainCell);
}
}
}
}
if (selectCollisionPanel.BackColor == Color.MidnightBlue)
{
currentMapFile.collisions = new byte[32, 32]; // Set all collision bytes to clear (0x0)
}
else
{
currentMapFile.types = new byte[32, 32]; // Set all type bytes to clear (0x0)
}
movPictureBox.Invalidate(); // Refresh main image
smallBox.Invalidate();
RestorePainter();
}
public string[] GetBuildingsList(bool interior)
{
List<string> names = new List<string>();
string path = _parent.romInfo.GetBuildingModelsDirPath(interior);
int buildModelsCount = Directory.GetFiles(path).Length;
for (int i = 0; i < buildModelsCount; i++)
{
using (DSUtils.EasyReader reader = new DSUtils.EasyReader(path + "\\" + i.ToString("D4"), 0x38))
{
string nsbmdName = Encoding.UTF8.GetString(reader.ReadBytes(16)).TrimEnd();
names.Add(nsbmdName);
}
}
return names.ToArray();
}
public void updateBuildingListComboBox(bool interior)
{
string[] bldList = GetBuildingsList(interior);
buildIndexComboBox.Items.Clear();
for (int i = 0; i < bldList.Length; i++)
{
buildIndexComboBox.Items.Add("[" + i + "] " + bldList[i]);
}
_parent.toolStripProgressBar.Value++;
}
private void locateCurrentMapBin_Click(object sender, EventArgs e)
{
Helpers.ExplorerSelect(Path.Combine(gameDirs[DirNames.maps].unpackedDir, selectMapComboBox.SelectedIndex.ToString("D4")));
}
private void collisionPictureBox_Click(object sender, EventArgs e)
{
selectTypePanel.BackColor = Color.Transparent;
typeGroupBox.Enabled = false;
selectCollisionPanel.BackColor = Color.MidnightBlue;
collisionGroupBox.Enabled = true;
DrawCollisionGrid();
RestorePainter();
}
private void exportMovButton_Click(object sender, EventArgs e)
{
SaveFileDialog em = new SaveFileDialog
{
Filter = MapFile.MovepermsFilter,
FileName = selectMapComboBox.SelectedItem.ToString()
};
if (em.ShowDialog(this) != DialogResult.OK)
{
return;
}
File.WriteAllBytes(em.FileName, currentMapFile.CollisionsToByteArray());
MessageBox.Show("Permissions exported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void importMovButton_Click(object sender, EventArgs e)
{
OpenFileDialog ip = new OpenFileDialog
{
Filter = MapFile.MovepermsFilter
};
if (ip.ShowDialog(this) != DialogResult.OK)
{
return;
}
currentMapFile.ImportPermissions(File.ReadAllBytes(ip.FileName));
DrawSmallCollision();
DrawSmallTypeCollision();
if (selectCollisionPanel.BackColor == Color.MidnightBlue)
{
DrawCollisionGrid();
}
else
{
DrawTypeGrid();
}
RestorePainter();
MessageBox.Show("Permissions imported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void movPictureBox_Click(object sender, EventArgs e)
{
MouseEventArgs mea = (MouseEventArgs)e;
int xCoord = movPictureBox.PointToClient(MousePosition).X / mapEditorSquareSize;
int yCoord = movPictureBox.PointToClient(MousePosition).Y / mapEditorSquareSize;
if (mea.Button == MouseButtons.Middle)
{
FloodFillCell(xCoord, yCoord);
}
else if (mea.Button == MouseButtons.Left)
{
EditCell(xCoord, yCoord);
}
else
{
if (selectCollisionPanel.BackColor == Color.MidnightBlue)
{
byte newValue = currentMapFile.collisions[yCoord, xCoord];
updateCollisions(newValue);
}
else
{
byte newValue = currentMapFile.types[yCoord, xCoord];
typePainterUpDown.Value = newValue;
updateTypeCollisions(newValue);
}
;
}
}
private void movPictureBox_MouseMove(object sender, MouseEventArgs e)
{
if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left)
{
EditCell(e.Location.X / mapEditorSquareSize, e.Location.Y / mapEditorSquareSize);
}
}
private void collisionPainterComboBox_SelectedIndexChange(object sender, EventArgs e)
{
byte? collisionByte = StringToCollisionByte((string)collisionPainterComboBox.SelectedItem);
if (collisionByte != null)
{
updateCollisions((byte)collisionByte);
}
}
private void typePainterComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
byte? collisionByte = StringToCollisionByte((string)collisionTypePainterComboBox.SelectedItem);
if (collisionByte != null)
{
updateTypeCollisions((byte)collisionByte);
}
}
private byte? StringToCollisionByte(string selectedItem)
{
byte? result;
try
{
result = Convert.ToByte(selectedItem.Substring(1, 2), 16);
}
catch (FormatException)
{
AppLogger.Error("Format incompatible");
result = null;
}
return result;
}
private void typePainterUpDown_ValueChanged(object sender, EventArgs e)
{
updateTypeCollisions((byte)typePainterUpDown.Value);
}
private void updateCollisions(byte typeValue)
{
PrepareCollisionPainterGraphics(typeValue);
paintByte = (byte)typeValue;
sf = new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
};
using (Graphics g = Graphics.FromImage(collisionPainterPictureBox.Image))
{
g.Clear(Color.FromArgb(255, paintBrush.Color));
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
g.DrawString(typeValue.ToString("X2"), new Font("Microsoft Sans Serif", 24), textBrush, painterBox, sf);
}
if (PokeDatabase.System.MapCollisionPainters.TryGetValue(typeValue, out string dictResult))
{
collisionPainterComboBox.SelectedItem = dictResult;
}
collisionPainterPictureBox.Invalidate();
}
private void updateTypeCollisions(byte typeValue)
{
PrepareTypePainterGraphics(typeValue);
paintByte = typeValue;
sf = new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
};
using (Graphics g = Graphics.FromImage(typePainterPictureBox.Image))
{
g.Clear(Color.FromArgb(255, paintBrush.Color));
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
g.DrawString(typeValue.ToString("X2"), new Font("Microsoft Sans Serif", 24), textBrush, painterBox, sf);
}
if (PokeDatabase.System.MapCollisionTypePainters.TryGetValue(typeValue, out string dictResult))
{
collisionTypePainterComboBox.SelectedItem = dictResult;
}
else
{
valueTypeRadioButton.Checked = true;
typePainterUpDown.Value = typeValue;
}
typePainterPictureBox.Invalidate();
}
private void typePictureBox_Click(object sender, EventArgs e)
{
selectCollisionPanel.BackColor = Color.Transparent;
collisionGroupBox.Enabled = false;
selectTypePanel.BackColor = Color.MidnightBlue;
typeGroupBox.Enabled = true;
DrawTypeGrid();
RestorePainter();
}
private void typesRadioButton_CheckedChanged(object sender, EventArgs e)
{
if (knownTypesRadioButton.Checked)
{
typePainterUpDown.Enabled = false;
collisionTypePainterComboBox.Enabled = true;
typePainterComboBox_SelectedIndexChanged(null, null);
}
}
private void valueTypeRadioButton_CheckedChanged(object sender, EventArgs e)
{
if (valueTypeRadioButton.Checked)
{
collisionTypePainterComboBox.Enabled = false;
typePainterUpDown.Enabled = true;
typePainterUpDown_ValueChanged(null, null);
}
}
#endregion
#region 3D Model Editor
public const ushort MAPMODEL_CRITICALSIZE = 61000;
private void importMapButton_Click(object sender, EventArgs e)
{
OpenFileDialog im = new OpenFileDialog
{
Filter = MapFile.NSBMDFilter,
InitialDirectory = SettingsManager.Settings.mapImportStarterPoint
};
if (im.ShowDialog(this) != DialogResult.OK)
{
return;
}
currentMapFile.LoadMapModel(DSUtils.ReadFromFile(im.FileName));
if (mapTextureComboBox.SelectedIndex > 0)
{
MW_LoadModelTextures(currentMapFile.mapModel, RomInfo.gameDirs[DirNames.mapTextures].unpackedDir, mapTextureComboBox.SelectedIndex - 1);
}
Helpers.RenderMap(ref mapRenderer, ref buildingsRenderer, ref currentMapFile, ang, dist, elev, perspective, mapOpenGlControl.Width, mapOpenGlControl.Height, mapTexturesOn, bldTexturesOn);
modelSizeLBL.Text = currentMapFile.mapModelData.Length.ToString() + " B";
string message;
string title;
if (currentMapFile.mapModelData.Length > MAPMODEL_CRITICALSIZE)
{
message = "You imported a map model that exceeds " + MAPMODEL_CRITICALSIZE + " bytes." + Environment.NewLine
+ "This may lead to unexpected behavior in game.";
title = "Imported correctly, but...";
}
else
{
message = "Map model imported successfully!";
title = "Success!";
}
MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void exportMapButton_Click(object sender, EventArgs e)
{
SaveFileDialog em = new SaveFileDialog
{
FileName = selectMapComboBox.SelectedItem.ToString()
};
byte[] modelToWrite;
if (embedTexturesInMapModelCheckBox.Checked)
{ /* Textured NSBMD file */
em.Filter = MapFile.TexturedNSBMDFilter;
if (em.ShowDialog(this) != DialogResult.OK)
{
return;
}
string texturePath = RomInfo.gameDirs[DirNames.mapTextures].unpackedDir + "\\" + (mapTextureComboBox.SelectedIndex - 1).ToString("D4");
byte[] texturesToEmbed = File.ReadAllBytes(texturePath);
modelToWrite = NSBUtils.BuildNSBMDwithTextures(currentMapFile.mapModelData, texturesToEmbed);
}
else
{ /* Untextured NSBMD file */
em.Filter = MapFile.UntexturedNSBMDFilter;
if (em.ShowDialog(this) != DialogResult.OK)
{
return;
}
modelToWrite = currentMapFile.mapModelData;
}
File.WriteAllBytes(em.FileName, modelToWrite);
MessageBox.Show("Map model exported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void daeExportButton_Click(object sender, EventArgs e)
{
ModelUtils.ModelToDAE(
modelName: selectMapComboBox.SelectedItem.ToString().TrimEnd('\0'),
modelData: currentMapFile.mapModelData,
textureData: mapTextureComboBox.SelectedIndex < 0 ? null : File.ReadAllBytes(RomInfo.gameDirs[DirNames.mapTextures].unpackedDir + "\\" + (mapTextureComboBox.SelectedIndex - 1).ToString("D4"))
);
}
private void glbExportButton_Click(object sender, EventArgs e)
{
ModelUtils.ModelToGLB(
modelName: selectMapComboBox.SelectedItem.ToString().TrimEnd('\0'),
modelData: currentMapFile.mapModelData,
textureData: mapTextureComboBox.SelectedIndex < 0 ? null : File.ReadAllBytes(RomInfo.gameDirs[DirNames.mapTextures].unpackedDir + "\\" + (mapTextureComboBox.SelectedIndex - 1).ToString("D4"))
);
}
#endregion
#region BDHC I/O
private void bdhcImportButton_Click(object sender, EventArgs e)
{
OpenFileDialog it = new OpenFileDialog()
{
Filter = RomInfo.gameFamily == GameFamilies.DP ? MapFile.BDHCFilter : MapFile.BDHCamFilter
};
if (it.ShowDialog(this) != DialogResult.OK)
{
return;
}
currentMapFile.ImportTerrain(File.ReadAllBytes(it.FileName));
terrainSizeLBL.Text = currentMapFile.bdhc.Length.ToString() + " B";
MessageBox.Show("Terrain settings imported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void bdhcExportButton_Click(object sender, EventArgs e)
{
SaveFileDialog sf = new SaveFileDialog
{
FileName = selectMapComboBox.SelectedItem.ToString(),
Filter = RomInfo.gameFamily == GameFamilies.DP ? MapFile.BDHCFilter : MapFile.BDHCamFilter
};
if (sf.ShowDialog(this) != DialogResult.OK)
{
return;
}
File.WriteAllBytes(sf.FileName, currentMapFile.bdhc);
terrainSizeLBL.Text = currentMapFile.bdhc.Length.ToString() + " B";
MessageBox.Show("Terrain settings exported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
#endregion
#region Soundplates I/O
private void soundPlatesImportButton_Click(object sender, EventArgs e)
{
OpenFileDialog it = new OpenFileDialog
{
Filter = MapFile.BGSFilter
};
if (it.ShowDialog(this) != DialogResult.OK)
{
return;
}
currentMapFile.ImportSoundPlates(File.ReadAllBytes(it.FileName));
BGSSizeLBL.Text = currentMapFile.bgs.Length.ToString() + " B";
MessageBox.Show("BackGround Sound data imported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void soundPlatesExportButton_Click(object sender, EventArgs e)
{
SaveFileDialog sf = new SaveFileDialog
{
Filter = MapFile.BGSFilter,
FileName = selectMapComboBox.SelectedItem.ToString()
};
if (sf.ShowDialog(this) != DialogResult.OK)
{
return;
}
File.WriteAllBytes(sf.FileName, currentMapFile.bgs);
BGSSizeLBL.Text = currentMapFile.bgs.Length.ToString() + " B";
MessageBox.Show("BackGround Sound data exported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void soundPlatesBlankButton_Click(object sender, EventArgs e)
{
currentMapFile.bgs = MapFile.blankBGS;
BGSSizeLBL.Text = currentMapFile.bgs.Length.ToString() + " B";
MessageBox.Show("BackGround Sound data successfull blanked.\nRemember to save the current map file.", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
#endregion
#endregion
private void mapOpenGlControl_Load(object sender, EventArgs e)
{
mapOpenGlControl.InitializeContexts();
}
}
}