private void OnGUI() { DrawWindow(); if (repaint) DrawWindow(); repaint = false; } //drawing window, or doing it twice if repaint is needed private void DrawWindow() { if (gens == null) return; //un-selecting field on drag #if !UNITY_EDITOR_LINUX if (Event.current.button != 0 && UnityEngine.GUI.GetNameOfFocusedControl() != "Temp") RemoveFocusOnControl(); #endif //startingscript.layout if (gens.layout==null) { gens.layout = new Layout(); gens.layout.scroll = gens.guiScroll; gens.layout.zoom = gens.guiZoom; gens.layout.maxZoom = 1f; } gens.layout.Zoom(); gens.layout.Scroll(); //scrolling and zooming if (gens.layout.zoom < 0.0001f) gens.layout.zoom = 1; gens.layout.field = this.position; //zoomning with keyboard if (Event.current.type == EventType.KeyDown) { if (Event.current.keyCode==KeyCode.Equals && Event.current.alt) { gens.layout.zoom += gens.layout.zoomStep; if (gens.layout.zoom>1) gens.layout.zoom=1; Event.current.Use(); } if (Event.current.keyCode==KeyCode.Minus && Event.current.alt) { gens.layout.zoom -= gens.layout.zoomStep; Event.current.Use(); } } //unity 5.4 beta if (Event.current.type == EventType.Layout) return; if (Event.current.type == EventType.MouseDrag) //skip all mouse drags (except when dragging text selection cursor in field) { if (!UnityEditor.EditorGUIUtility.editingTextField) return; if (UnityEngine.GUI.GetNameOfFocusedControl() == "Temp") return; } //using middle mouse click events if (Event.current.button == 2) Event.current.Use(); //undo Undo.undoRedoPerformed -= PerformUndo; Undo.undoRedoPerformed += PerformUndo; //setting title content titleContent = new GUIContent("Map Magic"); titleContent.image =gens.layout.GetIcon("MapMagic_WindowIcon"); //drawing background Vector2 windowZeroPos =gens.layout.ToInternal(Vector2.zero); windowZeroPos.x = ((int)(windowZeroPos.x/64f)) * 64; windowZeroPos.y = ((int)(windowZeroPos.y/64f)) * 64; Texture2D backTex = gens.layout.GetIcon("MapMagic_Background"); Rect backRect = new Rect(windowZeroPos - new Vector2(64,64), position.size + new Vector2(127,127)); UnityEditor.EditorGUI.DrawPreviewTexture(new Rect(0,0,position.width,position.height), backTex, null, ScaleMode.ScaleAndCrop); gens.layout.Icon(backTex, backRect, tile:true); //drawing test center //script.layout.Button("Zero", new Rect(-10,-10,20,20)); //calculating visible area Rect visibleArea = gens.layout.ToInternal( new Rect(0,0,position.size.x,position.size.y) ); if (forceAll) { visibleArea = new Rect(-200000,-200000,400000,400000); forceAll = false; } //visibleArea = new Rect(visibleArea.x+100, visibleArea.y+100, visibleArea.width-200, visibleArea.height-200); //layout.Label("Area", helpBox:true, rect:visibleArea); //checking if all generators are loaded, and none of them is null for (int i=gens.list.Length-1; i>=0; i--) { if (gens.list[i] == null) { ArrayTools.RemoveAt(ref gens.list, i); continue; } foreach (Generator.Input input in gens.list[i].Inputs()) { if (input == null) continue; if (input.linkGen == null) input.Link(null, null); } } #region Drawing groups for(int i=0; i<gens.list.Length; i++) { if (!(gens.list[i] is Group)) continue; Group group = gens.list[i] as Group; //checking if this is withinscript.layout field if (group.guiRect.x > visibleArea.x+visibleArea.width || group.guiRect.y > visibleArea.y+visibleArea.height || group.guiRect.x+group.guiRect.width < visibleArea.x || group.guiRect.y+group.guiRect.height < visibleArea.y) if (group.guiRect.width > 0.001f && gens.layout.dragState != Layout.DragState.Drag) continue; //if guiRect initialized and not dragging //settingscript.layout data group.layout.field = group.guiRect; group.layout.scroll = gens.layout.scroll; group.layout.zoom = gens.layout.zoom; group.OnGUI(gens); group.guiRect = group.layout.field; } #endregion #region Drawing connections (before generators to make them display under nodes) foreach(Generator gen in gens.list) { foreach (Generator.Input input in gen.Inputs()) { if (input==null || input.link == null) continue; //input could be null in layered generators if (gen is Portal) { Portal portal = (Portal)gen; if (!portal.drawInputConnection) continue; } gens.layout.Spline(input.link.guiConnectionPos, input.guiConnectionPos, color:GeneratorsAsset.CanConnect(input.link,input)? input.guiColor : Color.red); } } #endregion #region creating connections (after generators to make clicking in inout work) int dragIdCounter = gens.list.Length+1; foreach (Generator gen in gens.list) foreach (Generator.IGuiInout inout in gen.Inouts()) { if (inout == null) continue; if (gens.layout.DragDrop(inout.guiRect, dragIdCounter)) { //finding target Generator.IGuiInout target = null; foreach (Generator gen2 in gens.list) foreach (Generator.IGuiInout inout2 in gen2.Inouts()) if (inout2.guiRect.Contains(gens.layout.dragPos)) target = inout2; //converting inout to Input (or Output) and target to Output (or Input) Generator.Input input = inout as Generator.Input; if (input==null) input = target as Generator.Input; Generator.Output output = inout as Generator.Output; if (output==null) output = target as Generator.Output; //connection validity test bool canConnect = input!=null && output!=null && GeneratorsAsset.CanConnect(output,input); //infinite loop test if (canConnect) { Generator outputGen = output.GetGenerator(gens.list); Generator inputGen = input.GetGenerator(gens.list); if (inputGen == outputGen || gens.CheckDependence(inputGen,outputGen)) canConnect = false; } //drag //if (script.layout.dragState==Layout.DragState.Drag) //commented out because will not be displayed on repaint otherwise //{ if (input == null)gens.layout.Spline(output.guiConnectionPos,gens.layout.dragPos, color:Color.red); else if (output == null)gens.layout.Spline(gens.layout.dragPos, input.guiConnectionPos, color:Color.red); else gens.layout.Spline(output.guiConnectionPos, input.guiConnectionPos, color:canConnect? input.guiColor : Color.red); //} //release if (gens.layout.dragState==Layout.DragState.Released && input!=null) //on release. Do nothing if input not defined { Undo.RecordObject (gens, "MapMagic Connection"); gens.setDirty = !gens.setDirty; input.Unlink(); if (canConnect) input.Link(output, output.GetGenerator(gens.list)); if (mapMagic!=null) { mapMagic.ClearResults(gen); mapMagic.Generate(); } EditorUtility.SetDirty(gens); } } dragIdCounter++; } #endregion #region Drawing generators for(int i=0; i<gens.list.Length; i++) { Generator gen = gens.list[i]; if (gen is Group) continue; //skipping groups //checking if this generator is withinscript.layout field if (gen.guiRect.x > visibleArea.x+visibleArea.width || gen.guiRect.y > visibleArea.y+visibleArea.height || gen.guiRect.x+gen.guiRect.width < visibleArea.x || gen.guiRect.y+gen.guiRect.height < visibleArea.y) if (gen.guiRect.width > 0.001f && gens.layout.dragState != Layout.DragState.Drag) continue; //if guiRect initialized and not dragging if (gen.layout == null) gen.layout = new Layout(); gen.layout.field = gen.guiRect; gen.layout.field.width = 160; //MapMagic.instance.guiGeneratorWidth; //gen.layout.OnBeforeChange -= RecordGeneratorUndo; //gen.layout.OnBeforeChange += RecordGeneratorUndo; gen.layout.undoObject = gens; gen.layout.undoName = "MapMagic Generators Change"; gen.layout.dragChange = true; gen.layout.disabled = changeLock; //copyscript.layout params gen.layout.scroll = gens.layout.scroll; gen.layout.zoom = gens.layout.zoom; //drawing background gen.layout.Element("MapMagic_Window", gen.layout.field, new RectOffset(34,34,34,34), new RectOffset(33,33,33,33)); //resetting layout gen.layout.field.height = 0; gen.layout.field.width =160; gen.layout.cursor = new Rect(); gen.layout.change = false; gen.layout.margin = 1; gen.layout.rightMargin = 1; gen.layout.fieldSize = 0.4f; //drawing header gen.DrawHeader (mapMagic, gens); if (gen is OutputGenerator && gen.layout.change && gen.enabled == false) //if just disabled output gensBiomeHierarchy[0].OnDisableGenerator(gen); //drawing parameters #if WDEBUG gen.OnGUI(gens); #else try { gen.OnGUI(gens); } catch (UnityException e) { Debug.LogError("Error drawing generator " + GetType() + "\n" + e);} //should be system.exception but it causes ExitGUIException on opening curve/color/texture fields //it's so unity... //if something goes wrong but no error is displayed - you know where to find it #endif gen.layout.Par(3); //drawing debug generate time #if WDEBUG if (mapMagic!=null) { Rect timerRect = new Rect(gen.layout.field.x, gen.layout.field.y+gen.layout.field.height, 200, 20); string timeLabel = "g:" + gen.guiGenerateTime + "ms "; if (gen is OutputGenerator) { if (Generator.guiProcessTime.ContainsKey(gen.GetType())) timeLabel += " p:" + Generator.guiProcessTime[gen.GetType()] + "ms "; if (Generator.guiApplyTime.ContainsKey(gen.GetType())) timeLabel += " a:" + Generator.guiApplyTime[gen.GetType()] + "ms "; } gen.layout.Label(timeLabel, timerRect); } #endif //instant generate on params change if (gen.layout.change) { if (mapMagic!=null) { mapMagic.ClearResults(gen); mapMagic.Generate(); } repaint=true; Repaint(); EditorUtility.SetDirty(gens); } //drawing biome "edit" button. Rather hacky, but we have to call editor method when pressing "Edit" if (gen is Biome) { Biome biome = (Biome)gen; if (gen.layout.Button("Edit", disabled:biome.data==null)) { MapMagicWindow.Show(biome.data, mapMagic, forceOpen:true,asBiome: true); Repaint(); return; //cancel drawing this graph if biome was opened } gen.layout.Par(10); } //changing all of the output generators of the same type (in case this one was disabled to make refresh) if (gen.layout.change && !gen.enabled && gen is OutputGenerator) { foreach (GeneratorsAsset ga in gensBiomeHierarchy) foreach (OutputGenerator sameOut in ga.GeneratorsOfType<OutputGenerator>(onlyEnabled:true, checkBiomes:true)) if (sameOut.GetType() == gen.GetType()) { mapMagic.ClearResults(sameOut); mapMagic.Generate(); } } if (gen.guiRect.width<1 && gen.guiRect.height<1) { repaint=true; Repaint(); } //repainting if some of the generators rect is 0 gen.guiRect = gen.layout.field; } #endregion #region Toolbar if (toolbarLayout==null) toolbarLayout = new Layout(); toolbarLayout.margin = 0; toolbarLayout.rightMargin = 0; toolbarLayout.field.width = this.position.width; toolbarLayout.field.height = 18; toolbarLayout.cursor = new Rect(); //toolbarLayout.window = this; toolbarLayout.Par(18, padding:0); EditorGUI.LabelField(toolbarLayout.field, "", EditorStyles.toolbarButton); if (mapMagic!=null && mapMagic.ToString()!="null" && !ReferenceEquals(mapMagic.gameObject,null)) //check game object in case it was deleted //mapMagic.ToString()!="null" - the only efficient delete check. Nor Equals neither ReferenceEquals are reliable. I <3 Unity! { //drawing state icon toolbarLayout.Inset(25); if (ThreadWorker.IsWorking("MapMagic")) { toolbarLayout.Icon("MapMagic_Loading", new Rect(5,0,16,16), animationFrames:12); Repaint(); } else toolbarLayout.Icon("MapMagic_Success", new Rect(5,0,16,16)); //TODO: changed sign //mapmagic name Rect nameLabelRect = toolbarLayout.Inset(100); nameLabelRect.y+=1; //nameLabelRect.height-=4; EditorGUI.LabelField(nameLabelRect, mapMagic.gameObject.name, EditorStyles.miniLabel); //generate buttons if (GUI.Button(toolbarLayout.Inset(110,padding:0), "Generate Changed", EditorStyles.toolbarButton)) mapMagic.Generate(force:true); if (GUI.Button(toolbarLayout.Inset(110,padding:0), "Force Generate All", EditorStyles.toolbarButton)) { mapMagic.ClearResults(); if (MapMagic.instance != null) foreach (Chunk chunk in MapMagic.instance.chunks.All()) if (chunk.terrain != null) chunk.terrain.transform.RemoveChildren(); mapMagic.Generate(force:true); } //seed field toolbarLayout.Inset(10); Rect seedLabelRect = toolbarLayout.Inset(34); seedLabelRect.y+=1; seedLabelRect.height-=4; Rect seedFieldRect = toolbarLayout.Inset(64); seedFieldRect.y+=2; seedFieldRect.height-=4; } else { Rect nameLabelRect = toolbarLayout.Inset(300); nameLabelRect.y+=1; //nameLabelRect.height-=4; EditorGUI.LabelField(nameLabelRect, "External data '" + AssetDatabase.GetAssetPath(gens) + "'", EditorStyles.miniLabel); } //right part toolbarLayout.Inset(toolbarLayout.field.width - toolbarLayout.cursor.x - 150 - 22,padding:0); //drawing exit biome button Rect biomeRect = toolbarLayout.Inset(80, padding:0); if (gensBiomeHierarchy.Count>1) { if (toolbarLayout.Button("", biomeRect, icon:"MapMagic_ExitBiome", style:EditorStyles.toolbarButton)) { gensBiomeHierarchy.RemoveAt(gensBiomeHierarchy.Count-1); Repaint(); return; } toolbarLayout.Label("Exit Biome", new Rect(toolbarLayout.cursor.x-60, toolbarLayout.cursor.y+3, 60, toolbarLayout.cursor.height), fontSize:9); } //focus button // if (GUI.Button(script.toolbarLayout.Inset(100,padding:0), "Focus", EditorStyles.toolbarButton)) FocusOnGenerators(); if (toolbarLayout.Button("", toolbarLayout.Inset(23,padding:0), icon:"MapMagic_Focus", style:EditorStyles.toolbarButton)) FocusOnGenerators(); if (toolbarLayout.Button("", toolbarLayout.Inset(47,padding:0), icon:"MapMagic_Zoom", style:EditorStyles.toolbarButton)) gens.layout.zoom=1; toolbarLayout.Label((int)(gens.layout.zoom*100)+"%", new Rect(toolbarLayout.cursor.x-28, toolbarLayout.cursor.y+3, 28, toolbarLayout.cursor.height), fontSize:8); toolbarLayout.Inset(3, margin:0); toolbarLayout.Label("", toolbarLayout.Inset(22, margin:0), url:"https://gitlab.com/denispahunov/mapmagic/wikis/Editor%20Window", icon:"MapMagic_Help"); #endregion #region Draging //dragging generators for(int i=gens.list.Length-1; i>=0; i--) { Generator gen = gens.list[i]; if (gen is Group) continue; gen.layout.field = gen.guiRect; //dragging if (gens.layout.DragDrop(gen.layout.field, i)) { if (gens.layout.dragState == Layout.DragState.Pressed) { Undo.RecordObject (gens, "MapMagic Generators Drag"); gens.setDirty = !gens.setDirty; } if (gens.layout.dragState == Layout.DragState.Drag || gens.layout.dragState == Layout.DragState.Released) { //gen.Move(gens.layout.dragDelta,true); gen.layout.field.position += gens.layout.dragDelta; gen.guiRect = gens.layout.field; //moving inouts to remove lag foreach (Generator.IGuiInout inout in gen.Inouts()) inout.guiRect = new Rect(inout.guiRect.position+gens.layout.dragDelta, inout.guiRect.size); //moving group if (gen is Group) { Group group = gen as Group; for (int g=0; g<group.generators.Count; g++) //group.generators[g].Move(delta,false); { group.generators[g].layout.field.position += gens.layout.dragDelta; group.generators[g].guiRect = gens.layout.field; foreach (Generator.IGuiInout inout in group.generators[g].Inouts()) //moving inouts to remove lag inout.guiRect = new Rect(inout.guiRect.position+gens.layout.dragDelta, inout.guiRect.size); } } repaint=true; Repaint(); EditorUtility.SetDirty(gens); } } //saving all generator rects gen.guiRect = gen.layout.field; } //dragging groups for (int i=gens.list.Length-1; i>=0; i--) { //Generator gen = gens.list[i]; Group group = gens.list[i] as Group; if (group == null) continue; group.layout.field = group.guiRect; //resizing group.layout.field =gens.layout.ResizeRect(group.layout.field, i+20000); //dragging if (gens.layout.DragDrop(group.layout.field, i)) { if (gens.layout.dragState == Layout.DragState.Pressed) { Undo.RecordObject (gens, "MapMagic Group Drag"); gens.setDirty = !gens.setDirty; group.Populate(gens); } if (gens.layout.dragState == Layout.DragState.Drag || gens.layout.dragState == Layout.DragState.Released) { //group.Move(gens.layout.dragDelta,true); group.layout.field.position += gens.layout.dragDelta; group.guiRect = gens.layout.field; for (int g=0; g<group.generators.Count; g++) //group.generators[g].Move(delta,false); { group.generators[g].layout.field.position += gens.layout.dragDelta; group.generators[g].guiRect.position += gens.layout.dragDelta; // = gens.layout.field; // foreach (Generator.IGuiInout inout in group.generators[g].Inouts()) //moving inouts to remove lag // inout.guiRect = new Rect(inout.guiRect.position+gens.layout.dragDelta, inout.guiRect.size); } repaint=true; Repaint(); EditorUtility.SetDirty(gens); } if (gens.layout.dragState == Layout.DragState.Released && group != null) gens.SortGroups(); } //saving all group rects group.guiRect = group.layout.field; } #endregion //right-click menus if (Event.current.type == EventType.ContextClick || (Event.current.type == EventType.MouseDown && Event.current.control)) DrawPopup(); //debug center //EditorGUI.HelpBox(script.layout.ToLocal(new Rect(-25,-10,50,20)), "Zero", MessageType.None); //assigning portal popup action Portal.OnChooseEnter -= DrawPortalSelector; Portal.OnChooseEnter += DrawPortalSelector; //saving scroll and zoom gens.guiScroll = gens.layout.scroll; gens.guiZoom = gens.layout.zoom; DrawDemoLock(); }
public void Update () { //shifting world if (!isEditor && shift) WorldShifter.Update(shiftThreshold, shiftExcludeLayers); //checking if instance already exists and disabling if it is another mm if (instance != null && instance != this) { Debug.LogError("MapMagic object already present in scene. Disabling duplicate"); this.enabled = false; return; } //do nothing if chink size is zero if (terrainSize < 0.1f) return; //finding camera positions camPoses = Extensions.GetCamPoses(genAroundMainCam:genAroundMainCam, genAroundTag:genAroundObjsTag? genAroundTag : null, camPoses:camPoses); if (camPoses.Length == 0) return; //no cameras to deploy Voxeland transform.InverseTransformPoint(camPoses); //deploy if (!isEditor && generateInfinite) { //finding deploy rects if (deployRects == null || deployRects.Length!=camPoses.Length) { deployRects = new CoordRect[camPoses.Length]; removeRects = new CoordRect[camPoses.Length]; } for (int r=0; r<camPoses.Length; r++) //TODO: add cam pos change check { deployRects[r] = CoordRect.PickIntersectingCellsByPos(camPoses[r], generateRange, cellSize:terrainSize); removeRects[r] = CoordRect.PickIntersectingCellsByPos(camPoses[r], removeRange, cellSize:terrainSize); } //checking and deploying bool chunksChange = chunks.CheckDeploy(deployRects); if (chunksChange) chunks.Deploy(deployRects, removeRects, parent:this, allowMove:true); } //updating chunks foreach (Chunk chunk in chunks.All()) { //removing (unpinning) chunk if it's terrain was removed somehow if (chunk.terrain==null || chunk.terrain.transform==null || chunk.terrain.terrainData==null) { chunk.pinned = false; return; } //TODO: causes out of sync error //distance, priority and visibility float distance = camPoses.DistToRectAxisAligned(chunk.coord.x*terrainSize, chunk.coord.z*terrainSize, terrainSize); chunk.worker.priority = 1f / distance; //starting generate if ((distance<MapMagic.instance.generateRange || MapMagic.instance.isEditor) && chunk.worker.blank && !chunk.locked && instantGenerate) chunk.worker.Start(); //enabling/disabling (after starting generate to avoid blink) if (!MapMagic.instance.isEditor && //if non-editor ( (!chunk.worker.ready && !chunk.locked) || //if non-ready (MapMagic.instance.hideFarTerrains && distance>MapMagic.instance.enableRange) //or if out of range in playmode ) ) //TODO: it works but I don't like the way it formatted { if (chunk.terrain.gameObject.activeSelf) chunk.terrain.gameObject.SetActive(false); } //disabling else { if (!chunk.terrain.gameObject.activeSelf) chunk.terrain.gameObject.SetActive(true); } //enabling //setting terrain neighbors (they reset after each serialize) chunk.SetNeighbors(); //TODO: try doing in ondeserialize } //updating threads ThreadWorker.multithreading = multithreading; ThreadWorker.maxThreads = maxThreads; ThreadWorker.autoMaxThreads = autoMaxThreads; ThreadWorker.maxApplyTime = maxApplyTime; ThreadWorker.Refresh(); }
public static void GetProgresByTag(string tag, out float contained, out float calculated, out float ready) { if (profile) { UnityEngine.Profiling.Profiler.BeginSample("Get Progress Tag"); } DictTuple <string, bool, bool> dict = new DictTuple <string, bool, bool>(); int queueCount = queue.Count; contained = 0; calculated = 0; ready = 0; for (int i = 0; i < queueCount; i++) { ThreadWorker worker = queue[i]; if (worker.stage == Stage.stop || worker.stage == Stage.blank) { continue; } if (!worker.tag.Contains(tag)) { continue; } //contains if (!dict.ContainsKey(worker.tag)) { dict.Add(worker.tag, true, true); } //calculated TupleSet <bool, bool> tuple = dict[worker.tag]; if (worker.stage != Stage.applyEnqueued && worker.stage != Stage.coroutineEnqueued && worker.stage != Stage.coroutineRunning && worker.stage != Stage.ready) { tuple.item1 = false; tuple.item2 = false; dict[worker.tag] = tuple; } //ready if (worker.stage != Stage.ready) { tuple.item2 = false; dict[worker.tag] = tuple; } } //calculating total statistics contained = dict.Count; foreach (TupleSet <bool, bool> tuple in dict.Values()) { if (tuple.item1) { calculated++; } if (tuple.item2) { ready++; } } if (profile) { UnityEngine.Profiling.Profiler.EndSample(); } }
public static void UpdateThreads() //called each time any thread is complete { try{ if (!on || queue.Count == 0) { return; } #if WDEBUG if (IsMainThread) { Profiler.BeginSample("Update Threads"); } #endif int threadsRunning = 0; //current number of threads then multithreading is on //calculating number of threads running int queueCount = queue.Count; for (int i = 0; i < queueCount; i++) { if (queue[i].stage == Stage.threadRunning) { threadsRunning++; } } //guard if all possible threads already started: exit with no queue locking if (threadsRunning >= maxThreads) { #if WDEBUG if (IsMainThread) { Profiler.EndSample(); } #endif return; } //staring new threads lock (queue) while (threadsRunning < maxThreads) { //finding suitable worker with highest priority float maxProirity = -2000000; // int maxProirityNum = -1; ThreadWorker maxPriorityWorker = null; queueCount = queue.Count; for (int i = 0; i < queueCount; i++) { ThreadWorker worker = queue[i]; if (worker == null) { continue; } if (worker.priority < maxProirity) { continue; } if (worker.stage != Stage.threadEnqueued) { continue; //if object destroyed or other stage } if (worker.threadCondition != null && !worker.threadCondition()) { continue; } maxPriorityWorker = worker; maxProirity = worker.priority; // maxProirityNum = i; } //no suitable threads if (maxPriorityWorker == null) { break; } //starting thread //lock (maxPriorityWorker.locker) Monitor.Enter(maxPriorityWorker.locker); maxPriorityWorker.lockWasTaken = true; try { if (maxPriorityWorker.stage != Stage.threadEnqueued) { return; //this could happen if two threads selecting one worker, or worker stopped while being selected } if (logging) { Log(maxPriorityWorker, "Refresh:ThreadSelected (max" + maxProirity + ") "); } threadsRunning++; if (multithreading) { maxPriorityWorker.thread = new Thread(maxPriorityWorker.ThreadFn); maxPriorityWorker.thread.IsBackground = true; maxPriorityWorker.SwitchStage(Stage.threadRunning, "Refresh: start thread"); //before actually starting maxPriorityWorker.thread.Start(); } else { maxPriorityWorker.ThreadFn(); if (IsMainThread) { UnityEngine.Profiling.Profiler.EndSample(); } if (oneThreadPerFrame) { break; } } } finally { Monitor.Exit(maxPriorityWorker.locker); maxPriorityWorker.lockWasTaken = false; } } #if WDEBUG if (IsMainThread) { Profiler.EndSample(); } #endif } catch (System.Exception e) { Debug.LogError("Spinner Error: " + e); } }
public static void UpdateApply() { if (!on || queue.Count == 0) { return; } #if WDEBUG Profiler.BeginSample("Update Apply"); #endif System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch(); timer.Start(); while (timer.ElapsedMilliseconds < maxApplyTime) { //if couroutine has started - moving coroutine if (CurrentCoroutine != null) { currentCoroutineWorker.CoroutineFn(); continue; } //finding suitable worker with highest priority float maxProirity = -2000000; // int maxProirityNum = -1; ThreadWorker maxPriorityWorker = null; int queueCount = queue.Count; for (int i = 0; i < queueCount; i++) { ThreadWorker worker = queue[i]; if (worker == null) { continue; //if object destroyed } if (worker.priority < maxProirity) { continue; } if (worker.stage != Stage.applyEnqueued && worker.stage != Stage.prepareEnqueued && worker.stage != Stage.coroutineEnqueued && worker.stage != Stage.coroutineRunning) { continue; //other stage } if (worker.stage == Stage.prepareEnqueued && worker.prepareCondition != null && !worker.prepareCondition()) { continue; } if (worker.stage == Stage.applyEnqueued && worker.applyCondition != null && !worker.applyCondition()) { continue; //if apply condition has not met } if (worker.stage == Stage.coroutineEnqueued && worker.coroutineCondition != null && !worker.coroutineCondition()) { continue; //if coroutine condition has not met (note that conditions is checked only before starting coroutine) } maxPriorityWorker = worker; maxProirity = worker.priority; // maxProirityNum = i; } //no suitable applies if (maxPriorityWorker == null) { break; } //apply //lock (maxPriorityWorker.locker) Monitor.Enter(maxPriorityWorker.locker); maxPriorityWorker.lockWasTaken = true; try { if (logging) { Log(maxPriorityWorker, "Refresh:ApplyPrepSelected"); } if (maxPriorityWorker.stage == Stage.prepareEnqueued) { //maxPriorityWorker.SwitchStage(Stage.applyRunning); maxPriorityWorker.PrepareFn(); } if (maxPriorityWorker.stage == Stage.applyEnqueued) { //maxPriorityWorker.SwitchStage(Stage.applyRunning); maxPriorityWorker.ApplyFn(); } if (maxPriorityWorker.stage == Stage.coroutineEnqueued || maxPriorityWorker.stage == Stage.coroutineRunning) { maxPriorityWorker.CoroutineFn(); } } finally { Monitor.Exit(maxPriorityWorker.locker); maxPriorityWorker.lockWasTaken = false; } } #if WDEBUG Profiler.EndSample(); #endif }
public static string PrintLog(ThreadWorker worker) { List <ThreadWorker> workers = new List <ThreadWorker>(); workers.Add(worker); return(PrintLog(workers)); }