diff --git a/src/main/scala/ocelot/desktop/ui/UiHandler.scala b/src/main/scala/ocelot/desktop/ui/UiHandler.scala index a69aeb3..391838b 100644 --- a/src/main/scala/ocelot/desktop/ui/UiHandler.scala +++ b/src/main/scala/ocelot/desktop/ui/UiHandler.scala @@ -4,9 +4,9 @@ import buildinfo.BuildInfo import ocelot.desktop.audio.{Audio, SoundBuffers, SoundSource} import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D} import ocelot.desktop.graphics.Graphics -import ocelot.desktop.ui.event.{Event, MouseEvent} import ocelot.desktop.ui.event.handlers.HoverHandler import ocelot.desktop.ui.event.sources.{BrainEvents, KeyEvents, MouseEvents, ScrollEvents} +import ocelot.desktop.ui.event.{Event, MouseEvent} import ocelot.desktop.ui.widget.window.Window import ocelot.desktop.ui.widget.{RootWidget, Widget} import ocelot.desktop.util._ @@ -15,7 +15,6 @@ import org.apache.commons.lang3.SystemUtils import org.lwjgl.BufferUtils import org.lwjgl.input.Mouse import org.lwjgl.opengl._ -import totoro.ocelot.brain.event.{InventoryEvent, NodeEvent} import java.awt.Toolkit import java.awt.datatransfer.{DataFlavor, StringSelection, UnsupportedFlavorException} @@ -437,14 +436,37 @@ object UiHandler extends Logging { } } + private def dispatchBrainEvents(): Unit = { + val cutoff = BrainEvents.events.peekLast() + + if (cutoff == null) { + return + } + + // we're effectively taking a snapshot of all events we have received at the point of the call. + // new events may still be added to the queue, but we'll defer everything after the cutoff until the next update. + val events = LazyList.continually(BrainEvents.events.poll()).takeWhile({ + var inSnapshot = true + + { event => + val pass = inSnapshot + inSnapshot = !(event eq cutoff) + + pass + } + }) + + for (event <- events) { + root.workspaceView.dispatchBrainEvent(event) + } + } + private def update(): Unit = { if (shouldUpdateHierarchy) { _updateHierarchy() } - for (event <- LazyList.continually(BrainEvents.events.poll()).takeWhile(_ != null)) { - root.workspaceView.dispatchBrainEvent(event) - } + dispatchBrainEvents() val mousePos = mousePosition if (mousePos.x < 0 || mousePos.y < 0 || mousePos.x > root.width || mousePos.y > root.height) { diff --git a/src/main/scala/ocelot/desktop/ui/event/sources/BrainEvents.scala b/src/main/scala/ocelot/desktop/ui/event/sources/BrainEvents.scala index ce4ab76..353b521 100644 --- a/src/main/scala/ocelot/desktop/ui/event/sources/BrainEvents.scala +++ b/src/main/scala/ocelot/desktop/ui/event/sources/BrainEvents.scala @@ -2,10 +2,10 @@ package ocelot.desktop.ui.event.sources import totoro.ocelot.brain.event.{Event, EventBus} -import java.util.concurrent.ConcurrentLinkedQueue +import java.util.concurrent.ConcurrentLinkedDeque object BrainEvents { - val events = new ConcurrentLinkedQueue[Event]() + val events = new ConcurrentLinkedDeque[Event]() private val eventSubscription = EventBus.subscribe { event => events.add(event)