diff --git a/editor/src/main/com/mbrlabs/mundus/editor/core/project/ProjectManager.java b/editor/src/main/com/mbrlabs/mundus/editor/core/project/ProjectManager.java index 4809aaa3f..e766783f6 100644 --- a/editor/src/main/com/mbrlabs/mundus/editor/core/project/ProjectManager.java +++ b/editor/src/main/com/mbrlabs/mundus/editor/core/project/ProjectManager.java @@ -16,10 +16,6 @@ package com.mbrlabs.mundus.editor.core.project; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.g3d.ModelBatch; @@ -47,12 +43,17 @@ import com.mbrlabs.mundus.editor.core.registry.ProjectRef; import com.mbrlabs.mundus.editor.core.registry.Registry; import com.mbrlabs.mundus.editor.core.scene.SceneManager; +import com.mbrlabs.mundus.editor.events.LogEvent; import com.mbrlabs.mundus.editor.events.ProjectChangedEvent; import com.mbrlabs.mundus.editor.events.SceneChangedEvent; import com.mbrlabs.mundus.editor.scene3d.components.PickableComponent; import com.mbrlabs.mundus.editor.utils.Log; import com.mbrlabs.mundus.editor.utils.SkyboxBuilder; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + /** * Manages Mundus projects and scenes. * @@ -203,11 +204,13 @@ public ProjectContext loadProject(ProjectRef ref) @Override public void onLoad(Asset asset, int progress, int assetCount) { Log.debug(TAG, "Loaded {} asset ({}/{})", asset.getMeta().getType(), progress, assetCount); + Mundus.INSTANCE.postEvent(new LogEvent("Loaded " + asset.getMeta().getType() + " asset ("+progress+"/"+assetCount+")")); } @Override public void onFinish(int assetCount) { Log.debug(TAG, "Finished loading {} assets", assetCount); + Mundus.INSTANCE.postEvent(new LogEvent("Finished loading " + assetCount + " assets")); } }, false); @@ -242,6 +245,7 @@ public void saveProject(ProjectContext projectContext) { SceneManager.saveScene(projectContext, projectContext.currScene); Log.debug(TAG, "Saving currentProject {}", projectContext.name + " [" + projectContext.path + "]"); + Mundus.INSTANCE.postEvent(new LogEvent("Saving currentProject " + projectContext.name + " [" + projectContext.path + "]")); } /** diff --git a/editor/src/main/com/mbrlabs/mundus/editor/events/LogEvent.kt b/editor/src/main/com/mbrlabs/mundus/editor/events/LogEvent.kt new file mode 100644 index 000000000..bcc554503 --- /dev/null +++ b/editor/src/main/com/mbrlabs/mundus/editor/events/LogEvent.kt @@ -0,0 +1,13 @@ +package com.mbrlabs.mundus.editor.events + +/** + * An Event for posting new log entries in the log bar + */ +class LogEvent(val logMessage: String) { + + interface LogEventListener { + @Subscribe + fun onLogEvent(event: LogEvent) + } + +} \ No newline at end of file diff --git a/editor/src/main/com/mbrlabs/mundus/editor/ui/UI.kt b/editor/src/main/com/mbrlabs/mundus/editor/ui/UI.kt index ab9a67fca..498cd4375 100644 --- a/editor/src/main/com/mbrlabs/mundus/editor/ui/UI.kt +++ b/editor/src/main/com/mbrlabs/mundus/editor/ui/UI.kt @@ -130,4 +130,8 @@ object UI : Stage(ScreenViewport()) { dialog.show(this) } + override fun act() { + super.act() + docker.update(); + } } diff --git a/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/dock/DockBar.kt b/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/dock/DockBar.kt index e2193a413..5baead4bb 100644 --- a/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/dock/DockBar.kt +++ b/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/dock/DockBar.kt @@ -32,6 +32,7 @@ import com.mbrlabs.mundus.editor.ui.widgets.MundusSplitPane class DockBar(private val splitPane: MundusSplitPane) : VisTable(), TabbedPaneListener { private val assetsDock = AssetsDock() + private val logBar = LogBar() private val tabbedPane: TabbedPane @@ -46,7 +47,11 @@ class DockBar(private val splitPane: MundusSplitPane) : VisTable(), TabbedPaneLi tabbedPane.addListener(this) tabbedPane.add(assetsDock) + tabbedPane.add(logBar) add(tabbedPane.table).expandX().fillX().left().bottom().height(30f).row() + + // Keeping asset tab the default active tab + tabbedPane.switchTab(assetsDock) } override fun switchedTab(tab: Tab?) { @@ -68,4 +73,8 @@ class DockBar(private val splitPane: MundusSplitPane) : VisTable(), TabbedPaneLi // user can't do that } + fun update() { + tabbedPane.updateTabTitle(logBar) + } + } diff --git a/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/dock/LogBar.kt b/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/dock/LogBar.kt new file mode 100644 index 000000000..9d979e12f --- /dev/null +++ b/editor/src/main/com/mbrlabs/mundus/editor/ui/modules/dock/LogBar.kt @@ -0,0 +1,136 @@ +package com.mbrlabs.mundus.editor.ui.modules.dock + +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.Input +import com.badlogic.gdx.scenes.scene2d.Actor +import com.badlogic.gdx.scenes.scene2d.InputEvent +import com.badlogic.gdx.scenes.scene2d.InputListener +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener +import com.kotcrab.vis.ui.widget.* +import com.kotcrab.vis.ui.widget.tabbedpane.Tab +import com.mbrlabs.mundus.editor.Mundus +import com.mbrlabs.mundus.editor.events.LogEvent +import com.mbrlabs.mundus.editor.ui.UI +import java.text.SimpleDateFormat +import java.util.* + +/** + * Docked log bar for displaying LogEvents with timestamps + */ +class LogBar : Tab(false, false), LogEvent.LogEventListener { + + private val root = VisTable() + private val logTable = VisTable() + private val pane = VisScrollPane(logTable) + + private val logOpsMenu = PopupMenu() + private val clearLogsButton = MenuItem("Clear Logs") + + private val maxLogSize = 75 + private val dateFormat = SimpleDateFormat("HH:mm:ss") + + // True when new entries are in the log and log is not the active tab + var newEntries = false + + init { + Mundus.registerEventListener(this) + initUi() + } + + private fun initUi() { + root.setBackground("window-bg") + root.left().top() + root.add(pane).top().fillX().expandX() + + pane.fadeScrollBars = false + + logOpsMenu.addItem(clearLogsButton) + registerListeners() + } + + private fun registerListeners() { + // Pop up menu on right click + root.addListener(object : InputListener() { + override fun touchDown(event: InputEvent?, x: Float, y: Float, pointer: Int, button: Int): Boolean { + return true + } + + override fun touchUp(event: InputEvent?, x: Float, y: Float, pointer: Int, button: Int) { + if (event!!.button == Input.Buttons.RIGHT) { + logOpsMenu.showMenu(UI, Gdx.input.x.toFloat(), + (Gdx.graphics.height - Gdx.input.y).toFloat()) + } + } + + override fun enter(event: InputEvent, x: Float, y: Float, pointer: Int, fromActor: Actor?) { + // Give scroll focus to pane automatically when mouse enters + UI.scrollFocus = pane + } + + override fun exit(event: InputEvent, x: Float, y: Float, pointer: Int, toActor: Actor?) { + // Only clear focus if the exit to another actor is NOT an actor within the LogBars root + if (toActor?.isDescendantOf(root) != true) + UI.scrollFocus = null + } + }) + + clearLogsButton.addListener(object : ClickListener() { + override fun clicked(event: InputEvent, x: Float, y: Float) { + logTable.clearChildren() + } + }) + } + + override fun onShow() { + super.onShow() + newEntries = false + } + + override fun getTabTitle(): String { + if (newEntries) + return "Log*" + + return "Log" + } + + override fun getContentTable(): Table { + return root + } + + override fun onLogEvent(event: LogEvent) { + addLogMessage(event.logMessage) + } + + /** + * Appends new log message with a time stamp to the log table, then scrolls to most recent entry and + * removes old entries. + */ + private fun addLogMessage(message : String) { + if (!isActiveTab) + newEntries = true + + val timeStamp = dateFormat.format(Date()) + + val logString = buildString { + append("[") + append(timeStamp) + append("] ") + append(message) + } + + logTable.add(VisLabel(logString)).left().pad(4f).expand().row() + + // Remove oldest entry + if (logTable.cells.size > maxLogSize) + logTable.removeActorAt(0, true) + + scrollToBottom() + } + + private fun scrollToBottom() { + // Update layout and scroll to the latest (bottom) log message + pane.layout() + pane.scrollTo(0f, 0f, 0f, 0f) + } +} \ No newline at end of file