CodeWalker/MapForm.cs
2017-09-21 20:33:05 +10:00

1207 lines
38 KiB
C#

using SlimDX;
using SlimDX.Direct3D9;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CodeWalker
{
public partial class MapForm : Form
{
Vector3 TargetViewCenter = new Vector3(0.0f);
Vector3 CurrentViewCenter = new Vector3(0.0f);
float TargetZoom = 1.0f;
float CurrentZoom = 1.0f;
volatile bool LoadingImages = false;
List<MapImage> Images;
MapImage CurrentMap = null;
List<MapIcon> Icons;
MapIcon MarkerIcon = null;
MapIcon LocatorIcon = null;
MapMarker LocatorMarker = null;
MapMarker GrabbedMarker = null;
MapMarker SelectedMarker = null;
MapMarker MousedMarker = null;
List<MapMarker> Markers = new List<MapMarker>();
List<MapMarker> RenderMarkers = new List<MapMarker>();
bool Resizing = false;
bool MouseButtonDown = false;
Point MouseDownPoint;
Point MouseLastPoint;
volatile bool NeedsUpdate = false;
Direct3D d3d = null;
Device device = null;
Sprite sprite = null;
Stopwatch FrameTimer = new Stopwatch();
Size OldSize;
public MapForm()
{
InitializeComponent();
Icons = new List<MapIcon>();
AddIcon("Google Marker", "icon_google_marker_64x64.png", 64, 64, 11.0f, 40.0f, 1.0f);
AddIcon("Glokon Marker", "icon_glokon_normal_32x32.png", 32, 32, 11.0f, 32.0f, 1.0f);
AddIcon("Glokon Debug", "icon_glokon_debug_32x32.png", 32, 32, 11.5f, 32.0f, 1.0f);
MarkerIcon = Icons[1];
LocatorIcon = Icons[2];
foreach (MapIcon icon in Icons)
{
MarkerStyleComboBox.Items.Add(icon);
LocatorStyleComboBox.Items.Add(icon);
}
MarkerStyleComboBox.SelectedItem = MarkerIcon;
LocatorStyleComboBox.SelectedItem = LocatorIcon;
LocatorMarker = new MapMarker();
LocatorMarker.Icon = LocatorIcon;
LocatorMarker.IsMovable = true;
////for google map calibration...
//var game_1_x = 1972.606; //var map_1_lng = -60.8258056640625;
//var game_1_y = 3817.044; //var map_1_lat = 72.06379257078102;
//var game_2_x = -1154.11; //var map_2_lng = -72.1417236328125;
//var game_2_y = -2715.203; //var map_2_lat = 48.41572128171852;
////reference point:
//501.4398, 5603.9600, 795.9738, 0x4CC3BAFC, cs1_10_redeye
//origin in 8192x8192 textures is at approx:
//3755.2, 5525.5
float ox = 3755.2f;
float oy = 5525.5f;
float uptx = 1.517952f; //this seems pretty close...
float upty = -1.517952f;
Images = new List<MapImage>();
AddImage("Satellite", "gtav_satellite_8192x8192.jpg", 8192, 8192, ox, oy, uptx, upty);
AddImage("Roads", "gtav_roadmap_8192x8192.jpg", 8192, 8192, ox, oy, uptx, upty);
AddImage("Atlas", "gtav_atlas_8192x8192.jpg", 8192, 8192, ox, oy, uptx, upty);
foreach (MapImage mi in Images)
{
MapComboBox.Items.Add(mi);
}
InitializeDevice();
if (Images.Count > 0)
{
MapImage mi = Images[0];
MapComboBox.SelectedItem = mi;
TargetViewCenter = mi.Origin;
CurrentViewCenter = mi.Origin;
}
this.MouseWheel += MapForm_MouseMove;
FrameTimer.Restart();
SlimDX.Windows.MessagePump.Run(this, new SlimDX.Windows.MainLoop(SlimDX_Render));
}
private void MapForm_FormClosing(object sender, FormClosingEventArgs e)
{
DisposeDevice();
if (d3d != null)
{
d3d.Dispose();
d3d = null;
}
}
public void InitializeDevice()
{
if (WindowState == FormWindowState.Minimized) return;
PresentParameters presentParams = new PresentParameters
{
BackBufferWidth = ClientSize.Width,
BackBufferHeight = ClientSize.Height,
DeviceWindowHandle = Handle,
PresentFlags = PresentFlags.None,
Multisample = MultisampleType.None,
BackBufferCount = 0,
PresentationInterval = PresentInterval.One, // VSYNC ON
SwapEffect = SwapEffect.Discard,
BackBufferFormat = Format.X8R8G8B8,
Windowed = true,
EnableAutoDepthStencil = false,
};
if (d3d == null)
{
d3d = new Direct3D();
}
device = new Device(d3d, 0, DeviceType.Hardware, Handle, CreateFlags.HardwareVertexProcessing, presentParams);
device.Viewport = new Viewport(0, 0, ClientSize.Width, ClientSize.Height);
sprite = new Sprite(device);
if (Icons != null)
{
foreach (MapIcon icon in Icons)
{
LoadIconTexture(icon);
}
}
if ((CurrentMap != null) && (CurrentMap.Tex == null))
{
LoadImageTexture(CurrentMap);
}
}
public void DisposeDevice()
{
if (device == null) return;
if (Icons != null)
{
foreach (MapIcon icon in Icons)
{
if (icon.Tex != null)
{
icon.Tex.Dispose();
icon.Tex = null;
}
}
}
foreach (MapImage img in Images)
{
if (img.Tex != null)
{
img.Tex.Dispose();
img.Tex = null;
}
}
if ((CurrentMap != null) && (CurrentMap.Tex != null))
{
CurrentMap.Tex.Dispose();
CurrentMap.Tex = null;
}
sprite.Dispose();
sprite = null;
device.Dispose();
device = null;
}
private void HandleWindowResize()
{
DisposeDevice();
InitializeDevice(); //this really shouldn't be necessary!
//sprite.Dispose();
//sprite = null;
//device.Reset();
//sprite = new Sprite(device);
}
private void MapForm_ResizeBegin(object sender, EventArgs e)
{
OldSize = Size;
Resizing = true;
}
private void MapForm_ResizeEnd(object sender, EventArgs e)
{
Resizing = false;
if ((OldSize != Size) && (!LoadingImages))
{
HandleWindowResize();
}
}
private void MapForm_SizeChanged(object sender, EventArgs e)
{
}
private void MapForm_ClientSizeChanged(object sender, EventArgs e)
{
if ((!Resizing) && (!LoadingImages))
{
HandleWindowResize();
}
}
private void MapForm_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
MouseButtonDown = true;
}
MouseDownPoint = e.Location;
MouseLastPoint = MouseDownPoint;
if (MouseButtonDown)
{
if (MousedMarker != null)
{
if (MousedMarker.IsMovable)
{
GrabbedMarker = MousedMarker;
}
else
{
SelectedMarker = MousedMarker;
SelectionNameTextBox.Text = SelectedMarker.Name;
SelectionPositionTextBox.Text = SelectedMarker.Get3DWorldPosString();
UpdateSelectionPanel();
SelectionPanel.Visible = true;
}
}
else
{
GrabbedMarker = null;
//SelectedMarker = null;
//SelectionPanel.Visible = false;
}
}
}
private void MapForm_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
MouseButtonDown = false;
GrabbedMarker = null;
if ((e.Location == MouseDownPoint) && (MousedMarker == null))
{
//was clicked. but not on a marker... deselect and hide the panel
SelectedMarker = null;
SelectionPanel.Visible = false;
}
}
}
private void MapForm_MouseMove(object sender, MouseEventArgs e)
{
if (e.Delta != 0)
{
float zoomfac = 1.0f + 0.1f*((float)ZoomSpeedUpDown.Value);
float oldzoom = TargetZoom;
float newzoom = oldzoom * (e.Delta > 0 ? zoomfac : 1.0f / zoomfac);
if (newzoom < 1e-2f) newzoom = 1e-2f;
if (newzoom > 1e4f) newzoom = 1e4f;
//figure out the new target center based on current mouse pos
float w = ClientSize.Width;
float h = ClientSize.Height;
float mx = MouseLastPoint.X - w * 0.5f;
float my = MouseLastPoint.Y - h * 0.5f;
Vector3 mpold = new Vector3(mx, my, 0.0f) / oldzoom;
Vector3 mpnew = new Vector3(mx, my, 0.0f) / newzoom;
Vector3 mpdelt = mpnew - mpold;
TargetViewCenter -= mpdelt;
TargetZoom = newzoom;
NeedsUpdate = true;
}
if (MouseButtonDown)
{
float dx = (e.X - MouseLastPoint.X) / CurrentZoom;
float dy = (e.Y - MouseLastPoint.Y) / CurrentZoom;
if (GrabbedMarker == null)
{
//pan the view.
TargetViewCenter.X -= dx;
TargetViewCenter.Y -= dy;
NeedsUpdate = true;
}
else
{
//move the grabbed marker...
float uptx = (CurrentMap != null) ? CurrentMap.UnitsPerTexelX : 1.0f;
float upty = (CurrentMap != null) ? CurrentMap.UnitsPerTexelY : 1.0f;
Vector3 wpos = GrabbedMarker.WorldPos;
wpos.X += dx*uptx;
wpos.Y += dy*upty;
GrabbedMarker.WorldPos = wpos;
UpdateMarkerTexturePos(GrabbedMarker);
if (GrabbedMarker == LocatorMarker)
{
LocateTextBox.Text = LocatorMarker.ToString();
WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString();
TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString();
}
}
}
if (NeedsUpdate)
{
//limit to the texture.
float tvcmaxx = 8192.0f;
float tvcminx = 0.0f;
float tvcmaxy = 8192.0f;
float tvcminy = 0.0f;
if (!((TargetViewCenter.X > tvcmaxx) && (TargetViewCenter.X < tvcminx)))
{
if (TargetViewCenter.X > tvcmaxx) TargetViewCenter.X = tvcmaxx;
if (TargetViewCenter.X < tvcminx) TargetViewCenter.X = tvcminx;
}
if (!((TargetViewCenter.Y > tvcmaxy) && (TargetViewCenter.Y < tvcminy)))
{
if (TargetViewCenter.Y > tvcmaxy) TargetViewCenter.Y = tvcmaxy;
if (TargetViewCenter.Y < tvcminy) TargetViewCenter.Y = tvcminy;
}
}
MouseLastPoint = e.Location;
MousedMarker = FindMousedMarker();
if (MousedMarker != null)
{
if (MousedMarker.IsMovable)
{
Cursor = Cursors.SizeAll;
}
else
{
Cursor = Cursors.Hand;
}
}
else
{
Cursor = Cursors.Default;
}
}
private void SlimDX_Render()
{
if (device == null)
{
return;
}
if (LoadingImages)
{
return;
}
device.Clear(ClearFlags.Target, new Color4(BackColor), 1.0f, 0);
device.BeginScene();
device.SetRenderState(RenderState.AlphaBlendEnable, true);
device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha);
if (NeedsUpdate)
{
}
if ((CurrentMap != null) && (CurrentMap.Tex != null))
{
float smooth = 1.0f - (((float)SmoothingUpDown.Value)*0.9f);
float elapsed = (float)Math.Min(FrameTimer.Elapsed.TotalSeconds, 0.1);
CurrentZoom = CurrentZoom + (TargetZoom - CurrentZoom) * smooth;
CurrentViewCenter = CurrentViewCenter + (TargetViewCenter - CurrentViewCenter) * smooth;
float w = ClientSize.Width;
float h = ClientSize.Height;
Matrix scale = Matrix.Scaling(CurrentZoom, CurrentZoom, 0.0f);
Matrix trans = Matrix.Translation(-CurrentViewCenter);
Matrix offset = Matrix.Translation(w * 0.5f, h * 0.5f, 0.0f);
Matrix matrix = Matrix.Multiply(Matrix.Multiply(trans, scale), offset);
sprite.Begin(SpriteFlags.None);
sprite.Transform = matrix;
sprite.Draw(CurrentMap.Tex, Color.White);
sprite.End();
sprite.Begin(SpriteFlags.None);
sprite.Transform = Matrix.Identity;
//sort by Y to make markers look correct
RenderMarkers.Clear();
RenderMarkers.AddRange(Markers);
RenderMarkers.Sort((m1, m2) => m1.TexturePos.Y.CompareTo(m2.TexturePos.Y));
//draw all the markers
foreach (MapMarker m in RenderMarkers)
{
if ((m.Icon != null) && (m.Icon.Tex != null))
{
UpdateMarkerScreenPos(m);
sprite.Transform = GetMarkerRenderMatrix(m);
sprite.Draw(m.Icon.Tex, Color.White);
}
}
//draw the locator marker
MapIcon locic = LocatorMarker.Icon;
if ((ShowLocatorCheckBox.Checked) && (locic != null) && (locic.Tex != null))
{
UpdateMarkerScreenPos(LocatorMarker);
sprite.Transform = GetMarkerRenderMatrix(LocatorMarker);
sprite.Draw(locic.Tex, Color.White);
}
sprite.End();
}
device.EndScene();
device.Present();
if (SelectedMarker != null)
{
UpdateSelectionPanel();
}
FrameTimer.Restart();
}
private void UpdateSelectionPanel()
{
int ox = -90;
int oy = -76;
int px = (int)Math.Round(SelectedMarker.ScreenPos.X, MidpointRounding.AwayFromZero) + ox;
int py = (int)Math.Round(SelectedMarker.ScreenPos.Y, MidpointRounding.AwayFromZero) + oy;
int sx = SelectionPanel.Width;
int sy = SelectionPanel.Height;
SelectionPanel.SetBounds(px, py, sx, sy);
}
private void MapComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
MapImage mi = MapComboBox.SelectedItem as MapImage;
if ((mi != null) && (mi != CurrentMap) && (device != null))
{
SetIsLoading(true);
if ((CurrentMap != null) && (CurrentMap.Tex != null))
{
CurrentMap.Tex.Dispose();
CurrentMap.Tex = null;
}
if (mi.Tex == null)
{
LoadImageTexture(mi);
}
else
{
SetIsLoading(false);
}
CurrentMap = mi;
NeedsUpdate = true;
if (CurrentMap != null)
{
TextureNameLabel.Text = CurrentMap.Name;
TextureFileLabel.Text = CurrentMap.Filepath;
TextureOriginTextBox.Text = string.Format("{0}, {1}", CurrentMap.Origin.X, CurrentMap.Origin.Y);
UnitsPerTexelXTextBox.Text = CurrentMap.UnitsPerTexelX.ToString();
UnitsPerTexelYTextBox.Text = CurrentMap.UnitsPerTexelY.ToString();
if (LocatorMarker != null)
{
UpdateMarkerTexturePos(LocatorMarker);
WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString();
TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString();
}
}
else
{
TextureNameLabel.Text = "(No texture)";
TextureFileLabel.Text = "(No texture)";
}
}
}
private void MainPanelShowButton_Click(object sender, EventArgs e)
{
MainPanel.Visible = true;
MainPanelShowButton.Visible = false;
}
private void MainPanelHideButton_Click(object sender, EventArgs e)
{
MainPanel.Visible = false;
MainPanelShowButton.Visible = true;
}
private void MarkerStyleComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
MapIcon icon = MarkerStyleComboBox.SelectedItem as MapIcon;
if (icon != MarkerIcon)
{
MarkerIcon = icon;
foreach (MapMarker m in Markers)
{
m.Icon = icon;
}
}
}
private void LocatorStyleComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
MapIcon icon = LocatorStyleComboBox.SelectedItem as MapIcon;
if (icon != LocatorIcon)
{
LocatorIcon = icon;
LocatorMarker.Icon = icon;
}
}
private void LocateTextBox_TextChanged(object sender, EventArgs e)
{
if (GrabbedMarker == LocatorMarker) return; //don't try to update the marker if it's being dragged
if (LocatorMarker == null) return; //this shouldn't happen, but anyway
LocatorMarker.Parse(LocateTextBox.Text);
UpdateMarkerTexturePos(LocatorMarker);
}
private void GoToButton_Click(object sender, EventArgs e)
{
GoToMarker(LocatorMarker);
}
private void AddMarkersButton_Click(object sender, EventArgs e)
{
string[] lines = MultiFindTextBox.Text.Split('\n');
foreach (string line in lines)
{
AddMarker(line);
}
}
private void ClearMarkersButton_Click(object sender, EventArgs e)
{
Markers.Clear();
MarkersListView.Items.Clear();
}
private void ResetMarkersButton_Click(object sender, EventArgs e)
{
Markers.Clear();
MarkersListView.Items.Clear();
AddDefaultMarkers();
}
private void SetOriginButton_Click(object sender, EventArgs e)
{
if (CurrentMap == null) return;
TextureOriginTextBox.Text = TextureCoordTextBox.Text;
string[] comps = TextureOriginTextBox.Text.Split(',');
if (comps.Length > 1)
{
Vector3 origin = new Vector3(0.0f);
float.TryParse(comps[0].Trim(), out origin.X);
float.TryParse(comps[1].Trim(), out origin.Y);
CurrentMap.Origin = origin;
RecalculateAllMarkers();
LocatorMarker.WorldPos = new Vector3(0.0f);//force to the world origin
LocatorMarker.TexturePos = origin;
GrabbedMarker = LocatorMarker; //don't force the marker update when updating textbox..
LocateTextBox.Text = "0, 0, 0";
GrabbedMarker = null;
WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString();
TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString();
}
}
private void SetCoordButton_Click(object sender, EventArgs e)
{
if (CurrentMap == null) return;
string[] comps = WorldCoordTextBox.Text.Split(',');
if (comps.Length > 1)
{
Vector3 coord = new Vector3(0.0f);
float.TryParse(comps[0].Trim(), out coord.X);
float.TryParse(comps[1].Trim(), out coord.Y);
//assume the entered coord is the world coord for the locator's tex coord.
//find the appropriate scaling factor to make it so.
float tdx = LocatorMarker.TexturePos.X - CurrentMap.Origin.X; //texel dist from origin
float tdy = LocatorMarker.TexturePos.Y - CurrentMap.Origin.Y;
float tdl = (float)Math.Sqrt(tdx * tdx + tdy * tdy);
float wcl = (float)Math.Sqrt(coord.X * coord.X + coord.Y * coord.Y);
float upt = wcl / tdl;
float uptx = upt * Math.Sign(tdx * coord.X);
float upty = upt * Math.Sign(tdy * coord.Y);
CurrentMap.UnitsPerTexelX = uptx;
CurrentMap.UnitsPerTexelY = upty;
RecalculateAllMarkers();
LocatorMarker.WorldPos = coord;
GrabbedMarker = LocatorMarker; //don't force the marker update when updating textbox..
LocateTextBox.Text = LocatorMarker.ToString();
GrabbedMarker = null;
WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString();
TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString();
UnitsPerTexelXTextBox.Text = uptx.ToString();
UnitsPerTexelYTextBox.Text = upty.ToString();
}
}
private void CalibrateButton_Click(object sender, EventArgs e)
{
MessageBox.Show("Not yet implemented...");
}
private void CopyMarkersButton_Click(object sender, EventArgs e)
{
MessageBox.Show("Still need to build this function.");
}
private void RecalculateAllMarkers()
{
//updates marker world coords based off current tex coord
if (LocatorMarker != null)
{
LocatorMarker.WorldPos = GetWorldCoordFromTextureCoord(LocatorMarker.TexturePos);
}
foreach (MapMarker marker in Markers)
{
marker.WorldPos = GetWorldCoordFromTextureCoord(marker.TexturePos);
}
}
private Vector3 GetTextureCoordFromWorldCoord(Vector3 world)
{
if (CurrentMap != null)
{
float tx = world.X / CurrentMap.UnitsPerTexelX;
float ty = world.Y / CurrentMap.UnitsPerTexelY;
return CurrentMap.Origin + new Vector3(tx, ty, 1.0f);
}
else
{
return new Vector3(0.0f);
}
}
private Vector3 GetWorldCoordFromTextureCoord(Vector3 coord)
{
if (CurrentMap != null)
{
Vector3 tv = (coord - CurrentMap.Origin);
tv.X *= CurrentMap.UnitsPerTexelX;
tv.Y *= CurrentMap.UnitsPerTexelY;
return tv;
}
else
{
return new Vector3(0.0f);
}
}
private Vector3 GetTextureCoordFromScreenCoord(Vector3 screen)
{
return new Vector3(0.0f);
}
private Vector3 GetScreenCoordFromTextureCoord(Vector3 coord)
{
float w = ClientSize.Width;
float h = ClientSize.Height;
Vector3 centerdisttx = coord - CurrentViewCenter;
Vector3 centerdistpx = centerdisttx * CurrentZoom;
Vector3 screenpos = centerdistpx + new Vector3(w*0.5f, h*0.5f, 0.0f);
screenpos.Z = 0.0f;
return screenpos;
}
private Vector3 GetWorldCoordFromScreenCoord(Vector3 screen)
{
return GetWorldCoordFromTextureCoord(GetTextureCoordFromScreenCoord(screen));
}
private Vector3 GetScreenCoordFromWorldCoord(Vector3 world)
{
return GetScreenCoordFromTextureCoord(GetTextureCoordFromWorldCoord(world));
}
private void UpdateMarkerTexturePos(MapMarker marker)
{
marker.TexturePos = GetTextureCoordFromWorldCoord(marker.WorldPos);
}
private void UpdateMarkerScreenPos(MapMarker marker)
{
marker.ScreenPos = GetScreenCoordFromTextureCoord(marker.TexturePos);
}
private void UpdateMarkerTexAndScreenPos(MapMarker marker)
{
marker.TexturePos = GetTextureCoordFromWorldCoord(marker.WorldPos);
marker.ScreenPos = GetScreenCoordFromTextureCoord(marker.TexturePos);
}
private Matrix GetMarkerRenderMatrix(MapMarker marker)
{
float sx = 1.0f, sy = 1.0f;
MapIcon ic = marker.Icon;
int icw = ic.TexWidth;
int ich = ic.TexHeight;
if (icw > ich) //shrink square vertically
{
sy = ((float)ich) / ((float)icw);
}
else //shrink square horizontally
{
sx = ((float)icw) / ((float)ich);
}
sx *= ic.Scale;
sy *= ic.Scale;
float px = marker.ScreenPos.X - ic.Center.X * ic.Scale;
float py = marker.ScreenPos.Y - ic.Center.Y*ic.Scale;
px = (float)Math.Round(px, MidpointRounding.AwayFromZero); //snap to pixels...
py = (float)Math.Round(py, MidpointRounding.AwayFromZero);
Matrix scale = Matrix.Scaling(sx, sy, 0.0f);
Matrix trans = Matrix.Translation(px, py, 0.0f);
return Matrix.Multiply(scale, trans);
}
private MapMarker FindMousedMarker()
{
float mx = MouseLastPoint.X;
float my = MouseLastPoint.Y;
if (ShowLocatorCheckBox.Checked)
{
if (IsMapMarkerUnderPoint(LocatorMarker, mx, my))
{
return LocatorMarker;
}
}
//search backwards through the render markers (front to back)
for (int i = RenderMarkers.Count - 1; i >= 0; i--)
{
MapMarker m = RenderMarkers[i];
if (IsMapMarkerUnderPoint(m, mx, my))
{
return m;
}
}
return null;
}
private bool IsMapMarkerUnderPoint(MapMarker marker, float x, float y)
{
float dx = x - marker.ScreenPos.X;
float dy = y - marker.ScreenPos.Y;
float mcx = marker.Icon.Center.X;
float mcy = marker.Icon.Center.Y;
bool bx = ((dx >= -mcx) && (dx <= mcx));
bool by = ((dy <= 0.0f) && (dy >= -mcy));
return (bx && by);
}
private void GoToMarker(MapMarker m)
{
//adjust the target to account for the main panel...
Vector3 view = m.TexturePos;
view.X += ((float)(MainPanel.Width + 4) * 0.5f) / CurrentZoom;
TargetViewCenter = view;
}
private void AddMarker(string markerstr)
{
MapMarker m = new MapMarker();
m.Parse(markerstr.Trim());
m.Icon = MarkerIcon;
UpdateMarkerTexturePos(m);
Markers.Add(m);
//////sort by Y
////Markers.Sort((m1, m2) => m1.TexturePos.Y.CompareTo(m2.TexturePos.Y));
ListViewItem lvi = new ListViewItem(new string[] { m.Name, m.WorldPos.X.ToString(), m.WorldPos.Y.ToString(), m.WorldPos.Z.ToString() });
lvi.Tag = m;
MarkersListView.Items.Add(lvi);
}
private void AddDefaultMarkers()
{
AddMarker("1972.606, 3817.044, 0.0, Trevor Bed");
AddMarker("94.5723, -1290.082, 0.0, Strip Club Bed");
AddMarker("-1151.746, -1518.136, 0.0, Trevor City Bed");
AddMarker("-2052.0, 3237.0, 0.0, Zancudo UFO");
AddMarker("2490.0, 3777.0, 0.0, Hippy UFO");
AddMarker("760.4618, 7392.8032, -126.0774, Sea UFO");
AddMarker("501.4398, 5603.96, 0.0, RedEye");
AddMarker("-1154.11, -2715.203, 0.0, Flight School");
AddMarker("-1370.625, 56.1227, 0.0, Golf");
AddMarker("-1109.213, 4914.744, 0.0, Altruist Cult");
AddMarker("-1633.087, 4736.784, 0.0, Deal Gone Wrong");
AddMarker("51.3909, 5957.7568, 209.614, cs1_10_clue_moon02");
AddMarker("400.7087, 5714.5645, 605.0978, cs1_10_clue_rain01");
AddMarker("703.442, 6329.8936, 76.4973, cs1_10_clue_rain02");
AddMarker("228.7844, 5370.585, 577.2613, cs1_10_clue_moon01");
AddMarker("366.4871, 5518.0742, 704.3185, cs1_10_clue_mountain01");
}
private MapIcon AddIcon(string name, string filename, int texw, int texh, float centerx, float centery, float scale)
{
string filepath = "maps\\" + filename;
try
{
MapIcon mi = new MapIcon(name, filepath, texw, texh, centerx, centery, scale);
Icons.Add(mi);
return mi;
}
catch (Exception ex)
{
MessageBox.Show("Could not load map icon " + filepath + " for " + name + "!\n\n" + ex.ToString());
}
return null;
}
private MapImage AddImage(string name, string filename, int texw, int texh, float origx, float origy, float uppx, float uppy)
{
string filepath = "maps\\" + filename;
try
{
MapImage mi = new MapImage(name, filepath, texw, texh, origx, origy, uppx, uppy);
Images.Add(mi);
return mi;
}
catch (Exception ex)
{
MessageBox.Show("Could not load map image " + filepath + " for " + name + " map!\n\n" + ex.ToString());
}
return null;
}
private void LoadImageTexture(MapImage mi)
{
SetIsLoading(true);
Task.Run(() =>
{
try
{
if (device != null)
{
mi.Tex = Texture.FromFile(device, mi.Filepath);
}
}
catch (Exception ex)
{
MessageBox.Show("Could not load map image " + mi.Filepath + " for " + mi.Name + " map!\n\n" + ex.ToString());
}
LoadCurrentImageComplete();
});
}
private void LoadIconTexture(MapIcon mi)
{
try
{
if (device != null)
{
mi.Tex = Texture.FromFile(device, mi.Filepath);
}
}
catch (Exception ex)
{
MessageBox.Show("Could not load map icon " + mi.Filepath + " for " + mi.Name + "!\n\n" + ex.ToString());
}
}
private void LoadCurrentImageComplete()
{
try
{
if (InvokeRequired)
{
Invoke(new Action(() => { LoadCurrentImageComplete(); }));
}
else
{
SetIsLoading(false);
}
}
catch { }
}
private void LoadImagesComplete()
{
try
{
if (InvokeRequired)
{
Invoke(new Action(() => { LoadImagesComplete(); }));
}
else
{
if (Images.Count > 0)
{
foreach (MapImage mi in Images)
{
MapComboBox.Items.Add(mi);
}
CurrentMap = Images[0];
MapComboBox.SelectedItem = CurrentMap;
}
SetIsLoading(false);
}
}
catch { }
}
private void SetIsLoading(bool loading)
{
LoadingImages = loading;
LoadingLabel.Visible = loading;
MapComboBox.Enabled = !loading;
}
private void GoToSelectedMarkerButton_Click(object sender, EventArgs e)
{
if (MarkersListView.SelectedItems.Count == 1)
{
MapMarker m = MarkersListView.SelectedItems[0].Tag as MapMarker;
if (m != null)
{
GoToMarker(m);
}
}
}
private void MarkersListView_DoubleClick(object sender, EventArgs e)
{
//go to the marker..
if (MarkersListView.SelectedItems.Count == 1)
{
MapMarker m = MarkersListView.SelectedItems[0].Tag as MapMarker;
if (m != null)
{
GoToMarker(m);
}
}
}
}
public class MapImage
{
public string Name { get; set; }
public string Filepath { get; set; }
public Texture Tex { get; set; }
public Vector3 Origin { get; set; } //in image pixels
public float UnitsPerTexelX { get; set; } //world units per image pixel
public float UnitsPerTexelY { get; set; } //world units per image pixel
public int TexWidth { get; set; }
public int TexHeight { get; set; }
public MapImage(string name, string filepath, int texw, int texh, float origx, float origy, float uppx, float uppy)
{
Name = name;
Filepath = filepath;
TexWidth = texw;
TexHeight = texh;
Origin = new Vector3(origx, origy, 0.0f);
UnitsPerTexelX = uppx;
UnitsPerTexelY = uppy;
if (!File.Exists(filepath))
{
throw new Exception("File not found.");
}
}
public override string ToString()
{
return Name;
}
}
public class MapIcon
{
public string Name { get; set; }
public string Filepath { get; set; }
public Texture Tex { get; set; }
public Vector3 Center { get; set; } //in image pixels
public float Scale { get; set; } //screen pixels per icon pixel
public int TexWidth { get; set; }
public int TexHeight { get; set; }
public MapIcon(string name, string filepath, int texw, int texh, float centerx, float centery, float scale)
{
Name = name;
Filepath = filepath;
TexWidth = texw;
TexHeight = texh;
Center = new Vector3(centerx, centery, 0.0f);
Scale = scale;
if (!File.Exists(filepath))
{
throw new Exception("File not found.");
}
}
public override string ToString()
{
return Name;
}
}
public class MapMarker
{
public MapIcon Icon { get; set; }
public Vector3 WorldPos { get; set; } //actual world pos
public Vector3 TexturePos { get; set; } //position in the current texture (temp)
public Vector3 ScreenPos { get; set; } //position on screen (updated per frame if needed)
public string Name { get; set; }
public List<string> Properties { get; set; } //additional data
public bool IsMovable { get; set; }
public void Parse(string s)
{
Vector3 p = new Vector3(0.0f);
string[] ss = s.Split(',');
if (ss.Length > 1)
{
float.TryParse(ss[0].Trim(), out p.X);
float.TryParse(ss[1].Trim(), out p.Y);
}
if (ss.Length > 2)
{
float.TryParse(ss[2].Trim(), out p.Z);
}
if (ss.Length > 3)
{
Name = ss[3].Trim();
}
else
{
Name = string.Empty;
}
for (int i = 4; i < ss.Length; i++)
{
if (Properties == null) Properties = new List<string>();
Properties.Add(ss[i].Trim());
}
WorldPos = p;
}
public override string ToString()
{
string cstr = string.Format("{0}, {1}, {2}", WorldPos.X, WorldPos.Y, WorldPos.Z);
if (!string.IsNullOrEmpty(Name))
{
cstr += ", " + Name;
if (Properties != null)
{
foreach (string prop in Properties)
{
cstr += ", " + prop;
}
}
}
return cstr;
}
public string Get2DWorldPosString()
{
return string.Format("{0}, {1}", WorldPos.X, WorldPos.Y);
}
public string Get3DWorldPosString()
{
return string.Format("{0}, {1}, {2}", WorldPos.X, WorldPos.Y, WorldPos.Z);
}
public string Get2DTexturePosString()
{
return string.Format("{0}, {1}", TexturePos.X, TexturePos.Y);
}
}
}