/// <summary> /// Function to create all <see cref="GorgonGamingDevice"/> objects for this driver. /// </summary> /// <param name="connectedOnly">[Optional] <b>true</b> to only include connected gaming devices, <b>false</b> to include all devices.</param> /// <returns>A list of of <see cref="GorgonGamingDevice"/> objects for this driver.</returns> /// <remarks> /// This will create an instance of <see cref="IGorgonGamingDevice"/> for all devices supported by the driver at one time and return a list containing those instances. /// </remarks> public IReadOnlyList <IGorgonGamingDevice> CreateGamingDevices(bool connectedOnly = false) { IReadOnlyList <IGorgonGamingDeviceInfo> infoList = EnumerateGamingDevices(connectedOnly); if ((infoList == null) || (infoList.Count == 0)) { return(Array.Empty <GorgonGamingDevice>()); } var result = new List <IGorgonGamingDevice>(); foreach (IGorgonGamingDeviceInfo deviceInfo in infoList) { IGorgonGamingDevice device = CreateGamingDevice(deviceInfo); if ((!device.IsConnected) && (connectedOnly)) { device.Dispose(); continue; } result.Add(device); } return(result); }
/// <summary> /// Function to update the controller labels. /// </summary> /// <param name="device">Controller to update.</param> /// <param name="index">Index of the controller.</param> private void UpdateControllerLabels(IGorgonGamingDevice device, int index) { var panel = (Panel)panelControllers.Controls["panelController" + index]; var label = (Label)panel.Controls["labelController" + index]; // Update the label visibility for the controller. if (device.IsConnected) { if (!panel.Visible) { panel.Visible = true; } } else { label.Text = $"{device.Info.Description}"; // Turn off the other ones since we don't want to clutter // up the screen. if ((index > 0) && (panel.Visible)) { panel.Visible = false; } return; } // Set the label information. label.Text = $"{device.Info.Description}: " + $"Left Stick Position {device.Axis[GamingDeviceAxis.LeftStickX].Value}x{device.Axis[GamingDeviceAxis.LeftStickY].Value}. " + $"Right Stick Position {device.Axis[GamingDeviceAxis.RightStickX].Value}x{device.Axis[GamingDeviceAxis.RightStickY].Value}. " + $"Right Trigger Position {device.Axis[GamingDeviceAxis.RightTrigger].Value}. " + $"Left Trigger Position {device.Axis[GamingDeviceAxis.LeftTrigger].Value}."; }
/// <summary> /// Function to draw the controller cursor. /// </summary> /// <param name="controller">Controller for the cursor.</param> /// <param name="index">Index of the controller.</param> private void DrawControllerCursor(IGorgonGamingDevice controller, int index) { GorgonRange xRange = controller.Info.AxisInfo[GamingDeviceAxis.LeftStickX].Range; GorgonRange yRange = controller.Info.AxisInfo[GamingDeviceAxis.LeftStickY].Range; int playerColorValue = (int)(((uint)0xFF << (index * 8)) | 0xFF000000); // Get the color based on the controller index. var cursorSize = new Size(_surface.CursorSize.Width / 2, _surface.CursorSize.Height / 2); // Get the cursor size with offset. // Transform the axis into a -1 .. 1 range. var moveVector = new PointF(controller.Axis[GamingDeviceAxis.LeftStickX].Value - (float)xRange.Minimum, controller.Axis[GamingDeviceAxis.LeftStickY].Value - (float)yRange.Minimum); moveVector = new PointF((moveVector.X / (xRange.Range + 1) * 2.0f) - 1.0f, (moveVector.Y / (yRange.Range + 1) * 2.0f) - 1.0f); // Move at 100 units per second float speed = panelDisplay.ClientSize.Width / 2.0f * GorgonTiming.Delta; var position = new PointF((speed * moveVector.X) + _stickPosition[index].X, (speed * -moveVector.Y) + _stickPosition[index].Y); // Limit the range of the positioning. if (position.X < -cursorSize.Width) { position = new PointF(panelDisplay.ClientRectangle.Right + cursorSize.Width, position.Y); } if (position.Y <= -cursorSize.Height) { position = new PointF(position.X, panelDisplay.ClientRectangle.Bottom + cursorSize.Height); } if (position.X > panelDisplay.ClientRectangle.Right + cursorSize.Width) { position = new PointF(-cursorSize.Width, position.Y); } if (position.Y > panelDisplay.ClientRectangle.Bottom + cursorSize.Height) { position = new PointF(position.X, -cursorSize.Height); } // Draw our cursor. _surface.DrawCursor(Point.Round(position), Color.FromArgb(playerColorValue)); // Update our global position. _stickPosition[index] = position; }
/// <summary> /// Function to process idle time in the application. /// </summary> /// <returns><b>true</b> to continue processing, <b>false</b> to end processing.</returns> private bool Idle() { if (labelMessage.Visible) { return(true); } _surface.Clear(Color.White); for (int i = 0; i < _controllers.Count; i++) { IGorgonGamingDevice controller = _controllers[i]; // Do nothing if this joystick isn't connected. if (!controller.IsConnected) { continue; } controller.Poll(); // Clear the drawing if the primary button is clicked. if (controller.Button[0] == GamingDeviceButtonState.Down) { _surface.ClearDrawing(); } // Draw the controller cursor. DrawControllerCursor(controller, i); // Begin drawing. DrawSpray(controller, i); UpdateControllerLabels(controller, i); } _surface.Render(); return(true); }
/// <summary> /// Function to draw a spray on the screen. /// </summary> /// <param name="device">Controller to use for the spray.</param> /// <param name="index">Index of the controller.</param> private void DrawSpray(IGorgonGamingDevice device, int index) { SprayCan state = _sprayStates[index]; // Update the origin of the spray. state.Origin = _stickPosition[index]; GorgonRange throttleRange = device.Info.AxisInfo[GamingDeviceAxis.RightTrigger].Range; // Find out if we're spraying. if (device.Axis[GamingDeviceAxis.RightTrigger].Value > throttleRange.Minimum) { if ((!state.IsActive) && (!state.NeedReset)) { // Convert the throttle value to a unit value. float throttleUnit = ((float)(device.Axis[GamingDeviceAxis.RightTrigger].Value - throttleRange.Minimum) / throttleRange.Range); // Set up the spray state. state.Position = state.Origin; state.Amount = throttleRange.Range / 2.0f; state.Time = throttleUnit * 10.0f; state.VibrationAmount = device.Info.VibrationMotorRanges[1].Maximum; state.SprayAlpha = (throttleUnit * 239.0f) + 16; state.IsActive = true; } } else { state.IsActive = false; } if (!state.IsActive) { return; } // Update the state spray effect. state.Update(); _surface.DrawPoint(Point.Round(state.Position), state.SprayColor, state.SprayPointSize); }
/// <summary> /// Raises the <see cref="E:System.Windows.Forms.Form.Load"></see> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { GorgonExample.PlugInLocationDirectory = new DirectoryInfo(Settings.Default.PlugInLocation); // Load the assembly. _assemblyCache = new GorgonMefPlugInCache(GorgonApplication.Log); // Create the plugin service. IGorgonPlugInService plugInService = new GorgonMefPlugInService(_assemblyCache); // Create the factory to retrieve gaming device drivers. var factory = new GorgonGamingDeviceDriverFactory(plugInService); // Create the raw input interface. _input = new GorgonRawInput(this, GorgonApplication.Log); // Get available gaming device driver plug ins. _assemblyCache.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, "Gorgon.Input.DirectInput.dll"); _assemblyCache.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, "Gorgon.Input.XInput.dll"); _drivers = factory.LoadAllDrivers(); _joystickList = new List <IGorgonGamingDevice>(); // Get all gaming devices from the drivers. foreach (IGorgonGamingDeviceDriver driver in _drivers) { IReadOnlyList <IGorgonGamingDeviceInfo> infoList = driver.EnumerateGamingDevices(true); foreach (IGorgonGamingDeviceInfo info in infoList) { IGorgonGamingDevice device = driver.CreateGamingDevice(info); // Turn off dead zones for this example. foreach (GorgonGamingDeviceAxis axis in device.Axis) { axis.DeadZone = GorgonRange.Empty; } _joystickList.Add(device); } } // Create mouse. _mouse = new GorgonRawMouse(); // Create the graphics interface. ClientSize = Settings.Default.Resolution; IReadOnlyList <IGorgonVideoAdapterInfo> adapters = GorgonGraphics.EnumerateAdapters(); _graphics = new GorgonGraphics(adapters[0], log: GorgonApplication.Log); _screen = new GorgonSwapChain(_graphics, this, new GorgonSwapChainInfo("INeedYourInput Swapchain") { Width = Settings.Default.Resolution.Width, Height = Settings.Default.Resolution.Height, Format = BufferFormat.R8G8B8A8_UNorm }); _graphics.SetRenderTarget(_screen.RenderTargetView); if (!Settings.Default.IsWindowed) { _screen.EnterFullScreen(); } // For the backup image. Used to make it as large as the monitor that we're on. var currentScreen = Screen.FromHandle(Handle); // Relocate the window to the center of the screen. Location = new Point(currentScreen.Bounds.Left + (currentScreen.WorkingArea.Width / 2) - (ClientSize.Width / 2), currentScreen.Bounds.Top + (currentScreen.WorkingArea.Height / 2) - (ClientSize.Height / 2)); // Create the 2D renderer. _2D = new Gorgon2D(_graphics); // Create the text font. var fontFactory = new GorgonFontFactory(_graphics); _font = fontFactory.GetFont(new GorgonFontInfo("Arial", 9.0f, FontHeightMode.Points, "Arial 9pt") { FontStyle = FontStyle.Bold, AntiAliasingMode = FontAntiAliasMode.AntiAlias }); // Create text sprite. _messageSprite = new GorgonTextSprite(_font, "Using mouse and keyboard (Windows Forms).") { Color = Color.Black }; // Create a back buffer. _backBuffer = GorgonRenderTarget2DView.CreateRenderTarget(_graphics, new GorgonTexture2DInfo("Backbuffer storage") { Width = _screen.Width, Height = _screen.Height, Format = _screen.Format }); _backBuffer.Clear(Color.White); _backBufferView = _backBuffer.GetShaderResourceView(); // Clear our backup image to white to match our primary screen. using (IGorgonImage image = new GorgonImage(new GorgonImageInfo(ImageType.Image2D, _screen.Format) { Width = _screen.Width, Height = _screen.Height, Format = _screen.Format })) { image.Buffers[0].Fill(0xff); _backupImage = image.ToTexture2D(_graphics, new GorgonTexture2DLoadOptions { Binding = TextureBinding.None, Usage = ResourceUsage.Staging }); } // Set gorgon events. _screen.BeforeSwapChainResized += BeforeSwapChainResized; _screen.AfterSwapChainResized += AfterSwapChainResized; // Enable the mouse. Cursor = Cursors.Cross; _mouse.MouseButtonDown += MouseInput; _mouse.MouseMove += MouseInput; _mouse.MouseWheelMove += (sender, args) => { _radius += args.WheelDelta.Sign(); if (_radius < 2.0f) { _radius = 2.0f; } if (_radius > 10.0f) { _radius = 10.0f; } }; // Set the mouse position. _mouse.Position = new Point(ClientSize.Width / 2, ClientSize.Height / 2); _noBlending = _blendBuilder.BlendState(GorgonBlendState.NoBlending) .Build(); _inverted = _blendBuilder.BlendState(GorgonBlendState.Inverted) .Build(); // Set up blending states for our pen. var blendStateBuilder = new GorgonBlendStateBuilder(); _currentBlend = _drawModulatedBlend = _blendBuilder.BlendState(blendStateBuilder .ResetTo(GorgonBlendState.Default) .DestinationBlend(alpha: Blend.One) .Build()) .Build(); _drawAdditiveBlend = _blendBuilder.BlendState(blendStateBuilder .ResetTo(GorgonBlendState.Additive) .DestinationBlend(alpha: Blend.One) .Build()) .Build(); _drawNoBlend = _blendBuilder.BlendState(blendStateBuilder .ResetTo(GorgonBlendState.NoBlending) .DestinationBlend(alpha: Blend.One) .Build()) .Build(); GorgonApplication.IdleMethod = Gorgon_Idle; } catch (ReflectionTypeLoadException refEx) { string refErr = string.Join("\n", refEx.LoaderExceptions.Select(item => item.Message)); GorgonDialogs.ErrorBox(this, refErr); } catch (Exception ex) { GorgonExample.HandleException(ex); GorgonApplication.Quit(); } }
/// <summary> /// Handles the <see cref="E:KeyDown" /> event. /// </summary> /// <param name="e">The <see cref="KeyEventArgs" /> instance containing the event data.</param> protected override void OnKeyUp(KeyEventArgs e) { switch (e.KeyCode) { case Keys.Escape: Close(); // Close break; case Keys.F: if (_screen.IsWindowed) { _screen.EnterFullScreen(); } else { _screen.ExitFullScreen(); } break; case Keys.Down: _radius -= 1.0f; if (_radius < 2.0f) { _radius = 2.0f; } break; case Keys.Up: _radius += 1.0f; if (_radius > 50.0f) { _radius = 50.0f; } break; case Keys.F1: _currentBlend = _drawModulatedBlend; break; case Keys.F2: _currentBlend = _drawAdditiveBlend; break; case Keys.F3: _currentBlend = _drawNoBlend; break; case Keys.C: // Fill the back up image with white _backBuffer.Clear(GorgonColor.White); _backBuffer.Texture.CopyTo(_backupImage); break; case Keys.J: // Disable if we go beyond the end of the list. _counter++; if (_counter == -1) { // Clip the mouse cursor to our client area. Cursor.Clip = _mouse.PositionConstraint = RectangleToScreen(ClientRectangle); // Set the position to the current mouse position. _mouse.Position = Cursor.Position; _input.RegisterDevice(_mouse); _useWinFormsInput = false; _messageSprite.Text = "Using mouse and keyboard (Raw Input)"; break; } if ((_joystickList.Count == 0) || ((_counter >= _joystickList.Count) && (_joystick != null))) { if (!_useWinFormsInput) { Cursor.Clip = Rectangle.Empty; _input.UnregisterDevice(_mouse); } _useWinFormsInput = true; _joystick = null; _counter = -2; _messageSprite.Text = "Using mouse and keyboard (Windows Forms)."; break; } // If we previously had raw input on, turn it off. if (!_useWinFormsInput) { Cursor.Clip = Rectangle.Empty; _input.UnregisterDevice(_mouse); _useWinFormsInput = true; } // Move to the next joystick. _joystick = _joystickList[_counter]; _messageSprite.Text = "Using joystick " + _joystick.Info.Description; break; } }