void FogWorker::FloodFill(int32 x, int32 y) { if(x < 0 || x >= TextureSize || y < 0 || y >= TextureSize) { return; } // Wikipedia // Flood-fill (node, target-color, replacement-color): // 1. If target - color is equal to replacement - color, return. // 2. If color of node is not equal to target - color, return. if(FMath::IsNearlyEqual(UnfoggedData[x + y * TextureSize], 1.0f)) { return; } // 3. Set Q to the empty queue. TQueue<FIntVector> Q; // 4. Add node to Q. Q.Enqueue(FIntVector(x, y, 0)); FIntVector N; // 5. For each element N of Q : while(Q.Dequeue(N)) { // 6. Set w and e equal to N. auto w = N, e = N; // 7. Move w to the west until the color of the node to the west of w no longer matches target - color. while(w.X - 1 > 0 && !FMath::IsNearlyEqual(UnfoggedData[w.X - 1 + w.Y * TextureSize], 1.0f)) { w.X--; } // 8. Move e to the east until the color of the node to the east of e no longer matches target - color. while(e.X + 1 < TextureSize && !FMath::IsNearlyEqual(UnfoggedData[e.X + 1 + e.Y * TextureSize], 1.0f)) { e.X++; } // 9. For each node n between w and e : for(auto i = w.X; i <= e.X; ++i) { FIntVector n(i, N.Y, 0); // 10. Set the color of n to replacement - color. UnfoggedData[n.X + n.Y * TextureSize] = 1.0f; // 11. If the color of the node to the north of n is target - color, add that node to Q. if(n.Y + 1 < TextureSize && !FMath::IsNearlyEqual(UnfoggedData[n.X + (n.Y + 1) * TextureSize], 1.0f)) Q.Enqueue(FIntVector(n.X, n.Y + 1, 0)); // 12. If the color of the node to the south of n is target - color, add that node to Q. if(n.Y - 1 > 0 && !FMath::IsNearlyEqual(UnfoggedData[n.X + (n.Y - 1) * TextureSize], 1.0f)) { Q.Enqueue(FIntVector(n.X, n.Y - 1, 0)); } } // 13. Continue looping until Q is exhausted. } // 14. Return. }
bool FAppEventManager::WaitForEventInQueue(EAppEventState InState, double TimeoutSeconds) { bool FoundEvent = false; double StopTime = FPlatformTime::Seconds() + TimeoutSeconds; TQueue<FAppEventData, EQueueMode::Spsc> HoldingQueue; while (!FoundEvent) { int rc = pthread_mutex_lock(&QueueMutex); check(rc == 0); // Copy the existing queue (and check for our event) while (!Queue.IsEmpty()) { FAppEventData OutData; Queue.Dequeue(OutData); if (OutData.State == InState) FoundEvent = true; HoldingQueue.Enqueue(OutData); } if (FoundEvent) break; // Time expired? if (FPlatformTime::Seconds() > StopTime) break; // Unlock for new events and wait a bit before trying again rc = pthread_mutex_unlock(&QueueMutex); check(rc == 0); FPlatformProcess::Sleep(0.01f); } // Add events back to queue from holding while (!HoldingQueue.IsEmpty()) { FAppEventData OutData; HoldingQueue.Dequeue(OutData); Queue.Enqueue(OutData); } int rc = pthread_mutex_unlock(&QueueMutex); check(rc == 0); return FoundEvent; }