Skip to content

Commit

Permalink
Merge pull request #504 from baaahs/grid-fixes
Browse files Browse the repository at this point in the history
Misc client optimizations
  • Loading branch information
merge-when-green[bot] authored Oct 1, 2022
2 parents 8365b06 + 6cff0b5 commit f0fb771
Show file tree
Hide file tree
Showing 23 changed files with 514 additions and 305 deletions.
2 changes: 1 addition & 1 deletion src/commonMain/kotlin/baaahs/gl/render/RenderManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import baaahs.util.Logger
class RenderManager(glContext: GlContext) {
private val renderEngines = CacheBuilder<FixtureType, ModelRenderEngine> { fixtureType ->
ModelRenderEngine(
glContext, fixtureType, resultDeliveryStrategy = pickResultDeliveryStrategy(glContext)
glContext, fixtureType, resultDeliveryStrategy = glContext.pickResultDeliveryStrategy()
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ class SyncResultDeliveryStrategy : ResultDeliveryStrategy {
}
}

fun GlContext.pickResultDeliveryStrategy() =
pickResultDeliveryStrategy(this)

expect fun pickResultDeliveryStrategy(gl: GlContext): ResultDeliveryStrategy
80 changes: 42 additions & 38 deletions src/commonMain/kotlin/baaahs/ui/gridlayout/Layout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -101,44 +101,33 @@ data class Layout(

/**
* Get all static elements.
* @param {Array} layout Array of layout objects.
* @return {Array} Array of static layout items..
*
* @return Array of static layout items.
*/
private fun getStatics(): List<LayoutItem> =
items.filter { l -> l.isStatic }

/**
* Move an element. Responsible for doing cascading movements of other elements.
*
* Returns a new layout with moved layout items.
*
* @param {Array} layout Full layout to modify.
* @param {LayoutItem} l element to move.
* @param {Number} [x] X position in grid units.
* @param {Number} [y] Y position in grid units.
* @param item Element to move.
* @param x X position in grid units.
* @param y Y position in grid units.
* @return A new layout with moved layout items.
* @throws ImpossibleLayoutException if the move isn't possible because of collisions or constraints.
*/
fun moveElement(
l: LayoutItem,
x: Int,
y: Int
): Layout {
for (direction in Direction.rankedPushOptions(x - l.x, y - l.y)) {
fun moveElement(item: LayoutItem, x: Int, y: Int): Layout {
for (direction in Direction.rankedPushOptions(x - item.x, y - item.y)) {
try {
return moveElementInternal(l, x, y, true, direction)
return moveElementInternal(item, x, y, direction)
} catch (e: ImpossibleLayoutException) {
// Try again.
}
}
throw ImpossibleLayoutException()
}

private fun moveElementInternal(
l: LayoutItem,
x: Int,
y: Int,
isDirectUserAction: Boolean,
pushDirection: Direction
): Layout {
private fun moveElementInternal(l: LayoutItem, x: Int, y: Int, pushDirection: Direction): Layout {
// If this is static and not explicitly enabled as draggable,
// no move is possible, so we can short-circuit this immediately.
if (l.isStatic && !l.isDraggable) throw ImpossibleLayoutException()
Expand All @@ -151,11 +140,15 @@ data class Layout(
}

val movedItem = l.movedTo(x, y)
if (outOfBounds(movedItem))
return fitElement(movedItem, pushDirection)
}

private fun fitElement(changedItem: LayoutItem, pushDirection: Direction): Layout {
if (outOfBounds(changedItem))
throw ImpossibleLayoutException()

var updatedLayout = updateLayout(movedItem)
val collisions = findCollisions(movedItem)
var updatedLayout = updateLayout(changedItem)
val collisions = findCollisions(changedItem)

// If it collides with anything, move it (recursively).
if (collisions.isNotEmpty()) {
Expand All @@ -164,30 +157,39 @@ data class Layout(
// nearest collision.
for (collision in pushDirection.sort(collisions)) {
logger.info {
"Resolving collision between ${movedItem.i} at [${movedItem.x},${movedItem.y}] and ${collision.i} at [${collision.x},${collision.y}]"
"Resolving collision between ${changedItem.i} at [${changedItem.x},${changedItem.y}] and ${collision.i} at [${collision.x},${collision.y}]"
}

// Short circuit so we can't infinitely loop
if (collision.moved) throw ImpossibleLayoutException()

updatedLayout =
updatedLayout.pushCollidingElement(movedItem, collision, isDirectUserAction, pushDirection)
updatedLayout.pushCollidingElement(changedItem, collision, pushDirection)
}
}

return updatedLayout
}

/**
* Resize an element. Responsible for doing cascading movements of other elements.
*
* @param item Element to move.
* @param w X position in grid units.
* @param y Y position in grid units.
* @return A new layout with resized and possibly moved layout items.
* @throws ImpossibleLayoutException if the move isn't possible because of collisions or constraints.
*/
fun resizeElement(item: LayoutItem, w: Int, h: Int): Layout {
val resizedItem = item.copy(w = w, h = h)
var updatedLayout = updateLayout(resizedItem)
val collisions = updatedLayout.findCollisions(resizedItem)

if (collisions.isNotEmpty()) {
throw ImpossibleLayoutException()
for (direction in arrayOf(Direction.East, Direction.South)) {
try {
return fitElement(resizedItem, direction)
} catch (e: ImpossibleLayoutException) {
// Try again.
}
}

return updatedLayout
throw ImpossibleLayoutException()
}

private fun outOfBounds(movedItem: LayoutItem) =
Expand All @@ -207,23 +209,25 @@ data class Layout(
private fun pushCollidingElement(
collidesWith: LayoutItem,
itemToMove: LayoutItem,
isDirectUserAction: Boolean,
direction: Direction
): Layout {
// Don't move static items - we have to move the other element away.
if (itemToMove.isStatic) {
if (collidesWith.isStatic) throw ImpossibleLayoutException()

return pushCollidingElement(itemToMove, collidesWith, isDirectUserAction, direction)
return moveElementInternal(
collidesWith,
collidesWith.x + direction.xIncr,
collidesWith.y + direction.yIncr,
direction
)
}

return moveElementInternal(
itemToMove,
itemToMove.x + direction.xIncr,
itemToMove.y + direction.yIncr,
false,
direction
// we're already colliding (not for static items)
)
}

Expand Down
12 changes: 7 additions & 5 deletions src/commonMain/kotlin/baaahs/util/Stats.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ open class Stats {
ReadOnlyProperty<Stats, Statistic> { _, _ -> statistic }
}

fun summarize(): String = statistics.values.joinToString("\n") { it.summarize() }
val all = statistics.values

fun summarize(): String = all.joinToString("\n") { it.summarize() }

class Statistic(val name: String) {
var calls = 0
var elapsedTime = Interval(0)
val elapsedTimeMs get() = (elapsedTime / 1000).roundToInt()
val averageTime get() = if (calls > 0) elapsedTime / calls else null
val averageTimeMs get() = averageTime?.div(1000)?.roundToInt()

fun <T> time(block: () -> T): T {
val startTime = internalTimerClock.now()
Expand All @@ -40,10 +45,7 @@ open class Stats {
}

fun summarize(): String {
val avgTimeMs = if (calls > 0) {
(elapsedTime / calls * 1000).roundToInt()
} else ""
return "$name: $calls calls, avg ${avgTimeMs}ms, total ${(elapsedTime * 1000).roundToInt()}ms"
return "$name: $calls calls, avg ${averageTimeMs ?: "-"}ms, total ${elapsedTimeMs}ms"
}
}
}
3 changes: 2 additions & 1 deletion src/jsMain/kotlin/baaahs/app/settings/UiSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ data class UiSettings(
val darkMode: Boolean = true,
val useSharedContexts: Boolean = true,
val renderButtonPreviews: Boolean = true,
val appMode: AppMode = AppMode.Show
val appMode: AppMode = AppMode.Show,
val developerMode: Boolean = false
)
2 changes: 1 addition & 1 deletion src/jsMain/kotlin/baaahs/app/ui/AppContext.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import baaahs.util.Clock
import react.createContext

val appContext = createContext<AppContext>()
val toolchainContext = createContext<Toolchain>()

/**
* The application context.
Expand All @@ -32,7 +33,6 @@ external interface AppContext {
var dragNDrop: ReactBeautifulDragNDrop
var webClient: WebClient.Facade
var plugins: Plugins
var toolchain: Toolchain
var uiSettings: UiSettings
var allStyles: AllStyles
var prompt: (prompt: Prompt) -> Unit
Expand Down
Loading

0 comments on commit f0fb771

Please sign in to comment.