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\$

1 Answer 1

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, 2019 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\$ Dec 16, 2019 at 12:38
  • \$\begingroup\$ @DMGregory good example and what i wanted to do ru.stackoverflow.com/a/1088121/178835 \$\endgroup\$ Jul 23, 2020 at 14:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .