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.##"); } } }