0
\$\begingroup\$

I need to make a progress bar in EditorWindow. To do this, I perform the function of calculations in threads: Thread thread = new Thread (_worker.Work); thread.Start (); The class itself emitting calculations looks like this for me (Worker.cs):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Threading;
public class Worker
{
    private bool _cancelled = false;
    public void Cancel() {
        _cancelled = true;
    }
    public void Work() {
        for (int i = 0;i<=100;i++) {
            if(_cancelled)
                break;

            Thread.Sleep(50);
            Debug.Log("i="+i);
            ProcessChanged(i);
        }
        WorkCompleted(_cancelled);
    }
    public event Action<int> ProcessChanged;
    public event Action<bool> WorkCompleted;
}

The PlacementObjects: EditorWindow (PlacementObjects.cs) class looks like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System.IO;
using System.Linq;
using System;
using System.Text.RegularExpressions;
using UnityEditor.IMGUI.Controls;
using UnityEngine.Profiling;
using Newtonsoft.Json;
using System.Threading;

public class PlacementObjects : EditorWindow
{
    private Worker _worker;
    bool pressedbool = false;
    float scaleSlider = 0;
    float scaleMinSlider = 0;
    float scaleMaxSlider = 100;
    [MenuItem("Window/PlacementObjects")]
    static void Init()
    {
        _windowPlacementObj = (PlacementObjects)EditorWindow.GetWindow(typeof(PlacementObjects));
        _windowPlacementObj.titleContent = new GUIContent("Работа с объектами и terrain");
    }
    ...
    void OnGUI()
    {
      DrawFooter();
    }
void DrawFooter()
{

    GUILayout.BeginArea(FooterSection);
        GUILayout.BeginVertical();

            if (!pressedbool)
            {
                GUILayout.Label("Выберите json");
                GUILayout.BeginHorizontal();
                    stringTextFieldURLjsonfile = GUILayout.TextField(stringTextFieldURLjsonfile);
                    if (GUILayout.Button("Обзор...", GUILayout.Width(100)))
                    {
                        stringTextFieldURLjsonfile = EditorUtility.OpenFilePanel("Выбрать json", "", "json");
                    }
                GUILayout.EndHorizontal();
                if (GUILayout.Button("Старт"))
                {
                    _worker = new Worker();
                    _worker.ProcessChanged += worker_ProcessChanged;
                    _worker.WorkCompleted += _worker_WorkCompleted;
                    pressedbool = true;
                    // ProcessJSONPlaceONmap();
                    Thread thread = new Thread(_worker.Work);
                    thread.Start();
                }
            } else {
                if (GUILayout.Button("Стоп"))
                {
                    pressedbool = false;
                }
                scaleSlider = EditorGUI.IntSlider(new Rect(3, 20, position.width - 6, 15), scaleSlider+"%", Mathf.RoundToInt(scaleSlider), scaleMinSlider, scaleMaxSlider);
                EditorGUI.ProgressBar(new Rect(3, 45, position.width - 6, 20), scaleSlider / scaleMaxSlider, scaleSlider+"%");
                Repaint();
            }

        GUILayout.EndVertical();
    GUILayout.EndArea();
}
private void _worker_WorkCompleted(bool cancelled)
{
    Action action = () =>
    {
        string messeg = cancelled ? "Процесс отменён" : "Процесс завершён!";
        Debug.Log("messeg=" + messeg);
        pressedbool = true;
    };

    // if (InvokeRequired)
    //     Invoke(action);
    // else
    //     action();
}
private void worker_ProcessChanged(int progress)
{
    Action action = () => {scaleSlider=progress;};
    // if (InvokeRequired)
    //     Invoke(action);
    // else
    //     action();
    action();
}
}

This code does not update the progress bar.

Found an example of Asynchronous tasks / methods But here it is not clear how to call StartCoroutine (LoadingRoutine ()) from EditorWindow.

\$\endgroup\$
0
\$\begingroup\$

I got this code:

PlacementObjects

namespace marijnz.EditorCoroutines
{
    public class PlacementObjects : EditorWindow
    {
      ...
    private Worker _worker;
    public static bool pressedbool = false;
    private Thread _thread;
    private UnityEngine.Object _locker;
    public static int _progress;

