private void RegisterMouseEventsOnBoxVisual(BoxVisual3D boxVisual3D, Ab3d.Utilities.EventManager3D eventManager3D) { var visualEventSource3D = new VisualEventSource3D(boxVisual3D); visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e) { ClearMouseOverBoxVisual(); var hitBoxVisual3D = e.HitObject as BoxVisual3D; if (hitBoxVisual3D != null && !ReferenceEquals(hitBoxVisual3D, _currentlySelectedBoxVisual3D)) { _savedMouseOverMaterial = hitBoxVisual3D.Material; hitBoxVisual3D.Material = _mouseOverBoxMaterial; _currentMouseOverBoxVisual3D = hitBoxVisual3D; } Mouse.OverrideCursor = Cursors.Hand; }; visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e) { var hitBoxVisual3D = e.HitObject as BoxVisual3D; if (!ReferenceEquals(hitBoxVisual3D, _currentlySelectedBoxVisual3D)) { ClearMouseOverBoxVisual(); } else { _currentMouseOverBoxVisual3D = null; } Mouse.OverrideCursor = null; }; visualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e) { ClearSelectedBoxVisual(); var hitBoxVisual3D = e.HitObject as BoxVisual3D; if (hitBoxVisual3D != null) { hitBoxVisual3D.Material = _selectedBoxMaterial; _currentlySelectedBoxVisual3D = hitBoxVisual3D; Camera1.RotationCenterPosition = hitBoxVisual3D.CenterPosition; } }; eventManager3D.RegisterEventSource3D(visualEventSource3D); }
public TouchManipulationsSample() { InitializeComponent(); // First, create an instace of EventManager3D for MainViewport _eventManager = new Ab3d.Utilities.EventManager3D(MainViewport); // Setting CustomEventsSourceElement to a Border that has Background defind (can also be set to Transparent, but should not be null) // allows EventManager3D to get events even if touch is not over any 3D model. // For example when moving the model with touch, the model may move away from the fingers _eventManager.CustomEventsSourceElement = ViewportBorder; // IMPORTANT: // We need to manually enable the manipulation events. // Otherwise we will only get mouse events (also those mouse events that are created from touch events) // // NOTE: // When IsManipulationEnabled, the mouse events will not be created from touch events. _eventManager.IsManipulationEnabled = true; // Now create an instance of VisualEventSource3D // It will be used to define the TeapotVisual3D as source of touch events var visualEventSource3D = new VisualEventSource3D(TeapotVisual3D); // Now we can subscribe to manipulation events (we could also subscribe to mouse events) visualEventSource3D.ManipulationStarted += delegate(object o, Manipulation3DEventArgs <ManipulationStartedEventArgs> e) { TeapotVisual3D.DefaultMaterial = new DiffuseMaterial(Brushes.Red); }; visualEventSource3D.ManipulationCompleted += delegate(object o, Manipulation3DEventArgs <ManipulationCompletedEventArgs> e) { TeapotVisual3D.DefaultMaterial = new DiffuseMaterial(Brushes.Silver); }; visualEventSource3D.ManipulationDelta += VisualEventSource3DOnManipulationDelta; // Register the teapot as an event source on EventManager3D _eventManager.RegisterEventSource3D(visualEventSource3D); // Finally, we need to disable touch events on MouseCameraController // Otherwise both MouseCameraController and EventManager3D will handle the same events (also zooming and rotating the camera) MouseCameraController1.IsTouchMoveEnabled = false; MouseCameraController1.IsTouchRotateEnabled = false; MouseCameraController1.IsTouchZoomEnabled = false; }
private void Setup3DObjects() { // The event manager will be used to manage the mouse events on our boxes _eventManager3D = new Ab3d.Utilities.EventManager3D(_viewport3D); // Add a wire grid var wireGridVisual3D = new Ab3d.Visuals.WireGridVisual3D() { Size = new System.Windows.Size(1000, 1000), HeightCellsCount = 10, WidthCellsCount = 10, LineThickness = 3 }; _viewport3D.Children.Add(wireGridVisual3D); // Create 7 x 7 boxes with different height for (int y = -3; y <= 3; y++) { for (int x = -3; x <= 3; x++) { // Height is based on the distance from the center double height = (5 - Math.Sqrt(x * x + y * y)) * 60; // Create the 3D Box visual element var boxVisual3D = new Ab3d.Visuals.BoxVisual3D() { CenterPosition = new Point3D(x * 100, height / 2, y * 100), Size = new Size3D(80, height, 80), Material = _normalMaterial }; _viewport3D.Children.Add(boxVisual3D); // With EventManager we can subscribe to mouse events as we would have standard 2D controls: var visualEventSource3D = new VisualEventSource3D(boxVisual3D); visualEventSource3D.MouseEnter += BoxOnMouseEnter; visualEventSource3D.MouseLeave += BoxOnMouseLeave; visualEventSource3D.MouseClick += BoxOnMouseClick; _eventManager3D.RegisterEventSource3D(visualEventSource3D); } } ToggleCameraAnimation(); // Start camer animation }
public ModelDecoratorSample() { InitializeComponent(); // Use EventManager3D to subscribe to MouseMove and MouseLeave events on RobotArmModel _eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport); var visualEventSource3D = new VisualEventSource3D(RobotArmModel); // RobotArmModel is a source of events visualEventSource3D.MouseMove += VisualEventSource3DOnMouseMove; visualEventSource3D.MouseLeave += VisualEventSource3DOnMouseLeave; _eventManager3D.RegisterEventSource3D(visualEventSource3D); // !!! IMPORTANT !!! // We need to exclude ModelDecorator from events // otherwise when mouse would be over line drawin with ModelDecorator we would get a MouseLeave event _eventManager3D.RegisterExcludedVisual3D(ModelDecorator); }
private void AddTextBlockVisuals(Point3D startPosition, string text, string fontFamily = null) { Point3D position = startPosition; Vector3D charAdvancementVector = new Vector3D(30, 0, 0); foreach (var oneChar in text) { var textBlockVisual3D = new TextBlockVisual3D() { Text = oneChar.ToString(), Position = position, PositionType = PositionTypes.Center, TextDirection = new Vector3D(1, 0, 0), UpDirection = new Vector3D(0, 1, 0), Size = new Size(20, 40), Foreground = Brushes.LightGray, IsTwoSidedText = true, IsBackSidedTextFlipped = false }; if (!string.IsNullOrEmpty(fontFamily)) { textBlockVisual3D.FontFamily = new FontFamily(fontFamily); } MainViewport.Children.Add(textBlockVisual3D); var visualEventSource3D = new VisualEventSource3D(textBlockVisual3D); visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e) { var hitTextBlockVisual3D = e.HitObject as TextBlockVisual3D; if (hitTextBlockVisual3D != null && hitTextBlockVisual3D.Foreground != Brushes.Red) { hitTextBlockVisual3D.Foreground = Brushes.Orange; } Mouse.OverrideCursor = Cursors.Hand; }; visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e) { var hitTextBlockVisual3D = e.HitObject as TextBlockVisual3D; if (hitTextBlockVisual3D != null && hitTextBlockVisual3D.Foreground != Brushes.Red) { hitTextBlockVisual3D.Foreground = Brushes.LightGray; } Mouse.OverrideCursor = null; }; visualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e) { var hitTextBlockVisual3D = e.HitObject as TextBlockVisual3D; if (hitTextBlockVisual3D != null) { if (hitTextBlockVisual3D.Foreground != Brushes.Red) { hitTextBlockVisual3D.Foreground = Brushes.Red; } else { hitTextBlockVisual3D.Foreground = Brushes.Orange; } } }; _eventManager3D.RegisterEventSource3D(visualEventSource3D); position += charAdvancementVector; } }
public void ShowData(List <SphereData> originalData, Rect3D displayedDataBounds, Rect xyDataRange) { // Now use original data to create our data view objects // All data will be displayed in a 3D box defined below: //var displayedDataBounds = new Rect3D(AxesBox.CenterPosition.X - AxesBox.Size.X * 0.5, // AxesBox.CenterPosition.Y - AxesBox.Size.Y * 0.5, // AxesBox.CenterPosition.Z - AxesBox.Size.Z * 0.5, // AxesBox.Size.X, // AxesBox.Size.Y, // AxesBox.Size.Z); _allSpheresData = new List <SphereDataView>(originalData.Count); foreach (var originalSphereData in originalData) { // Set color of the sphere based on its y position // We choose the color from the gradient defined in EnsureGradientColorsArray double relativeY = (originalSphereData.Location.Y - xyDataRange.Y) / xyDataRange.Height; int colorArrayIndex = (int)(relativeY * (_gradientColorsArray.Length - 1)); Color color = _gradientColorsArray[colorArrayIndex]; var sphereDataView = SphereDataView.Create(originalSphereData, displayedDataBounds, originalData.Count, xyDataRange, color); sphereDataView.IsSelectedChanged += delegate(object sender, EventArgs args) { var changedPositionDataView = (SphereDataView)sender; if (changedPositionDataView.IsSelected) { DataListBox.SelectedItems.Add(changedPositionDataView); } else { DataListBox.SelectedItems.Remove(changedPositionDataView); } UpdateSelectedSpheresData(); }; _allSpheresData.Add(sphereDataView); } // Bind positions data to ListBox DataListBox.ItemsSource = _allSpheresData; // Create curve through all positions // This is done by first creating all points that define the curve (10 points between each position that define the curve) List <Point3D> allPositions = new List <Point3D>(); foreach (var positionData in _allSpheresData) { allPositions.Add(positionData.Position); } BezierCurve bezierCurve = Ab3d.Utilities.BezierCurve.CreateFromCurvePositions(allPositions); Point3DCollection curvePoints = bezierCurve.CreateBezierCurve(positionsPerSegment: 10); // How many points between each defined position in the curve // Create 3D Polyline from curvePoints Model3D curveModel = Ab3d.Models.Line3DFactory.CreatePolyLine3D(curvePoints, thickness: 2, color: Colors.Blue, isClosed: false, startLineCap: LineCap.Flat, endLineCap: LineCap.Flat, parentViewport3D: MainViewport); CurveModelVisual.Content = curveModel; // Now create 3D sphere objects for each position SpheresModelVisual.Children.Clear(); // Each sphere will also need MouseEnter, MouseLeave and MouseClick event handlers // We use EventManager3D for that var eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport); // Add 3D sphere for each position foreach (var positionData in _allSpheresData) { SpheresModelVisual.Children.Add(positionData.ModelVisual3D); // Sphere Visual3D is created in SphereDataView object // Add event handlers (sphere Visual3D will be the source of the events) var visualEventSource3D = new VisualEventSource3D(positionData.ModelVisual3D); visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e) { if (_isSelecting) { return; } // Use hand cursor Mouse.OverrideCursor = Cursors.Hand; // Find selected position data var selectedPositionData = _allSpheresData.FirstOrDefault(p => p.ModelVisual3D == e.HitObject); SelectData(selectedPositionData, e.CurrentMousePosition); }; visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e) { if (_isSelecting) { return; } Mouse.OverrideCursor = null; DataToolTipBorder.Visibility = Visibility.Collapsed; DataToolTipBorder.DataContext = null; SelectedSphereLinesVisual.Children.Clear(); }; visualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e) { // Select / deselect on mouse click var clickedPositionData = _allSpheresData.FirstOrDefault(p => p.ModelVisual3D == e.HitObject); if (clickedPositionData != null) { positionData.IsSelected = !clickedPositionData.IsSelected; } }; // Register the event source eventManager3D.RegisterEventSource3D(visualEventSource3D); } }
private void SetupMouseEventHandlers(Visual3D targetModelVisual3D) { var visualEventSource3D = new VisualEventSource3D(targetModelVisual3D); visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e) { Mouse.OverrideCursor = Cursors.Cross; }; visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e) { Mouse.OverrideCursor = null; }; visualEventSource3D.MouseMove += delegate(object sender, Mouse3DEventArgs e) { if (e.MouseData.LeftButton != MouseButtonState.Pressed) { return; } // Calculte the position inside texture where the mouse is Point hitPosition; var success = GetRelativeHitTexturePosition(e.RayHitResult, out hitPosition); if (!success) { return; // Cannot get the position } // The position was now relative (1 was bottom right) // Now adjust the position for the size of target Canvas double xPos = hitPosition.X * DrawingCanvas.Width; double yPos = hitPosition.Y * DrawingCanvas.Height; double strokeThickness = _settings.CurrentStrokeThickness; double halfStrokeThickness = strokeThickness / 2; // Prevent drawing over the "edge" of Canvas // This would increase the size of Canvas and produce white areas on the model // Set xPos to be between halfStrokeThickness and DrawingCanvas.Width - halfStrokeThickness xPos = Math.Max(halfStrokeThickness, Math.Min(xPos, DrawingCanvas.Width - halfStrokeThickness)); yPos = Math.Max(halfStrokeThickness, Math.Min(yPos, DrawingCanvas.Height - halfStrokeThickness)); // Check if the change of position is significant if (Math.Abs(_lastXPos - xPos) < 1 && Math.Abs(_lastYPos - yPos) < 1) { return; } _lastXPos = xPos; _lastYPos = yPos; var ellipse = new Ellipse() { Width = strokeThickness, Height = strokeThickness, Fill = _settings.CurrentStrokeBrush }; Canvas.SetLeft(ellipse, xPos - halfStrokeThickness); Canvas.SetTop(ellipse, yPos - halfStrokeThickness); DrawingCanvas.Children.Add(ellipse); }; _eventManager3D.ResetEventSources3D(); // Clear all previously registered event sources _eventManager3D.RegisterEventSource3D(visualEventSource3D); }
private void GenerateRandomDucks(int ducksCount) { var rnd = new Random(); double lakeRadius = LakeCircleVisual3D.Radius; Point3D lakeCenter = LakeCircleVisual3D.CenterPosition; _duckModels = new List <ModelVisual3D>(ducksCount); RootDucksVisual3D.Children.Clear(); for (int i = 0; i < ducksCount; i++) { bool findNewPosition; do { var position = new Point3D(rnd.NextDouble() * lakeRadius * 2 - lakeRadius, 0, rnd.NextDouble() * lakeRadius * 2 - lakeRadius); // If position is outside of 80% of lake radius double distanceToLakeCenter = (position - lakeCenter).Length; findNewPosition = distanceToLakeCenter > (lakeRadius * 0.8); if (!findNewPosition) { // Now check if too close to any other duck foreach (var duckModel in _duckModels) { var standardTransform3D = StandardTransform3D.GetStandardTransform3D(duckModel); var distanceToDuck = (position - standardTransform3D.GetTranslateVector3D().ToPoint3D()).Length; if (distanceToDuck < DuckSize * 4) { findNewPosition = true; break; } } } if (!findNewPosition) { // The position is ok double scale = rnd.NextDouble() + 1; var standardTransform3D = new StandardTransform3D() { TranslateX = position.X, TranslateY = position.Y, TranslateZ = position.Z, RotateY = rnd.NextDouble() * 360, ScaleX = scale, ScaleY = scale, ScaleZ = scale }; var duckVisual3D = new ModelVisual3D() { Content = _duckModel3D, }; StandardTransform3D.SetStandardTransform3D(duckVisual3D, standardTransform3D, updateTransform3D: true); _duckModels.Add(duckVisual3D); RootDucksVisual3D.Children.Add(duckVisual3D); var visualEventSource3D = new VisualEventSource3D(duckVisual3D); visualEventSource3D.MouseEnter += OnDuckMouseEnter; visualEventSource3D.MouseLeave += OnDuckMouseLeave; visualEventSource3D.MouseDown += OnDuckMouseDown; visualEventSource3D.MouseUp += OnDuckMouseUp; _eventManager3D.RegisterEventSource3D(visualEventSource3D); } } while (findNewPosition); } }
public void ShowData(List <SphereData> originalData) { // Now use original data to create our data view objects // All data will be displayed in a 3D box defined below: var displayedDataBounds = new Rect3D(-40, -20, -40, 80, 40, 80); _allPositionsData = new List <SphereDataView>(originalData.Count); foreach (var originalSphereData in originalData) { var sphereDataView = SphereDataView.Create(originalSphereData, displayedDataBounds, originalData.Count, _locationSize, _maxSize); sphereDataView.IsSelectedChanged += delegate(object sender, EventArgs args) { var changedPositionDataView = (SphereDataView)sender; if (changedPositionDataView.IsSelected) { DataListBox.SelectedItems.Add(changedPositionDataView); } else { DataListBox.SelectedItems.Remove(changedPositionDataView); } UpdateSelectedSpheresData(); }; _allPositionsData.Add(sphereDataView); } // Setup axis limits and shown values AxisWireBox.MinYValue = 0; AxisWireBox.MaxYValue = 10; AxisWireBox.YAxisValues = new double[] { 0, 2, 4, 6, 8, 10 }; // Bind positions data to ListBox DataListBox.ItemsSource = _allPositionsData; // Create curve through all positions // This is done by first creating all points that define the curve (10 points between each position that define the curve) List <Point3D> allPositions = new List <Point3D>(); foreach (var positionData in _allPositionsData) { allPositions.Add(positionData.Position); } BezierCurve bezierCurve = Ab3d.Utilities.BezierCurve.CreateFromCurvePositions(allPositions); Point3DCollection curvePoints = bezierCurve.CreateBezierCurve(positionsPerSegment: 10); // How many points between each defined position in the curve // Create 3D Polyline from curvePoints Model3D curveModel = Ab3d.Models.Line3DFactory.CreatePolyLine3D(curvePoints, thickness: 2, color: Colors.Blue, isClosed: false, startLineCap: LineCap.Flat, endLineCap: LineCap.Flat, parentViewport3D: MainViewport); CurveModelVisual.Content = curveModel; // Now create 3D sphere objects for each position SpheresModelVisual.Children.Clear(); // Each sphere will also need MouseEnter, MouseLeave and MouseClick event handlers // We use EventManager3D for that var eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport); // Add 3D sphere for each position foreach (var positionData in _allPositionsData) { SpheresModelVisual.Children.Add(positionData.ModelVisual3D); // Sphere Visual3D is created in SphereDataView object // Add event handlers (sphere Visual3D will be the source of the events) var visualEventSource3D = new VisualEventSource3D(positionData.ModelVisual3D); visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e) { if (_isSelecting) { return; } // Use hand cursor Mouse.OverrideCursor = Cursors.Hand; // Find selected position data var selectedPositionData = _allPositionsData.FirstOrDefault(p => p.ModelVisual3D == e.HitObject); SelectData(selectedPositionData, e.CurrentMousePosition); }; visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e) { if (_isSelecting) { return; } Mouse.OverrideCursor = null; DataToolTipBorder.Visibility = Visibility.Collapsed; DataToolTipBorder.DataContext = null; SelectedSphereLinesVisual.Children.Clear(); }; visualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e) { // Select / deselect on mouse click var clickedPositionData = _allPositionsData.FirstOrDefault(p => p.ModelVisual3D == e.HitObject); if (clickedPositionData != null) { positionData.IsSelected = !clickedPositionData.IsSelected; } }; // Register the event source eventManager3D.RegisterEventSource3D(visualEventSource3D); } }