Exemple #1
0
        private Entity CreateOriginAxis(Color color, int axis)
        {
            var axisColor = color.ToColor3();

            if (GraphicsDevice != null)
            {
                axisColor = color.ToColor3().ToColorSpace(GraphicsDevice.ColorSpace);
            }

            var gridTexture  = CreateTexture(GenerateAxisImage);
            var axisMaterial = CreateColoredTextureMaterial(gridTexture, 1);

            axisMaterial.Passes[0].Parameters.Set(TexturingKeys.Texture0, gridTexture);
            axisMaterial.Passes[0].Parameters.Set(MaterialKeys.Sampler.ComposeWith("i0"), GraphicsDevice.SamplerStates.AnisotropicWrap);
            axisMaterial.Passes[0].Parameters.Set(GridColorKey, Color4.PremultiplyAlpha(new Color4(axisColor, 1f)));

            var axisEntity = new Entity("Scene grid origin axis")
            {
                new ModelComponent
                {
                    Model = new Model
                    {
                        axisMaterial,
                        new Mesh {
                            Draw = GeometricPrimitive.Plane.New(GraphicsDevice, GridBase, GridBase).ToMeshDraw()
                        }
                    },
                    RenderGroup = RenderGroup,
                }
            };

            axisEntity.TransformValue.Scale = new Vector3(GridSize, 1f / GridBase, 1f / GridBase);
            if (axis != 0)
            {
                axisEntity.TransformValue.Rotation = Quaternion.RotationX(MathUtil.PiOverTwo) * Quaternion.RotationAxis(new Vector3 {
                    [1 + (axis % 2)] = 1f
                }, MathUtil.PiOverTwo);
            }

            var axisEntityRoot = new Entity("Scene grid origin axis root");

            axisEntityRoot.AddChild(axisEntity);

            return(axisEntityRoot);
        }
        /// <summary>
        /// Highlights the given material, but only within the given entity.
        /// </summary>
        /// <param name="entity">The entity in which to highlight the given material. This method does nothing if it's null.</param>
        /// <param name="materialIndex">The index of the material to highlight in the given entity.</param>
        internal void HighlightMaterial(Entity entity, int materialIndex)
        {
            editor.Controller.EnsureGameAccess();
            lock (lockObject)
            {
                if (entity == null || materialIndex < 0)
                {
                    return;
                }

                var modelComponent = entity.Get <ModelComponent>();
                if (modelComponent?.Model == null)
                {
                    return;
                }

                var material = modelComponent.GetMaterial(materialIndex);
                if (material == null)
                {
                    return;
                }

                editor.Controller.InvokeAsync(() =>
                {
                    HighlightRenderFeature.MaterialsHighlightedForModel.Add(material);
                    highlightedMaterials.Add(material);

                    HighlightRenderFeature.ModelHighlightColors[modelComponent] = Color4.PremultiplyAlpha(AssetHighlighter.DirectReferenceColor);
                    highlightedModelComponents.Add(modelComponent);

                    foreach (var selectedEntity in Selection.GetSelectedIds().Select(x => editor.Controller.FindGameSidePart(x)).Cast <Entity>())
                    {
                        modelComponent = selectedEntity.Get <ModelComponent>();
                        if (modelComponent?.Model == null)
                        {
                            continue;
                        }

                        HighlightRenderFeature.ModelHighlightColors[modelComponent] = Color4.PremultiplyAlpha(AssetHighlighter.DirectReferenceColor);
                        highlightedModelComponents.Add(modelComponent);
                    }
                });
            }
        }
Exemple #3
0
        private async Task HighlightMaterial(Game game, Material material, float duration)
        {
            // TODO: this could be factorized between the different highlighters
            if (material == null)
            {
                return;
            }

            var currentTime = 0.0f;

            while (game.IsRunning)
            {
                Color4 color;
                lock (highlightedMaterials)
                {
                    if (!highlightedMaterials.TryGetValue(material, out color))
                    {
                        HighlightRenderFeature.MaterialHighlightColors.Remove(material);
                        return;
                    }
                }
                var ratio = duration >= 0 ? 1.0f - currentTime / duration : 1.0f;
                if (ratio <= 0.0f)
                {
                    lock (highlightedMaterials)
                    {
                        highlightedMaterials.Remove(material);
                    }
                    HighlightRenderFeature.MaterialHighlightColors.Remove(material);
                    return;
                }

                var currentColor = new Color4(color.R, color.G, color.B, color.A * ratio);
                HighlightRenderFeature.MaterialHighlightColors[material] = Color4.PremultiplyAlpha(currentColor);

                await game.Script.NextFrame();

                currentTime += (float)game.UpdateTime.Elapsed.TotalSeconds;
            }
        }