        void DrawFooter()
        {
            GUILayout.BeginArea(FooterSection);
            GUILayout.BeginVertical();
            if (!pressedbool)
            {
                GUILayout.Label("Выберите json");
                GUILayout.BeginHorizontal();
                stringTextFieldURLjsonfile = GUILayout.TextField(stringTextFieldURLjsonfile);
                if (GUILayout.Button("Обзор...", GUILayout.Width(100)))
                {
                    stringTextFieldURLjsonfile = EditorUtility.OpenFilePanel("Выбрать json", "", "json");
                }
                GUILayout.EndHorizontal();
                if (GUILayout.Button("Старт"))
                {

                    pressedbool = true;
                    _worker = new Worker();
                    _worker.ProcessChanged += worker_ProcessChanged;
                    _worker.WorkCompleted += worker_WorkCompleted;
                    Worker._cancelled = false;
                    _thread = new Thread(_worker.Work);
                    _locker = new UnityEngine.Object();
                    _progress = 0;
                    _thread.Start();

                    // if (count_list_index >= 0)
                    // {
                    //     if (myList[count_list_index].geometry_type == 0)
                    //     {
                    //         ProcessJSONPlaceONmapTextures();
                    //     }
                    //     else if (myList[count_list_index].geometry_type == 1)
                    //     {
                    //         ProcessJSONPlaceONmap();
                    //     }
                    // }

                }

            }
            else
            {
                if (GUILayout.Button("Стоп"))
                {
                    pressedbool = false;
                    Worker.Cancel();
                }
                EditorGUI.ProgressBar(new Rect(3, 45, FooterSection.width - 6, 20), _progress / 100.0f, "progress: " + _progress + "%");
            }
            GUILayout.EndVertical();
            GUILayout.EndArea();
        }
        // IEnumerator LoadingRoutine()
        // {
        //     while (_thread.IsAlive)
        //     {
        //         lock (_locker)
        //         {
        //             _progress = EditorGUILayout.IntSlider(Rect(3, 3, position.width - 6, 15), "progress:", _progress, 0, 100);
        //         }
        //         yield return null;
        //     }
        // }
        public static void worker_WorkCompleted(bool cancelled)
        {
            Action action = () =>
            {
                string messeg = cancelled ? "Процесс отменён" : "Процесс завершён!";
                Debug.Log("messeg=" + messeg);
                pressedbool = false;
            };
            action();
            // if (InvokeRequired)
            //     Invoke(action);
            // else
            //     action();
        }
        public static void worker_ProcessChanged(int progress)
        {
            Action action = () => { _progress = progress; };
            // if (InvokeRequired)
            //     Invoke(action);
            // else
            //     action();
            action();
        }
        void OnInspectorUpdate()
        {
            Repaint();
        }
        ...
    }
}

Worker

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Threading;
public class Worker
{
    public static bool _cancelled = false;
    public static void Cancel()
    {
        _cancelled = true;
    }
    public void Work()
    {
        for (int i = 0; i <= 100; i++)
        {
            if (_cancelled)
                break;

            Thread.Sleep(50);
            Debug.Log("i=" + i);
            marijnz.EditorCoroutines.PlacementObjects.worker_ProcessChanged(i);
        }
        marijnz.EditorCoroutines.PlacementObjects.worker_WorkCompleted(_cancelled);
    }
    public event Action<int> ProcessChanged;
    public event Action<bool> WorkCompleted;
}
\$\endgroup\$
3
  • \$\begingroup\$ This answer would be better if it explained how & why this updated code solves the problem. \$\endgroup\$ – DMGregory Dec 16 '19 at 12:32
  • \$\begingroup\$ @DMGregory there is no time to explain in detail what is happening in code. The example is very simple and anyone can test it. Perhaps in a couple of weeks I’ll sit down to edit the answers, but not earlier \$\endgroup\$ – Ivan Triumphov Dec 16 '19 at 12:38
  • \$\begingroup\$ @DMGregory good example and what i wanted to do ru.stackoverflow.com/a/1088121/178835 \$\endgroup\$ – Ivan Triumphov Jul 23 '20 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.