void EventManagerDragSample_Loaded(object sender, RoutedEventArgs e) { _eventManager = new Ab3d.Utilities.EventManager3D(Viewport3D1); // When using EventManager3D from Ab3d.PowerToys inside DXEngine, // it is recommended to set the CustomEventsSourceElement to the DXViewportView or its parent element (for example ViewportBorder). // If this is not done, then EventManager3D tries to find the DXViewportView and when found uses it as an element that used to subscribe to mouse events. _eventManager.CustomEventsSourceElement = ViewportBorder; // Exclude TransparentPlaneVisual3D from hit testing _eventManager.RegisterExcludedVisual3D(TransparentPlaneVisual3D); var multiEventSource3D = new Ab3d.Utilities.MultiVisualEventSource3D(); multiEventSource3D.TargetVisuals3D = new Visual3D[] { LowerBoxVisual3D, PassageBoxVisual3D, UpperBoxVisual3D }; multiEventSource3D.IsDragSurface = true; _eventManager.RegisterEventSource3D(multiEventSource3D); var eventSource3D = new Ab3d.Utilities.VisualEventSource3D(); eventSource3D.TargetVisual3D = MovableBoxVisual3D; eventSource3D.Name = "Movable"; eventSource3D.MouseEnter += new Ab3d.Common.EventManager3D.Mouse3DEventHandler(eventSource3D_MouseEnter); eventSource3D.MouseLeave += new Ab3d.Common.EventManager3D.Mouse3DEventHandler(eventSource3D_MouseLeave); eventSource3D.MouseClick += new Ab3d.Common.EventManager3D.MouseButton3DEventHandler(movableEventSource3D_MouseClick); eventSource3D.MouseDrag += new Ab3d.Common.EventManager3D.MouseDrag3DEventHandler(movableEventSource3D_MouseDrag); _eventManager.RegisterEventSource3D(eventSource3D); }
// Creates EventManager3D and subscribes the 3d objects to events private void SubscribeEvents() { // Create EventManager3D with MainViewport as constructor parameter var eventManager = new Ab3d.Utilities.EventManager3D(MainViewport); // Create EventSource3D for the Landscape // Each 3D object that needs to participate in the events needs to be registered by EventSource3D // The Landscape object will not be subscribed to any event, but instead it is only registered as DragSurface // This means that other objects can be drag over this 3D model. var eventSource = new Ab3d.Utilities.ModelEventSource3D(); eventSource.TargetModel3D = _landscapeModel; eventSource.IsDragSurface = true; // Register the Landscape's EventSource3D eventManager.RegisterEventSource3D(eventSource); // Now for each wind generator create its own EventSource3D object for (int i = 0; i < _windGenerators.Count; i++) { // Create new EventSource3D eventSource = new Ab3d.Utilities.ModelEventSource3D(); // Set the target object to the 3D model eventSource.TargetModel3D = _windGenerators[i].Model; // We can assign any custom data (object) to the EventSource3D // This is very useful because in event handler we can access this custom data eventSource.CustomData = _windGenerators[i]; // Each wind generator is subscribed to the following events: eventSource.MouseEnter += OnWindGeneratorMouseEnter; eventSource.MouseLeave += OnWindGeneratorMouseLeave; eventSource.BeginMouseDrag += OnWindGeneratorBeginMouseDrag; eventSource.MouseDrag += OnWindGeneratorMouseDrag; eventSource.EndMouseDrag += OnWindGeneratorEndMouseDrag; // Not used events: //eventSource.MouseClick += new eventSource_MouseClick; //eventSource.MouseDown += new eventSource_MouseDown; //eventSource.MouseUp += eventSource_MouseUp; // Register the EventSource3D to the EventManager3D eventManager.RegisterEventSource3D(eventSource); } }
private void CreateRandomScene() { SceneObjectsContainer.Children.Clear(); for (int i = 0; i < 10; i++) { var boxModel = new Ab3d.Visuals.BoxVisual3D() { CenterPosition = new Point3D(_rnd.NextDouble() * 400 - 200, _rnd.NextDouble() * 40 - 20, _rnd.NextDouble() * 400 - 200), Size = new Size3D(50, 20, 50), Material = _normalMaterial }; SceneObjectsContainer.Children.Add(boxModel); // Use EventManager from Ab3d.PowerToys to add support for click event on the box model var visualEventSource3D = new Ab3d.Utilities.VisualEventSource3D(boxModel); visualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e) { var selectedBoxModel = e.HitObject as Ab3d.Visuals.BoxVisual3D; SelectObject(selectedBoxModel); }; _eventManager.RegisterEventSource3D(visualEventSource3D); // Automatically select first box if (_selectedBoxModel == null) { SelectObject(boxModel); } } }
private void CreateRandomScene() { SceneObjectsContainer.Children.Clear(); for (int i = 0; i < 10; i++) { // Create simple box that user will be able to rotate // In order to support rotation, we need to create the box at (0,0,0) // and then after performing rotation, translate the object to its final location. // If we would create the object at its final rotation (basically applying translation before rotation), // then the box would not be rotated around its center but around the coordinate axes center. var boxModel = new Ab3d.UIElements.BoxUIElement3D() { CenterPosition = new Point3D(0, 0, 0), Size = new Size3D(50, 20, 50), Material = _normalMaterial }; // Create a StandardTransform3D // StandardTransform3D is a class that generates a MatrixTransform3D based on the translate, rotate and scale transform. // Note that because it is not possible to derive from WPF's Transform3D, the StandardTransform3D is a standalone class // that provides its own MatrixTransform3D object that can be assigned to the 3D model. // Its static SetStandardTransform3D and GetStandardTransform3D use a custom StandardTransform3DProperty // to "attach" the StandardTransform3D object to Model3D or Visual3D. But this does not automatically set the // object's transformation. var standardTransform3D = new StandardTransform3D() { TranslateX = _rnd.NextDouble() * 400 - 200, TranslateY = _rnd.NextDouble() * 40 - 20, TranslateZ = _rnd.NextDouble() * 400 - 200, }; // SetStandardTransform3D method will set the StandardTransform3DProperty to the standardTransform3D // The updateTransform3D argument will also set the boxModel.Transform to standardTransform3D.Transform StandardTransform3D.SetStandardTransform3D(boxModel, standardTransform3D, updateTransform3D: true); SceneObjectsContainer.Children.Add(boxModel); // Use EventManager from Ab3d.PowerToys to add support for click event on the box model var visualEventSource3D = new Ab3d.Utilities.VisualEventSource3D(boxModel); visualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e) { var selectedBoxModel = e.HitObject as Ab3d.UIElements.BoxUIElement3D; SelectObject(selectedBoxModel); }; _eventManager.RegisterEventSource3D(visualEventSource3D); // Automatically select first box if (_selectedBoxModel == null) { boxModel.Refresh(); // Force creating the model SelectObject(boxModel); } } }
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() { _eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport); var wireGridVisual3D = new Ab3d.Visuals.WireGridVisual3D() { Size = new System.Windows.Size(1000, 1000), HeightCellsCount = 10, WidthCellsCount = 10, LineThickness = 3 }; MainViewport.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 }; MainViewport.Children.Add(boxVisual3D); var visualEventSource3D = new VisualEventSource3D(boxVisual3D); visualEventSource3D.MouseEnter += BoxOnMouseEnter; visualEventSource3D.MouseLeave += BoxOnMouseLeave; visualEventSource3D.MouseClick += BoxOnMouseClick; _eventManager3D.RegisterEventSource3D(visualEventSource3D); } } ToggleCameraAnimation(); // Start camer animation }
private void CreateRandomScene() { SceneObjectsContainer.Children.Clear(); for (int i = 0; i < 10; i++) { // Create simple box that user will be able to rotate // In order to support rotation, we need to create the box at (0,0,0) // and then after performing rotation, translate the object to its final location. // If we would create the object at its final rotation (basically applying translation before rotation), // then the box would not be rotated around its center but around the coordinate axes center. var boxModel = new Ab3d.UIElements.BoxUIElement3D() { CenterPosition = new Point3D(0, 0, 0), Size = new Size3D(50, 20, 50), Material = _normalMaterial }; // Create Transform3DGroup that will hold the var transform3DGroup = new Transform3DGroup(); transform3DGroup.Children.Add(new TranslateTransform3D(_rnd.NextDouble() * 400 - 200, _rnd.NextDouble() * 40 - 20, _rnd.NextDouble() * 400 - 200)); boxModel.Transform = transform3DGroup; SceneObjectsContainer.Children.Add(boxModel); // Use EventManager from Ab3d.PowerToys to add support for click event on the box model var visualEventSource3D = new Ab3d.Utilities.VisualEventSource3D(boxModel); visualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e) { var selectedBoxModel = e.HitObject as Ab3d.UIElements.BoxUIElement3D; SelectObject(selectedBoxModel); }; _eventManager.RegisterEventSource3D(visualEventSource3D); // Automatically select first box if (_selectedBoxModel == null) { boxModel.Refresh(); // Force creating the model SelectObject(boxModel); } } }
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 SetModel(Model3D model) { Point3D center; double size; GetModelCenterAndSize(model, out center, out size); Camera1.TargetPosition = center; Camera1.Distance = size * 2; if (!(PreserveModelColorCheckBox.IsChecked ?? false)) { if (model.IsFrozen) { model = model.Clone(); } Ab3d.Utilities.ModelUtils.ChangeMaterial(model, new DiffuseMaterial(Brushes.White), newBackMaterial: null); } _rootModel = model; OriginalModelVisual.Content = model; SelectObject(null); var modelEventSource3D = new ModelEventSource3D(model); modelEventSource3D.MouseLeave += ModelEventSource3DOnMouseLeave; modelEventSource3D.MouseMove += ModelEventSource3DOnMouseMove; _eventManager3D.ResetEventSources3D(); _eventManager3D.RegisterEventSource3D(modelEventSource3D); // Exclude WireframeVisual from hit testing _eventManager3D.RegisterExcludedVisual3D(WireframeVisual); }
private void CreateSceneObjects() { for (int x = 0; x < 10; x++) { for (int y = 0; y < 4; y++) { var boxVisual3D = new Ab3d.Visuals.BoxVisual3D() { CenterPosition = new Point3D(-100 + 20 * x, 50 + y * 30, 0), Size = new Size3D(10, 10, 10), Material = _standardMaterial }; if (x == 4 && y == 2) { boxVisual3D.Material = _selectedMaterial; _selectedModel = boxVisual3D; } SelectionRootModelVisual3D.Children.Add(boxVisual3D); } } var eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport); var multiVisualEventSource3D = new MultiVisualEventSource3D(SelectionRootModelVisual3D.Children); multiVisualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs args) { Mouse.OverrideCursor = Cursors.Hand; }; multiVisualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs args) { Mouse.OverrideCursor = null; }; multiVisualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e) { if (_selectedModel != null) { _selectedModel.Material = _standardMaterial; } var baseModelVisual3D = e.HitObject as Ab3d.Visuals.BaseModelVisual3D; if (baseModelVisual3D != null) { baseModelVisual3D.Material = _selectedMaterial; _selectedModel = baseModelVisual3D; } else { _selectedModel = null; } string logText = string.Format("Camera1.TurnTo(new Point3D({0:0}, {1:0}, {2:0})", e.FinalPointHit.X, e.FinalPointHit.Y, e.FinalPointHit.Z); if (AnimateCheckBox.IsChecked ?? false) { // Animate the camera turn. Animation duration is 0.5 second and use QuadraticEaseInOutFunction for easing. Camera1.TurnTo(position: e.FinalPointHit, animationDurationInMilliseconds: 500, easingFunction: Ab3d.Animation.EasingFunctions.QuadraticEaseInOutFunction); logText += ", 500, QuadraticEaseInOutFunction)"; } else { Camera1.TurnTo(e.FinalPointHit); // Turn immediately logText += ")"; } LogCommandText(logText); // You can also call this with direction vector - for example: //var directionVector = e.FinalPointHit - Camera1.Position; //Camera1.TurnTo(directionVector); }; eventManager3D.RegisterEventSource3D(multiVisualEventSource3D); }
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); } }
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; } }
private void SubscribeEvents() { // Create an instance of EventManager3D for out Viewport3D // Important: // It is highly recommended not to have more than one EventManager3D object per Viewport3D. // Having multiple EventManager3D object can greatly reduce the performance because each time the Viewport3D camera is changed, // each EventManager3D must perform a full 3D hit testing from the current mouse position. // This operation is very CPU intensive and can affect performance when there are many 3D objects in the scene. // When multiple EventManager3D object are defined, then the 3D hit testing is performed multiple times. // Therefore it is recommended to have only one EventManager3D object per Viewport3D. // // It is also recommended to remove registered event sources after they are not used any more. // This can be done with RemoveEventSource3D method. _eventManager = new Ab3d.Utilities.EventManager3D(MainViewport); // Create a NamedObjects dictionary and set it to eventManager. // This way we can use names on EventSource objects to identify Model3D or Visual3D. // This is very usefull if we read the 3d objects with Reader3ds or ReaderObj and already have the NamedObjects dictionry. // When names are used in EventSource objects, we get the HitModelName or HitVisualName property set so we can know which object was hit. var namedObjects = new Dictionary <string, object>(); namedObjects.Add("Landscape", _landscapeModel); namedObjects.Add("Base", _windGenarator.BaseModel); namedObjects.Add("Blades", _windGenarator.BladesModel); namedObjects.Add("Turbine", _windGenarator.TurbineModel); _eventManager.NamedObjects = namedObjects; // subscribe the Landscape as the drag surface var modelEventSource = new Ab3d.Utilities.ModelEventSource3D(); // Instead of using TargetModelName and NamedObjects, we could also specify the model with TargetModel3D //modelEventSource.TargetModel3D = _landscapeModel; modelEventSource.TargetModelName = "Landscape"; modelEventSource.IsDragSurface = true; _eventManager.RegisterEventSource3D(modelEventSource); // subscribe other objects var multiModelEventSource = new Ab3d.Utilities.MultiModelEventSource3D(); // Instead of using TargetModelNames and NamedObjects, we could specify the models with model instances //multiModelEventSource.TargetModels3D = new Model3D[] { _windGenarator.BaseModel, // _windGenarator.BladesModel, // _windGenarator.TurbineModel }; // Because we have set the NamedObjects dictionary to _eventManager we can simply specify the models by their names: multiModelEventSource.TargetModelNames = "Base, Blades, Turbine"; multiModelEventSource.IsDragSurface = false; // Subscribe to all events multiModelEventSource.MouseEnter += eventSource_MouseEnter; multiModelEventSource.MouseLeave += eventSource_MouseLeave; multiModelEventSource.MouseMove += eventSource_MouseMove; multiModelEventSource.MouseUp += eventSource_MouseUp; multiModelEventSource.MouseDown += eventSource_MouseDown; multiModelEventSource.MouseClick += eventSource_MouseClick; multiModelEventSource.MouseWheel += multiModelEventSource_MouseWheel; multiModelEventSource.MouseDoubleClick += eventSource_MouseDoubleClick; multiModelEventSource.BeginMouseDrag += eventSource_BeginMouseDrag; multiModelEventSource.MouseDrag += eventSource_MouseDrag; multiModelEventSource.EndMouseDrag += eventSource_EndMouseDrag; multiModelEventSource.TouchEnter += eventSource_TouchEnter; multiModelEventSource.TouchDown += eventSource_TouchDown; multiModelEventSource.TouchMove += eventSource_TouchMove; multiModelEventSource.TouchUp += eventSource_TouchUp; multiModelEventSource.TouchLeave += eventSource_TouchLeave; // NOTE: // It is also possible to subscribe to touch manipulations events (pinch scale and rotate) // But this requires to set IsManipulationEnabled to true and that disables some other events // See the TouchManipulationsSample for more information _eventManager.RegisterEventSource3D(multiModelEventSource); }
private void CreateScene(bool useDXEngineHitTesting) { ObjectsPlaceholder.Children.Clear(); if (_dxEventManager3D != null) { _dxEventManager3D.ResetEventSources3D(); _dxEventManager3D = null; } if (_wpfEventManager != null) { _wpfEventManager.ResetEventSources3D(); _wpfEventManager = null; } if (_instancedMeshGeometryVisual3D != null) { _instancedMeshGeometryVisual3D.Dispose(); } _stopwatch = new Stopwatch(); _stopwatch.Start(); Mouse.OverrideCursor = Cursors.Wait; // Create InstancedGeometryVisual3D _instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(_instanceMeshGeometry3D); _instancedMeshGeometryVisual3D.InstancesData = _instancedData; // Setup hit testing if (useDXEngineHitTesting) { // Use DXEventManager3D from Ab3d.DXEngine - it has optimized hit testing for instanced objects _dxEventManager3D = new Ab3d.DirectX.Utilities.DXEventManager3D(MainDXViewportView); var visualEventSource3D = new Ab3d.DirectX.Utilities.VisualEventSource3D(_instancedMeshGeometryVisual3D); visualEventSource3D.MouseEnter += delegate(object sender, DirectX.Common.EventManager3D.Mouse3DEventArgs e) { var dxRayInstancedHitTestResult = e.RayHitResult as DXRayInstancedHitTestResult; if (dxRayInstancedHitTestResult != null) { ProcessMouseEnter(dxRayInstancedHitTestResult.HitInstanceIndex); } }; visualEventSource3D.MouseMove += delegate(object sender, DirectX.Common.EventManager3D.Mouse3DEventArgs e) { var dxRayInstancedHitTestResult = e.RayHitResult as DXRayInstancedHitTestResult; if (dxRayInstancedHitTestResult != null) { ProcessMouseMove(dxRayInstancedHitTestResult.HitInstanceIndex); } }; visualEventSource3D.MouseLeave += delegate(object sender, DirectX.Common.EventManager3D.Mouse3DEventArgs e) { ProcessMouseLeave(); }; _dxEventManager3D.RegisterEventSource3D(visualEventSource3D); } else { // // IMPORTANT: // // To make WPF hit testing work (also used by EventManager3D), you need to set the IsWpfHitTestVisible to true. // This increases initialization time because WPF objects needs to be created for each instance, but this makes the WPF hit testing work. _instancedMeshGeometryVisual3D.IsWpfHitTestVisible = true; _wpfEventManager = new Ab3d.Utilities.EventManager3D(MainViewport); // Because Viewport3D is actually not shown, we need to specify different WPF's object for the source of mouse events - this could be MainDXViewportView or even better a parent Border _wpfEventManager.CustomEventsSourceElement = MainDXViewportView; var visualEventSource3D = new Ab3d.Utilities.VisualEventSource3D(_instancedMeshGeometryVisual3D); visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e) { if (e.RayHitResult == null || e.RayHitResult.ModelHit == null) { return; // This should not happen, but it is safer to have this check anyway } // Get instance index of the hit object int hitInstanceIndex = GetHitInstanceIndex(e.RayHitResult); ProcessMouseEnter(hitInstanceIndex); }; visualEventSource3D.MouseMove += delegate(object sender, Mouse3DEventArgs e) { if (e.RayHitResult == null || e.RayHitResult.ModelHit == null) { return; // This should not happen, but it is safer to have this check anyway } // Get instance index of the hit object int hitInstanceIndex = GetHitInstanceIndex(e.RayHitResult); ProcessMouseMove(hitInstanceIndex); }; visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e) { ProcessMouseLeave(); }; _wpfEventManager.RegisterEventSource3D(visualEventSource3D); } ObjectsPlaceholder.Children.Add(_instancedMeshGeometryVisual3D); Mouse.OverrideCursor = null; // If we would only change the InstancedData we would need to call Update method (but here this is not needed because we have set the data for the first time) //_instancedGeometryVisual3D.Update(); }
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 CreateSceneObjects() { for (int y = 0; y < 5; y++) { for (int x = 0; x < 6; x++) { var boxVisual3D = new Ab3d.Visuals.BoxVisual3D() { CenterPosition = new Point3D(40 * x - 100, 6, y * 40 - 80), Size = new Size3D(10, 10, 10), Material = _standardMaterial }; SelectionRootModelVisual3D.Children.Add(boxVisual3D); } } // Use EventManager3D to handle clicking on selected boxes var eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport); var multiVisualEventSource3D = new MultiVisualEventSource3D(SelectionRootModelVisual3D.Children); multiVisualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e) { Mouse.OverrideCursor = Cursors.Hand; var hitBoxVisual3D = e.HitObject as Ab3d.Visuals.BoxVisual3D; if (hitBoxVisual3D != null) { _wireBoxVisual3D.CenterPosition = hitBoxVisual3D.CenterPosition; _wireBoxVisual3D.Size = hitBoxVisual3D.Size; MainViewport.Children.Add(_wireBoxVisual3D); } }; multiVisualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e) { Mouse.OverrideCursor = null; if (_wireBoxVisual3D != null) { MainViewport.Children.Remove(_wireBoxVisual3D); } }; multiVisualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e) { if (_selectedBoxVisual3D != null) { _selectedBoxVisual3D.Material = _standardMaterial; } var hitBoxVisual3D = e.HitObject as Ab3d.Visuals.BoxVisual3D; if (hitBoxVisual3D != null) { hitBoxVisual3D.Material = _selectedMaterial; _selectedBoxVisual3D = hitBoxVisual3D; if (_wireBoxVisual3D != null) { MainViewport.Children.Remove(_wireBoxVisual3D); } MoveCameraTo(hitBoxVisual3D); } else { _selectedBoxVisual3D = null; } }; eventManager3D.RegisterEventSource3D(multiVisualEventSource3D); // Exclude _wireBoxVisual3D from receiving mouse events eventManager3D.RegisterExcludedVisual3D(_wireBoxVisual3D); }
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); } }