Exemple #4
0
        protected override void UpdateBase(Color3 gridColor, float sceneUnit)
        {
            var cameraService = Game.EditorServices.Get <IEditorGameCameraService>();

            if (cameraService == null)
            {
                return;
            }

            // update the grid color
            GridMaterial.Passes[0].Parameters.Set(GridColorKey, Color4.PremultiplyAlpha(new Color4(gridColor, 0.35f)));

            // Determine the up vector depending on view matrix and projection mode
            // -> When orthographic, if we are looking along a coordinate axis, place the grid perpendicular to that axis.
            // -> Fall back to the default plane otherwise.
            var viewAxisIndex = 1;
            var upVector      = DefaultUpVector;
            var viewInvert    = Matrix.Invert(cameraService.ViewMatrix);

            if (cameraService.IsOrthographic)
            {
                for (var i = 0; i < 3; i++)
                {
                    var coordinateAxis = new Vector3 {
                        [i] = 1.0f
                    };
                    var dotProduct = Vector3.Dot(viewInvert.Forward, coordinateAxis);

                    if (Math.Abs(dotProduct) > 0.99f)
                    {
                        upVector      = coordinateAxis;
                        viewAxisIndex = i;
                    }
                }
            }

            // Check if the inverted View Matrix is valid (since it will be use for mouse picking, check the translation vector only)
            if (float.IsNaN(viewInvert.TranslationVector.X) ||
                float.IsNaN(viewInvert.TranslationVector.Y) ||
                float.IsNaN(viewInvert.TranslationVector.Z))
            {
                return;
            }

            // The position of the grid and the origin in the scene
            var snappedPosition = Vector3.Zero;
            var originPosition  = Vector3.Zero;

            // Add a small offset along the Up axis to avoid depth-fight with objects positioned at height=0
            snappedPosition[viewAxisIndex] = Math.Sign(viewInvert[3, viewAxisIndex]) * GridVerticalOffset * sceneUnit;

            // Move the grid origin in slightly in front the grid to have it in the foreground
            originPosition[viewAxisIndex] = snappedPosition[viewAxisIndex] + Math.Sign(viewInvert[3, viewAxisIndex]) * 0.001f * sceneUnit;

            // In orthographic mode, put the grid and origin in the very background of scene
            if (cameraService.IsOrthographic)
            {
                var dotProduct   = Vector3.Dot(viewInvert.Forward, upVector);
                var cameraOffset = viewInvert.TranslationVector[viewAxisIndex];
                originPosition[viewAxisIndex]  = cameraOffset + Math.Sign(dotProduct) * cameraService.FarPlane * 0.90f;
                snappedPosition[viewAxisIndex] = cameraOffset + Math.Sign(dotProduct) * cameraService.FarPlane * 0.95f;
            }

            // Determine the intersection point of the center of the vieport with the grid plane
            var ray          = EditorGameHelper.CalculateRayFromMousePosition(cameraService.Component, new Vector2(0.5f), viewInvert);
            var plane        = new Plane(Vector3.Zero, upVector);
            var intersection = EditorGameHelper.ProjectOnPlaneWithLimitAngle(ray, plane, MaximumViewAngle);

            // Detemine the scale of the grid depending of the distance of the camera to the grid plane
            // For orthographic projections, use a distance close to the one, at which the perspective projection would map to the viewport area.
            var gridScale      = sceneUnit;
            var distanceToGrid = cameraService.IsOrthographic ? cameraService.Component.OrthographicSize * 1.5f : (viewInvert.TranslationVector - intersection).Length();

            if (distanceToGrid < 1.5f * sceneUnit)
            {
                gridScale = 0.1f * sceneUnit;
            }
            if (distanceToGrid > 40f * sceneUnit)
            {
                gridScale = 10f * sceneUnit;
            }
            if (distanceToGrid > 400f * sceneUnit)
            {
                gridScale = 100f * sceneUnit;
            }

            // Snap the grid the closest possible to the intersection point
            var gridStringLineUnit = gridScale;

            for (var i = 0; i < 3; i++)
            {
                if (viewAxisIndex != i)
                {
                    snappedPosition[i] += (float)Math.Round(intersection[i] / gridStringLineUnit) * gridStringLineUnit;
                }
            }

            // Apply positions
            grid.Transform.Position            = snappedPosition;
            originAxis.TransformValue.Position = originPosition;
            for (int axis = 0; axis < 3; axis++)
            {
                originAxes[axis].TransformValue.Position[axis] = snappedPosition[axis];
            }

            // Apply the scale (Note: scale cannot be applied at root or sub-position is scaled too)
            grid.Transform.Scale = new Vector3(gridScale);
            for (int axis = 0; axis < 3; axis++)
            {
                originAxes[axis].TransformValue.Scale = new Vector3(gridScale);
            }

            // Determine and apply the rotation to the grid and origin axis entities
            SetPlaneEntityRotation(2, upVector, grid);
            for (var axis = 0; axis < 3; axis++)
            {
                SetPlaneEntityRotation((axis + 2) % 3, upVector, originAxes[axis]);
            }

            // Hide the vertical axis of the origin
            for (int axis = 0; axis < 3; axis++)
            {
                originAxes[axis].GetChild(0).Get <ModelComponent>().Enabled = axis != viewAxisIndex;
            }
        }