// Event method, which is called regularly, if target object is being or will be processed
        void OnUpdate()
        {
            Rasterizer voxelConverter = (Rasterizer)target;

            // Check if converter engine instance is existing
            if (Rasterizer.Engine.IsActive())
            {
                // Force call of the converter engine update method
                voxelConverter.gameObject.name = voxelConverter.gameObject.name;

                // Force update of the inspector
                Repaint();
            }
            else
            {
                // Remove this method from being called
                EditorApplication.update -= OnUpdate;
            }
        }
Esempio n. 2
0
    // Initialization
    void Start()
    {
        // Create empty array to store target objects, which will have been built from source ones
        targets = new GameObject[sources.Length];

        transformations = new Transformation[sources.Length];

        // Process given source objects
        for (int index = 0; index < sources.Length; ++index)
        {
            // Store rotation, position and scaling of the source
            transformations[index].sourceRotation = sources[index].transform.localRotation;
            transformations[index].sourcePosition = sources[index].transform.localPosition;
            transformations[index].sourceScaling  = sources[index].transform.localScale;

            // Try to get voxel rasterizer component for current source object
            Voxels.Rasterizer rasterizer = sources[index].GetComponent <Voxels.Rasterizer>();
            if (rasterizer != null)
            {
                // Start processing
                rasterizer.Process(ActOnCreation, sources[index]);
            }
            else
            {
                // Use source as target object
                targets[index] = sources[index];

                transformations[index].targetRotation = sources[index].transform.localRotation;
                transformations[index].targetPosition = sources[index].transform.localPosition;
                transformations[index].targetScaling  = sources[index].transform.localScale;
            }

            // Deactive unselected source object
            if (selectedTarget != index)
            {
                sources[index].SetActive(false);
            }
        }

        currentTarget = selectedTarget;
    }
        // Show and process inspector
        public override void OnInspectorGUI()
        {
            string  controlText;
            Bounds  targetBounds = new Bounds();
            Vector3 vector3, voxelSize;
            Vector  volumeResolution;
            int     width, height, depth;

            Rasterizer voxelConverter = (Rasterizer)target;

            //Rect rect = GUILayoutUtility.GetLastRect();
            //EditorGUI.DropShadowLabel(rect, "Voxels for Unity");
            //EditorGUILayout.GetControlRect();

            //GUIContent content = EditorGUIUtility.ObjectContent(null, typeof(ConverterEditor));
            //if (content != null)
            //{
            //    content.image = null;
            //}

            Vector3 minimum = voxelConverter.minimumBound;
            Vector3 maximum = voxelConverter.maximumBound;

            // Button to recompute scan area
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Boundaries:");
            if (GUILayout.Button("Adopt from object") || (voxelConverter.minimumBound == Vector3.one && voxelConverter.maximumBound == -Vector3.one))
            {
                Undo.RecordObject(voxelConverter, "Bound Adoption");
                voxelConverter.RecomputeBounds();
                minimum = voxelConverter.minimumBound;
                maximum = voxelConverter.maximumBound;
            }
            EditorGUILayout.EndHorizontal();

            // Add title to bar
            Rect rect = GUILayoutUtility.GetLastRect();

            rect.x += EditorGUIUtility.currentViewWidth * 0.5f;
            rect.y -= rect.height;
            EditorGUI.LabelField(rect, Information.Title);

            // Fields to change boundaries
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("    Minimum", GUILayout.MaxWidth(96));
            minimum = EditorGUILayout.Vector3Field("", minimum);
            maximum = Vector3.Max(minimum, maximum);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("    Maximum", GUILayout.MaxWidth(96));
            maximum = EditorGUILayout.Vector3Field("", maximum);
            minimum = Vector3.Min(minimum, maximum);
            EditorGUILayout.EndHorizontal();

            // Sort components
            vector3 = Vector3.Min(minimum, maximum);
            minimum = vector3;

            // Store new boundaries
            if (minimum != voxelConverter.minimumBound)
            {
                Undo.RecordObject(voxelConverter, "Minimum Bound");
                voxelConverter.minimumBound = minimum;
            }
            if (maximum != voxelConverter.maximumBound)
            {
                Undo.RecordObject(voxelConverter, "Maximum Bound");
                voxelConverter.maximumBound = maximum;
            }

            // Compute center and size
            targetBounds.center  = (minimum + maximum) * 0.5f;
            targetBounds.extents = maximum - minimum;

            // Get voxel size
            voxelSize = voxelConverter.GetVoxelSize(targetBounds.extents);

            // Field to change size of one voxel
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Voxel Size", GUILayout.MaxWidth(96));
            vector3 = EditorGUILayout.Vector3Field("", voxelSize);
            EditorGUILayout.EndHorizontal();

            // Store voxel size, if it has been changed
            if (vector3 != voxelSize)
            {
                Undo.RecordObject(voxelConverter, "Voxel Size Change");
                if (voxelConverter.SetVoxelSize(vector3.x, vector3.y, vector3.z))
                {
                    voxelSize = vector3;
                }
            }

            // Compute volume resolution, if it is not set
            volumeResolution = voxelConverter.GetVolumeResolution(targetBounds.extents);

            // Edit number of voxels
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Voxel Counts", GUILayout.MaxWidth(96));
            //EditorGUILayout.LabelField("X", GUILayout.MaxWidth(12));
            width = EditorGUILayout.IntField(volumeResolution.x, GUILayout.MinWidth(32));
            //EditorGUILayout.LabelField("Y", GUILayout.MaxWidth(12));
            height = EditorGUILayout.IntField(volumeResolution.y, GUILayout.MinWidth(32));
            //EditorGUILayout.LabelField("Z", GUILayout.MaxWidth(12));
            depth = EditorGUILayout.IntField(volumeResolution.z, GUILayout.MinWidth(32));
            EditorGUILayout.EndHorizontal();

            // Store volume resolution, if it has been changed
            if (width != volumeResolution.x || height != volumeResolution.y || depth != volumeResolution.z)
            {
                Undo.RecordObject(voxelConverter, "Voxel Resolution Change");
                if (voxelConverter.SetVolumeResolution(width, height, depth))
                {
                    volumeResolution = new Vector(width, height, depth);
                }
            }

            // Determine maximum sampling
            int samplingLimit = Rasterizer.Engine.TextureSizeLimit / Mathf.Max(Mathf.Max(volumeResolution.x, volumeResolution.y), volumeResolution.z);

            // Build resolution vector, sampling slider, color baking toggle mode with combo box
            int samplingResolution = EditorGUILayout.IntSlider("Sampling Resolution", voxelConverter.samplingResolution, 1, samplingLimit);

            if (voxelConverter.samplingResolution != samplingResolution)
            {
                Undo.RecordObject(voxelConverter, "Sampling Resolution Change");
                voxelConverter.samplingResolution = samplingResolution;
            }

            float oldVoxelOverscan = voxelConverter.voxelOverscan * 100.0f;
            float newVoxelOverscan = NonLinearHorizontalSlider("Voxel Overscan", oldVoxelOverscan, ref overscanInput, "%", overscanSliderSteps);

            //// Create own combination of edit field and non-linear slider
            //EditorGUILayout.BeginHorizontal();
            //EditorGUILayout.LabelField("Voxel Overscan", GUILayout.MinWidth(108), GUILayout.MaxWidth(116));
            //int oldVoxelOverscan = (int)(voxelConverter.voxelOverscan * 100.0f + 0.5f);
            //int newVoxelOverscan = EditorGUILayout.IntField(oldVoxelOverscan, GUILayout.MinWidth(24), GUILayout.MaxWidth(48));
            //EditorGUILayout.LabelField("%", GUILayout.MinWidth(20), GUILayout.MaxWidth(24));
            //newVoxelOverscan = (int)(SliderToValue(GUILayout.HorizontalSlider(ValueToSlider(newVoxelOverscan, overscanSliderSteps), 0, ValueToSlider(1000000, overscanSliderSteps)), overscanSliderSteps));
            //EditorGUILayout.EndHorizontal();

            // Store new value
            if (oldVoxelOverscan != newVoxelOverscan)
            {
                Undo.RecordObject(voxelConverter, "Voxel Overscan Change");
                voxelConverter.voxelOverscan = (float)newVoxelOverscan * 0.01f;
            }

            BakingOperation bakingOperationMode = (BakingOperation)EditorGUILayout.IntPopup("Baking Mode", (int)voxelConverter.bakingOperationMode, Rasterizer.BakingOperationModeNames, Rasterizer.BakingOperationModes);

            if (voxelConverter.bakingOperationMode != bakingOperationMode)
            {
                Undo.RecordObject(voxelConverter, "Baking Operation Mode Change");
                voxelConverter.bakingOperationMode = bakingOperationMode;
            }
            switch (bakingOperationMode)
            {
            case BakingOperation.OriginalMaterial:
                break;

            default:
                // Object selection of materials to use for opaque and transparent voxels
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("", GUILayout.MaxWidth(16));
                Material templateMaterial = (Material)EditorGUILayout.ObjectField("Opaque Template", voxelConverter.opaqueTemplate, typeof(Material), true);
                if (voxelConverter.opaqueTemplate != templateMaterial)
                {
                    Undo.RecordObject(voxelConverter, "Opaque Template Material Change");
                    voxelConverter.opaqueTemplate = templateMaterial;
                }
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("", GUILayout.MaxWidth(16));
                templateMaterial = (Material)EditorGUILayout.ObjectField("Transparent Template", voxelConverter.transparentTemplate, typeof(Material), true);
                if (voxelConverter.transparentTemplate != templateMaterial)
                {
                    Undo.RecordObject(voxelConverter, "Transparent Template Material Change");
                    voxelConverter.transparentTemplate = templateMaterial;
                }
                EditorGUILayout.EndHorizontal();

                // Flags to modulate material components
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("", GUILayout.MaxWidth(16));
                bool mainColorModulation = EditorGUILayout.ToggleLeft("Main Color", voxelConverter.mainColorModulation, GUILayout.MaxWidth(128));
                if (voxelConverter.mainColorModulation != mainColorModulation)
                {
                    Undo.RecordObject(voxelConverter, "Main Color Flag Change");
                    voxelConverter.mainColorModulation = mainColorModulation;
                }
                bool specularColorModulation = EditorGUILayout.ToggleLeft("Specular Color", voxelConverter.specularColorModulation, GUILayout.MaxWidth(128));
                if (voxelConverter.specularColorModulation != specularColorModulation)
                {
                    Undo.RecordObject(voxelConverter, "Specular Color Flag Change");
                    voxelConverter.specularColorModulation = specularColorModulation;
                }
                bool emissiveColorModulation = EditorGUILayout.ToggleLeft("Emissive Color", voxelConverter.emissiveColorModulation, GUILayout.MaxWidth(128));
                if (voxelConverter.emissiveColorModulation != emissiveColorModulation)
                {
                    Undo.RecordObject(voxelConverter, "Emissive Color Flag Change");
                    voxelConverter.emissiveColorModulation = emissiveColorModulation;
                }
                EditorGUILayout.EndHorizontal();

                //if (mainColorModulation || specularColorModulation || emissiveColorModulation)
                {
                    // Fields for color modulation
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("", GUILayout.MaxWidth(32));
                    float saturationFactor = EditorGUILayout.FloatField("Saturation", voxelConverter.saturationFactor, GUILayout.MaxWidth(320));
                    if (GUILayout.Button("Reset"))
                    {
                        saturationFactor = 1;
                    }
                    if (voxelConverter.saturationFactor != saturationFactor)
                    {
                        Undo.RecordObject(voxelConverter, "Color Saturation Change");
                        voxelConverter.saturationFactor = saturationFactor;
                    }
                    EditorGUILayout.EndHorizontal();
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("", GUILayout.MaxWidth(32));
                    float brightnessFactor = EditorGUILayout.FloatField("Brightness", voxelConverter.brightnessFactor, GUILayout.MaxWidth(320));
                    if (GUILayout.Button("Reset"))
                    {
                        brightnessFactor = 1;
                    }
                    if (voxelConverter.brightnessFactor != brightnessFactor)
                    {
                        Undo.RecordObject(voxelConverter, "Color Brightness Change");
                        voxelConverter.brightnessFactor = brightnessFactor;
                    }
                    EditorGUILayout.EndHorizontal();
                }
                break;
            }

            // Get current processing state
            processingProgress = voxelConverter.GetProgress();

            // Check if game is not running
            if (!Application.isPlaying)
            {
                // Processing button with dynamic text depending on current progress
                controlText =
                    processingProgress > 1 ? "Waiting... [" + (int)processingProgress + "]" :
                    processingProgress >= 0 ? "Processing... [" + (int)((1 - processingProgress) * 100) + " %]" :
                    "Process";
                if (GUILayout.Button(controlText))
                {
                    // Check if object is already being processed or will be
                    if (processingProgress >= 0)
                    {
                        // Stop processing
                        if (voxelConverter.Stop())
                        {
                            // Unset progress
                            processingProgress = -1;
                        }
                    }
                    else
                    {
                        // Start processing
                        if (voxelConverter.Process())
                        {
                            // Add update callback
                            EditorApplication.update += OnUpdate;
                        }
                    }
                }
            }
            else
            {
                // Check if object is already being processed or will be
                if (processingProgress >= 0)
                {
                    controlText =
                        processingProgress > 1 ? "Waiting... [" + (int)processingProgress + "]" :
                        "Processing... [" + (int)((1 - processingProgress) * 100) + " %]";

                    // Output progress
                    GUILayout.Space(EditorGUIUtility.standardVerticalSpacing);
                    Rect rectangle = EditorGUILayout.BeginVertical();
                    EditorGUI.ProgressBar(rectangle, processingProgress == 1 ? 0 : 1 - processingProgress % 1, controlText);
                    GUILayout.Space(EditorGUIUtility.singleLineHeight);
                    EditorGUILayout.EndVertical();
                    GUILayout.Space(EditorGUIUtility.standardVerticalSpacing);

                    EditorUtility.SetDirty(voxelConverter);
                }
            }

            int oldValue, newValue;

            // Read current frame time target from preferences
            oldValue = (int)(EditorPrefs.GetFloat("VoxelConvertBudgetTime", voxelConverter.budgetTime) * 1000.0f + 0.5f);
            //oldValue = (int)(Converter.budgetTime * 1000.0f + 0.5f);

            //// Convert value to string
            //if (oldValue >= timeSliderSteps[timeSliderSteps.Length - 1].limit)
            //{
            //    controlText = "max";
            //}
            //else
            //{
            //    controlText = oldValue.ToString();
            //}

            //// Create own combination of edit field and non-linear slider
            //EditorGUILayout.BeginHorizontal();
            //EditorGUILayout.LabelField("Frame Time Target", GUILayout.MinWidth(108), GUILayout.MaxWidth(116));
            //if (!int.TryParse(controlText = GUILayout.TextField(controlText, GUILayout.MinWidth(24), GUILayout.MaxWidth(48)), out newValue))
            //{
            //    // Convert text to new value
            //    if (controlText.ToLower() == "max")
            //    {
            //        newValue = (int)timeSliderSteps[timeSliderSteps.Length - 1].limit;
            //    }
            //    else if (controlText.Length == 0)
            //    {
            //        newValue = 0;
            //    }
            //    else
            //    {
            //        newValue = oldValue;
            //    }
            //}
            //EditorGUILayout.LabelField("ms", GUILayout.MinWidth(20), GUILayout.MaxWidth(24));
            //int intermediateValue = (int)SliderToValue(ValueToSlider(newValue, timeSliderSteps), timeSliderSteps);
            //int temporaryValue = (int)(SliderToValue(GUILayout.HorizontalSlider(ValueToSlider(newValue, timeSliderSteps), 0, ValueToSlider(1000000, timeSliderSteps)), timeSliderSteps));
            //EditorGUILayout.EndHorizontal();

            //// Store value to instance and preferences, if it has been changed
            //if (intermediateValue != temporaryValue)
            //{
            //    newValue = temporaryValue;
            //}

            newValue = (int)(NonLinearHorizontalSlider("Frame Time Target", oldValue, ref frametimeTargetInput, "ms", timeSliderSteps, false, true, true) + 0.5f);
            if (oldValue != newValue)
            {
                Undo.RecordObject(voxelConverter, "Frame Time Target Change");
                voxelConverter.budgetTime = (float)newValue * 0.001f;
                EditorPrefs.SetFloat("VoxelConvertBudgetTime", voxelConverter.budgetTime);
            }

            bool oldFlag = EditorPrefs.GetBool("VoxelConvertMultiThreading", voxelConverter.multiThreading);
            bool newFlag;

            // Create toggle for multi-threading
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Multi Threading", GUILayout.MinWidth(108), GUILayout.MaxWidth(116));
            newFlag = EditorGUILayout.Toggle(oldFlag);
            EditorGUILayout.EndHorizontal();

            if (newFlag != oldFlag)
            {
                Undo.RecordObject(voxelConverter, "Multi Threading Change");
                voxelConverter.multiThreading = newFlag;
                EditorPrefs.SetBool("VoxelConvertMultiThreading", voxelConverter.multiThreading);
            }

            long sampledWidth, sampledHeight, sampledDepth, size;

            // Compute total size of the volume including sampling
            sampledWidth  = volumeResolution.x * voxelConverter.samplingResolution;
            sampledHeight = volumeResolution.y * voxelConverter.samplingResolution;
            sampledDepth  = volumeResolution.z * voxelConverter.samplingResolution;

            // Estimate highest amount of memory, which is required to store information to all possible voxels
            size = Storage.ComputeMaximumSize(width, height, depth, voxelConverter.samplingResolution, voxelConverter.bakingOperationMode == BakingOperation.OriginalMaterial);

            // Output information
            controlText = string.Format("Object Extent: {0:F} x {1:F} x {2:F}"
                                        + "\nRasterization: {3:##,#} x {5:##,#} x {7:##,#}" //   [{4:##,#} x {6:##,#} x {8:##,#}]"
                                        + "\nVoxels Count: {12}{9:##,#}"                    //   [{10:##,#}]"
                                        , targetBounds.extents.x, targetBounds.extents.y, targetBounds.extents.z
                                        , width, sampledWidth, height, sampledHeight, depth, sampledDepth
                                        , width * height * depth, sampledWidth * sampledHeight * sampledDepth
                                        , size
                                        , "max. ", "max. "
                                        );
            EditorGUILayout.HelpBox(controlText, MessageType.None);
        }