mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2025-02-27 19:32:54 +08:00
610 lines
16 KiB
C#
610 lines
16 KiB
C#
using CodeWalker.GameFiles;
|
|
using CodeWalker.Properties;
|
|
using CodeWalker.Rendering;
|
|
using CodeWalker.World;
|
|
using SharpDX;
|
|
using SharpDX.Direct3D11;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace CodeWalker.Vehicles
|
|
{
|
|
public partial class VehicleForm : Form, DXForm
|
|
{
|
|
public Form Form { get { return this; } } //for DXForm/DXManager use
|
|
|
|
public Renderer Renderer = null;
|
|
public object RenderSyncRoot { get { return Renderer.RenderSyncRoot; } }
|
|
|
|
volatile bool formopen = false;
|
|
volatile bool running = false;
|
|
volatile bool pauserendering = false;
|
|
//volatile bool initialised = false;
|
|
|
|
Stopwatch frametimer = new Stopwatch();
|
|
Camera camera;
|
|
Timecycle timecycle;
|
|
Weather weather;
|
|
Clouds clouds;
|
|
|
|
Entity camEntity = new Entity();
|
|
|
|
|
|
bool MouseLButtonDown = false;
|
|
bool MouseRButtonDown = false;
|
|
int MouseX;
|
|
int MouseY;
|
|
System.Drawing.Point MouseDownPoint;
|
|
System.Drawing.Point MouseLastPoint;
|
|
|
|
|
|
public GameFileCache GameFileCache { get; } = GameFileCacheFactory.Create();
|
|
|
|
|
|
InputManager Input = new InputManager();
|
|
|
|
|
|
bool initedOk = false;
|
|
|
|
|
|
|
|
|
|
public VehicleForm()
|
|
{
|
|
InitializeComponent();
|
|
|
|
Renderer = new Renderer(this, GameFileCache);
|
|
camera = Renderer.camera;
|
|
timecycle = Renderer.timecycle;
|
|
weather = Renderer.weather;
|
|
clouds = Renderer.clouds;
|
|
|
|
initedOk = Renderer.Init();
|
|
|
|
Renderer.controllightdir = !Settings.Default.Skydome;
|
|
Renderer.rendercollisionmeshes = false;
|
|
Renderer.renderclouds = false;
|
|
//Renderer.renderclouds = true;
|
|
//Renderer.individualcloudfrag = "Contrails";
|
|
Renderer.rendermoon = false;
|
|
Renderer.renderskeletons = false;
|
|
Renderer.SelectionFlagsTestAll = true;
|
|
|
|
}
|
|
|
|
|
|
public void InitScene(Device device)
|
|
{
|
|
int width = ClientSize.Width;
|
|
int height = ClientSize.Height;
|
|
|
|
try
|
|
{
|
|
Renderer.DeviceCreated(device, width, height);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show("Error loading shaders!\n" + ex.ToString());
|
|
return;
|
|
}
|
|
|
|
|
|
camera.FollowEntity = camEntity;
|
|
camera.FollowEntity.Position = Vector3.Zero;// prevworldpos;
|
|
camera.FollowEntity.Orientation = Quaternion.LookAtLH(Vector3.Zero, Vector3.Up, Vector3.ForwardLH);
|
|
camera.TargetDistance = 2.0f;
|
|
camera.CurrentDistance = 2.0f;
|
|
camera.TargetRotation.Y = 0.2f;
|
|
camera.CurrentRotation.Y = 0.2f;
|
|
camera.TargetRotation.X = 0.5f * (float)Math.PI;
|
|
camera.CurrentRotation.X = 0.5f * (float)Math.PI;
|
|
|
|
|
|
//LoadSettings();
|
|
|
|
|
|
formopen = true;
|
|
new Thread(new ThreadStart(ContentThread)).Start();
|
|
|
|
frametimer.Start();
|
|
|
|
}
|
|
public void CleanupScene()
|
|
{
|
|
formopen = false;
|
|
|
|
Renderer.DeviceDestroyed();
|
|
|
|
int count = 0;
|
|
while (running && (count < 5000)) //wait for the content thread to exit gracefully
|
|
{
|
|
Thread.Sleep(1);
|
|
count++;
|
|
}
|
|
}
|
|
public void RenderScene(DeviceContext context)
|
|
{
|
|
float elapsed = (float)frametimer.Elapsed.TotalSeconds;
|
|
frametimer.Restart();
|
|
|
|
if (pauserendering) return;
|
|
|
|
if (!Monitor.TryEnter(Renderer.RenderSyncRoot, 50))
|
|
{ return; } //couldn't get a lock, try again next time
|
|
|
|
//UpdateControlInputs(elapsed);
|
|
//space.Update(elapsed);
|
|
|
|
|
|
Renderer.Update(elapsed, MouseLastPoint.X, MouseLastPoint.Y);
|
|
|
|
|
|
|
|
//UpdateWidgets();
|
|
//BeginMouseHitTest();
|
|
|
|
|
|
|
|
|
|
Renderer.BeginRender(context);
|
|
|
|
Renderer.RenderSkyAndClouds();
|
|
|
|
Renderer.SelectedDrawable = null;// SelectedItem.Drawable;
|
|
|
|
|
|
//if (renderworld)
|
|
//{
|
|
// RenderWorld();
|
|
//}
|
|
//else if (rendermaps)
|
|
//{
|
|
// RenderYmaps();
|
|
//}
|
|
//else
|
|
//{
|
|
// RenderSingleItem();
|
|
//}
|
|
//UpdateMouseHitsFromRenderer();
|
|
//RenderSelection();
|
|
|
|
|
|
//RenderGrid(context);
|
|
|
|
|
|
Renderer.RenderQueued();
|
|
|
|
//Renderer.RenderBounds(MapSelectionMode.Entity);
|
|
|
|
//Renderer.RenderSelectionGeometry(MapSelectionMode.Entity);
|
|
|
|
//RenderMoused();
|
|
|
|
Renderer.RenderFinalPass();
|
|
|
|
//RenderMarkers();
|
|
//RenderWidgets();
|
|
|
|
Renderer.EndRender();
|
|
|
|
Monitor.Exit(Renderer.RenderSyncRoot);
|
|
|
|
//UpdateMarkerSelectionPanelInvoke();
|
|
}
|
|
public void BuffersResized(int w, int h)
|
|
{
|
|
Renderer.BuffersResized(w, h);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Init()
|
|
{
|
|
//called from VehicleForm_Load
|
|
|
|
if (!initedOk)
|
|
{
|
|
Close();
|
|
return;
|
|
}
|
|
|
|
|
|
MouseWheel += VehicleForm_MouseWheel;
|
|
|
|
if (!GTAFolder.UpdateGTAFolder(true))
|
|
{
|
|
Close();
|
|
return;
|
|
}
|
|
|
|
|
|
Input.Init();
|
|
|
|
|
|
Renderer.Start();
|
|
}
|
|
|
|
|
|
private void ContentThread()
|
|
{
|
|
//main content loading thread.
|
|
running = true;
|
|
|
|
UpdateStatus("Scanning...");
|
|
|
|
try
|
|
{
|
|
GTA5Keys.LoadFromPath(GTAFolder.CurrentGTAFolder, Settings.Default.Key);
|
|
}
|
|
catch
|
|
{
|
|
MessageBox.Show("Keys not found! This shouldn't happen.");
|
|
Close();
|
|
return;
|
|
}
|
|
|
|
GameFileCache.EnableDlc = true;
|
|
GameFileCache.LoadVehicles = true;
|
|
GameFileCache.LoadArchetypes = false;//to speed things up a little
|
|
GameFileCache.BuildExtendedJenkIndex = false;//to speed things up a little
|
|
GameFileCache.Init(UpdateStatus, LogError);
|
|
|
|
//UpdateDlcListComboBox(gameFileCache.DlcNameList);
|
|
|
|
//EnableCacheDependentUI();
|
|
|
|
LoadWorld();
|
|
|
|
|
|
|
|
//initialised = true;
|
|
|
|
//EnableDLCModsUI();
|
|
|
|
//UpdateStatus("Ready");
|
|
|
|
|
|
Task.Run(() => {
|
|
while (formopen && !IsDisposed) //renderer content loop
|
|
{
|
|
bool rcItemsPending = Renderer.ContentThreadProc();
|
|
|
|
if (!rcItemsPending)
|
|
{
|
|
Thread.Sleep(1); //sleep if there's nothing to do
|
|
}
|
|
}
|
|
});
|
|
|
|
while (formopen && !IsDisposed) //main asset loop
|
|
{
|
|
bool fcItemsPending = GameFileCache.ContentThreadProc();
|
|
|
|
if (!fcItemsPending)
|
|
{
|
|
Thread.Sleep(1); //sleep if there's nothing to do
|
|
}
|
|
}
|
|
|
|
GameFileCache.Clear();
|
|
|
|
running = false;
|
|
}
|
|
|
|
|
|
|
|
|
|
private void LoadWorld()
|
|
{
|
|
UpdateStatus("Loading timecycles...");
|
|
timecycle.Init(GameFileCache, UpdateStatus);
|
|
timecycle.SetTime(Renderer.timeofday);
|
|
|
|
UpdateStatus("Loading materials...");
|
|
BoundsMaterialTypes.Init(GameFileCache);
|
|
|
|
UpdateStatus("Loading weather...");
|
|
weather.Init(GameFileCache, UpdateStatus, timecycle);
|
|
//UpdateWeatherTypesComboBox(weather);
|
|
|
|
UpdateStatus("Loading clouds...");
|
|
clouds.Init(GameFileCache, UpdateStatus, weather);
|
|
//UpdateCloudTypesComboBox(clouds);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void UpdateStatus(string text)
|
|
{
|
|
try
|
|
{
|
|
if (InvokeRequired)
|
|
{
|
|
BeginInvoke(new Action(() => { UpdateStatus(text); }));
|
|
}
|
|
else
|
|
{
|
|
StatusLabel.Text = text;
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
private void LogError(string text)
|
|
{
|
|
try
|
|
{
|
|
if (InvokeRequired)
|
|
{
|
|
Invoke(new Action(() => { LogError(text); }));
|
|
}
|
|
else
|
|
{
|
|
//TODO: error logging..
|
|
//ConsoleTextBox.AppendText(text + "\r\n");
|
|
//StatusLabel.Text = text;
|
|
//MessageBox.Show(text);
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateMousePosition(MouseEventArgs e)
|
|
{
|
|
MouseX = e.X;
|
|
MouseY = e.Y;
|
|
MouseLastPoint = e.Location;
|
|
}
|
|
|
|
private void RotateCam(int dx, int dy)
|
|
{
|
|
camera.MouseRotate(dx, dy);
|
|
}
|
|
|
|
|
|
|
|
|
|
private void VehicleForm_Load(object sender, EventArgs e)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
private void VehicleForm_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
switch (e.Button)
|
|
{
|
|
case MouseButtons.Left: MouseLButtonDown = true; break;
|
|
case MouseButtons.Right: MouseRButtonDown = true; break;
|
|
}
|
|
|
|
//if (!ToolsPanelShowButton.Focused)
|
|
//{
|
|
// ToolsPanelShowButton.Focus(); //make sure no textboxes etc are focused!
|
|
//}
|
|
|
|
MouseDownPoint = e.Location;
|
|
MouseLastPoint = MouseDownPoint;
|
|
|
|
if (MouseLButtonDown)
|
|
{
|
|
}
|
|
|
|
if (MouseRButtonDown)
|
|
{
|
|
//SelectMousedItem();
|
|
}
|
|
|
|
MouseX = e.X; //to stop jumps happening on mousedown, sometimes the last MouseMove event was somewhere else... (eg after clicked a menu)
|
|
MouseY = e.Y;
|
|
}
|
|
|
|
private void VehicleForm_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
switch (e.Button)
|
|
{
|
|
case MouseButtons.Left: MouseLButtonDown = false; break;
|
|
case MouseButtons.Right: MouseRButtonDown = false; break;
|
|
}
|
|
|
|
|
|
|
|
if (e.Button == MouseButtons.Left)
|
|
{
|
|
}
|
|
}
|
|
|
|
private void VehicleForm_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
int dx = e.X - MouseX;
|
|
int dy = e.Y - MouseY;
|
|
|
|
//if (MouseInvert)
|
|
//{
|
|
// dy = -dy;
|
|
//}
|
|
|
|
//if (ControlMode == WorldControlMode.Free && !ControlBrushEnabled)
|
|
{
|
|
if (MouseLButtonDown)
|
|
{
|
|
RotateCam(dx, dy);
|
|
}
|
|
if (MouseRButtonDown)
|
|
{
|
|
if (Renderer.controllightdir)
|
|
{
|
|
Renderer.lightdirx += (dx * camera.Sensitivity);
|
|
Renderer.lightdiry += (dy * camera.Sensitivity);
|
|
}
|
|
else if (Renderer.controltimeofday)
|
|
{
|
|
float tod = Renderer.timeofday;
|
|
tod += (dx - dy) / 30.0f;
|
|
while (tod >= 24.0f) tod -= 24.0f;
|
|
while (tod < 0.0f) tod += 24.0f;
|
|
timecycle.SetTime(tod);
|
|
Renderer.timeofday = tod;
|
|
|
|
//float fv = tod * 60.0f;
|
|
//TimeOfDayTrackBar.Value = (int)fv;
|
|
//UpdateTimeOfDayLabel();
|
|
}
|
|
}
|
|
|
|
UpdateMousePosition(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
private void VehicleForm_MouseWheel(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Delta != 0)
|
|
{
|
|
camera.MouseZoom(e.Delta);
|
|
}
|
|
}
|
|
|
|
private void VehicleForm_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (ActiveControl is TextBox)
|
|
{
|
|
var tb = ActiveControl as TextBox;
|
|
if (!tb.ReadOnly) return; //don't move the camera when typing!
|
|
}
|
|
if (ActiveControl is ComboBox)
|
|
{
|
|
var cb = ActiveControl as ComboBox;
|
|
if (cb.DropDownStyle != ComboBoxStyle.DropDownList) return; //nontypable combobox
|
|
}
|
|
|
|
bool enablemove = true;// (!iseditmode) || (MouseLButtonDown && (GrabbedMarker == null) && (GrabbedWidget == null));
|
|
|
|
Input.KeyDown(e, enablemove);
|
|
|
|
var k = e.KeyCode;
|
|
var kb = Input.keyBindings;
|
|
bool ctrl = Input.CtrlPressed;
|
|
bool shift = Input.ShiftPressed;
|
|
|
|
|
|
if (!ctrl)
|
|
{
|
|
if (k == kb.MoveSlowerZoomIn)
|
|
{
|
|
camera.MouseZoom(1);
|
|
}
|
|
if (k == kb.MoveFasterZoomOut)
|
|
{
|
|
camera.MouseZoom(-1);
|
|
}
|
|
}
|
|
|
|
|
|
if (!Input.kbmoving) //don't trigger further actions if moving.
|
|
{
|
|
if (!ctrl)
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
//switch (k)
|
|
//{
|
|
// //case Keys.N:
|
|
// // New();
|
|
// // break;
|
|
// //case Keys.O:
|
|
// // Open();
|
|
// // break;
|
|
// //case Keys.S:
|
|
// // if (shift) SaveAll();
|
|
// // else Save();
|
|
// // break;
|
|
// //case Keys.Z:
|
|
// // Undo();
|
|
// // break;
|
|
// //case Keys.Y:
|
|
// // Redo();
|
|
// // break;
|
|
// //case Keys.C:
|
|
// // CopyItem();
|
|
// // break;
|
|
// //case Keys.V:
|
|
// // PasteItem();
|
|
// // break;
|
|
// //case Keys.U:
|
|
// // ToolsPanelShowButton.Visible = !ToolsPanelShowButton.Visible;
|
|
// // break;
|
|
//}
|
|
}
|
|
}
|
|
|
|
//if (ControlMode != WorldControlMode.Free || ControlBrushEnabled)
|
|
//{
|
|
// e.Handled = true;
|
|
//}
|
|
}
|
|
|
|
private void VehicleForm_KeyUp(object sender, KeyEventArgs e)
|
|
{
|
|
Input.KeyUp(e);
|
|
|
|
if (ActiveControl is TextBox)
|
|
{
|
|
var tb = ActiveControl as TextBox;
|
|
if (!tb.ReadOnly) return; //don't move the camera when typing!
|
|
}
|
|
if (ActiveControl is ComboBox)
|
|
{
|
|
var cb = ActiveControl as ComboBox;
|
|
if (cb.DropDownStyle != ComboBoxStyle.DropDownList) return; //non-typable combobox
|
|
}
|
|
|
|
//if (ControlMode != WorldControlMode.Free)
|
|
//{
|
|
// e.Handled = true;
|
|
//}
|
|
}
|
|
|
|
private void VehicleForm_Deactivate(object sender, EventArgs e)
|
|
{
|
|
//try not to lock keyboard movement if the form loses focus.
|
|
Input.KeyboardStop();
|
|
}
|
|
|
|
private void StatsUpdateTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
StatsLabel.Text = Renderer.GetStatusText();
|
|
|
|
if (Renderer.timerunning)
|
|
{
|
|
//float fv = Renderer.timeofday * 60.0f;
|
|
////TimeOfDayTrackBar.Value = (int)fv;
|
|
//UpdateTimeOfDayLabel();
|
|
}
|
|
|
|
//CameraPositionTextBox.Text = FloatUtil.GetVector3String(camera.Position, "0.##");
|
|
}
|
|
}
|
|
}
|