mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-19 18:49:19 +01:00
Add key mapping tab to the settings dialog
This commit is contained in:
parent
98d352a9e6
commit
3c604b976a
0
spritepack/spritepack.sh
Normal file → Executable file
0
spritepack/spritepack.sh
Normal file → Executable file
BIN
sprites/icons/SettingsKeymap.png
Normal file
BIN
sprites/icons/SettingsKeymap.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 196 B |
@ -23,6 +23,7 @@ Tier3 = #c354cd
|
||||
|
||||
Label = #333333
|
||||
LabelError = #aa0000
|
||||
LabelDisabled = #888888
|
||||
|
||||
Scrollbar = #e5e5e526
|
||||
ScrollbarThumb = #cc3f72
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 148 KiB |
@ -65,7 +65,7 @@ icons/Help 559 618 16 16
|
||||
icons/Home 214 567 22 22
|
||||
icons/Keyboard 576 618 16 16
|
||||
icons/KeyboardOff 593 618 16 16
|
||||
icons/LMB 350 655 11 14
|
||||
icons/LMB 363 655 11 14
|
||||
icons/Label 610 618 16 16
|
||||
icons/LinesHorizontal 627 618 16 16
|
||||
icons/Link 644 618 16 16
|
||||
@ -73,26 +73,27 @@ icons/LinkSlash 661 618 16 16
|
||||
icons/Memory 678 618 16 16
|
||||
icons/Microchip 695 618 16 16
|
||||
icons/NA 712 618 16 16
|
||||
icons/NotificationError 374 655 11 11
|
||||
icons/NotificationInfo 386 655 11 11
|
||||
icons/NotificationWarning 398 655 11 11
|
||||
icons/NotificationError 387 655 11 11
|
||||
icons/NotificationInfo 399 655 11 11
|
||||
icons/NotificationWarning 411 655 11 11
|
||||
icons/Ocelot 729 618 16 16
|
||||
icons/Pin 305 655 14 14
|
||||
icons/Pin 318 655 14 14
|
||||
icons/Plus 746 618 16 16
|
||||
icons/Power 763 618 16 16
|
||||
icons/RMB 362 655 11 14
|
||||
icons/RMB 375 655 11 14
|
||||
icons/Restart 780 618 16 16
|
||||
icons/Save 797 618 16 16
|
||||
icons/SaveAs 814 618 16 16
|
||||
icons/Server 831 618 16 16
|
||||
icons/SettingsSound 266 655 12 17
|
||||
icons/SettingsSystem 279 655 12 17
|
||||
icons/SettingsUI 292 655 12 17
|
||||
icons/SettingsKeymap 266 655 12 17
|
||||
icons/SettingsSound 279 655 12 17
|
||||
icons/SettingsSystem 292 655 12 17
|
||||
icons/SettingsUI 305 655 12 17
|
||||
icons/Tier0 848 618 16 16
|
||||
icons/Tier1 865 618 16 16
|
||||
icons/Tier2 882 618 16 16
|
||||
icons/Tiers 899 618 16 16
|
||||
icons/Unpin 320 655 14 14
|
||||
icons/Unpin 333 655 14 14
|
||||
icons/WaveLFSR 901 707 24 10
|
||||
icons/WaveNoise 926 707 24 10
|
||||
icons/WaveSawtooth 951 707 24 10
|
||||
@ -185,7 +186,7 @@ light-panel/Fill 207 560 2 2
|
||||
light-panel/Vent 356 434 2 38
|
||||
nodes/Cable 377 445 8 8
|
||||
nodes/Camera 375 674 16 16
|
||||
nodes/Chest 335 655 14 14
|
||||
nodes/Chest 348 655 14 14
|
||||
nodes/HologramProjector0 392 674 16 16
|
||||
nodes/HologramProjector1 409 674 16 16
|
||||
nodes/IronNoteBlock 426 674 16 16
|
||||
|
||||
@ -149,6 +149,7 @@ object IconSource {
|
||||
)),
|
||||
)
|
||||
|
||||
val SettingsKeymap: IconSource = IconSource("icons/SettingsKeymap")
|
||||
val SettingsSystem: IconSource = IconSource("icons/SettingsSystem")
|
||||
val SettingsSound: IconSource = IconSource("icons/SettingsSound")
|
||||
val SettingsUI: IconSource = IconSource("icons/SettingsUI")
|
||||
|
||||
@ -13,7 +13,7 @@ import ocelot.desktop.util._
|
||||
import ocelot.desktop.{OcelotDesktop, Settings}
|
||||
import org.apache.commons.lang3.SystemUtils
|
||||
import org.lwjgl.BufferUtils
|
||||
import org.lwjgl.input.{Keyboard, Mouse}
|
||||
import org.lwjgl.input.Mouse
|
||||
import org.lwjgl.opengl._
|
||||
|
||||
import java.awt.Toolkit
|
||||
@ -29,6 +29,7 @@ import scala.collection.mutable
|
||||
import scala.concurrent.duration.DurationInt
|
||||
import scala.util.Try
|
||||
|
||||
|
||||
object UiHandler extends Logging {
|
||||
var root: RootWidget = _
|
||||
var graphics: Graphics = _
|
||||
@ -386,7 +387,7 @@ object UiHandler extends Logging {
|
||||
// we are processing screenshots here to make sure that
|
||||
// the current frame was fully drawn on the screen,
|
||||
// but the update for the next frame yet not happened (if the window, for example, is to be resized)
|
||||
if (KeyEvents.isReleased(Keyboard.KEY_F12)) {
|
||||
if (KeyEvents.isReleased(Settings.get.keymap(Keybind.Screenshot))) {
|
||||
SoundSource.InterfaceShutter.play()
|
||||
val image = graphics.screenshot()
|
||||
root.flash.bang()
|
||||
|
||||
@ -3,12 +3,13 @@ package ocelot.desktop.ui.widget
|
||||
import ocelot.desktop.audio.SoundSource
|
||||
import ocelot.desktop.geometry.{Padding2D, Size2D}
|
||||
import ocelot.desktop.graphics.{Graphics, IconSource}
|
||||
import ocelot.desktop.ui.event.KeyEvent
|
||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenuEntry, ContextMenuSubmenu}
|
||||
import ocelot.desktop.ui.widget.help.{AboutDialog, UpdateCheckerDialog}
|
||||
import ocelot.desktop.ui.widget.settings.SettingsDialog
|
||||
import ocelot.desktop.util.Keybind.{QuickLoad, QuickSave}
|
||||
import ocelot.desktop.util.Keymap.Press
|
||||
import ocelot.desktop.{ColorScheme, OcelotDesktop}
|
||||
import org.lwjgl.input.Keyboard
|
||||
|
||||
|
||||
class MenuBar extends Widget {
|
||||
override def receiveMouseEvents: Boolean = true
|
||||
@ -70,8 +71,8 @@ class MenuBar extends Widget {
|
||||
}) // fill remaining space
|
||||
|
||||
eventHandlers += {
|
||||
case KeyEvent(KeyEvent.State.Press, Keyboard.KEY_F5, _) => OcelotDesktop.save()
|
||||
case KeyEvent(KeyEvent.State.Press, Keyboard.KEY_F9, _) => OcelotDesktop.showOpenDialog()
|
||||
case Press(QuickSave) => OcelotDesktop.save()
|
||||
case Press(QuickLoad) => OcelotDesktop.showOpenDialog()
|
||||
}
|
||||
|
||||
override def draw(g: Graphics): Unit = {
|
||||
|
||||
@ -4,17 +4,18 @@ import ocelot.desktop.OcelotDesktop
|
||||
import ocelot.desktop.color.RGBAColor
|
||||
import ocelot.desktop.graphics.Graphics
|
||||
import ocelot.desktop.ui.UiHandler
|
||||
import ocelot.desktop.ui.event.KeyEvent
|
||||
import ocelot.desktop.ui.layout.{CopyLayout, LinearLayout}
|
||||
import ocelot.desktop.ui.widget.contextmenu.ContextMenus
|
||||
import ocelot.desktop.ui.widget.itemdrag.DraggedItemPool
|
||||
import ocelot.desktop.ui.widget.modal.ModalDialogPool
|
||||
import ocelot.desktop.ui.widget.statusbar.StatusBar
|
||||
import ocelot.desktop.ui.widget.tooltip.TooltipPool
|
||||
import ocelot.desktop.util.Keybind.{Fullscreen, ReloadWorkspace, UIDebug}
|
||||
import ocelot.desktop.util.Keymap.Release
|
||||
import ocelot.desktop.util.{DrawUtils, Orientation}
|
||||
import org.lwjgl.input.Keyboard
|
||||
import totoro.ocelot.brain.nbt.NBTTagCompound
|
||||
|
||||
|
||||
class RootWidget(setupDefaultWorkspace: Boolean = true) extends Widget {
|
||||
override protected val layout = new CopyLayout(this)
|
||||
|
||||
@ -50,10 +51,10 @@ class RootWidget(setupDefaultWorkspace: Boolean = true) extends Widget {
|
||||
private var isDebugViewVisible = false
|
||||
|
||||
eventHandlers += {
|
||||
case KeyEvent(KeyEvent.State.Release, Keyboard.KEY_F1, _) =>
|
||||
case Release(UIDebug) =>
|
||||
isDebugViewVisible = !isDebugViewVisible
|
||||
|
||||
case KeyEvent(KeyEvent.State.Release, Keyboard.KEY_F3, _) =>
|
||||
case Release(ReloadWorkspace) =>
|
||||
OcelotDesktop.withTickLockAcquired {
|
||||
val backendNBT = new NBTTagCompound
|
||||
val frontendNBT = new NBTTagCompound
|
||||
@ -63,7 +64,7 @@ class RootWidget(setupDefaultWorkspace: Boolean = true) extends Widget {
|
||||
UiHandler.root.workspaceView.load(frontendNBT)
|
||||
}
|
||||
|
||||
case KeyEvent(KeyEvent.State.Release, Keyboard.KEY_F11, _) =>
|
||||
case Release(Fullscreen) =>
|
||||
UiHandler.fullScreen = !UiHandler.fullScreen
|
||||
}
|
||||
|
||||
|
||||
@ -12,11 +12,12 @@ import ocelot.desktop.ui.event.sources.KeyEvents
|
||||
import ocelot.desktop.ui.layout.{CopyLayout, Layout}
|
||||
import ocelot.desktop.ui.widget.WorkspaceView.NodeLoadException
|
||||
import ocelot.desktop.ui.widget.window.{NodeSelector, ProfilerWindow, WindowPool}
|
||||
import ocelot.desktop.util.Keybind.{Center, Profiler}
|
||||
import ocelot.desktop.util.Keymap.Press
|
||||
import ocelot.desktop.util.ReflectionUtils.findUnaryConstructor
|
||||
import ocelot.desktop.util.animation.ValueAnimation
|
||||
import ocelot.desktop.util.{DrawUtils, Logging, Persistable}
|
||||
import ocelot.desktop.{ColorScheme, OcelotDesktop}
|
||||
import org.lwjgl.input.Keyboard
|
||||
import ocelot.desktop.{ColorScheme, OcelotDesktop, Settings}
|
||||
import totoro.ocelot.brain.entity.traits.{Environment, SidedEnvironment}
|
||||
import totoro.ocelot.brain.entity.{Case, Screen}
|
||||
import totoro.ocelot.brain.event.{EventBus, InventoryEvent, NodeEvent}
|
||||
@ -28,6 +29,7 @@ import scala.collection.immutable.ArraySeq
|
||||
import scala.collection.{immutable, mutable}
|
||||
import scala.jdk.CollectionConverters._
|
||||
|
||||
|
||||
class WorkspaceView extends Widget with Persistable with MouseHandler with HoverHandler with Logging {
|
||||
@volatile
|
||||
var nodes: immutable.Seq[Node] = immutable.ArraySeq[Node]()
|
||||
@ -262,10 +264,10 @@ class WorkspaceView extends Widget with Persistable with MouseHandler with Hover
|
||||
nodeSelector.close()
|
||||
}
|
||||
|
||||
case KeyEvent(KeyEvent.State.Press, Keyboard.KEY_F4, _) =>
|
||||
case Press(Profiler) =>
|
||||
profilerWindow.open()
|
||||
|
||||
case KeyEvent(KeyEvent.State.Press, Keyboard.KEY_HOME, _) =>
|
||||
case Press(Center) =>
|
||||
moveCameraOffset(-cameraOffset)
|
||||
}
|
||||
|
||||
@ -608,7 +610,7 @@ class WorkspaceView extends Widget with Persistable with MouseHandler with Hover
|
||||
nodes.foreach(_.update())
|
||||
|
||||
if (isHovered) {
|
||||
root.get.statusBar.addKeyEntry("HOME", "Reset camera")
|
||||
root.get.statusBar.addKeyEntry(Settings.get.keymap.name(Center), "Reset camera")
|
||||
}
|
||||
|
||||
if (isHovered || nodes.exists(_.isHovered)) {
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
package ocelot.desktop.ui.widget.settings
|
||||
|
||||
import ocelot.desktop.color.Color
|
||||
import ocelot.desktop.{ColorScheme, Settings}
|
||||
import ocelot.desktop.geometry.{Padding2D, Size2D}
|
||||
import ocelot.desktop.graphics.IconSource
|
||||
import ocelot.desktop.ui.event.KeyEvent
|
||||
import ocelot.desktop.ui.layout.LinearLayout
|
||||
import ocelot.desktop.ui.widget.{Button, Label, PaddingBox, Widget}
|
||||
import ocelot.desktop.util.Keybind.Keybind
|
||||
import ocelot.desktop.util.{Keybind, Orientation}
|
||||
import org.lwjgl.input.Keyboard
|
||||
|
||||
|
||||
class KeymapSettingsTab extends SettingsTab {
|
||||
override val layout = new LinearLayout(this, orientation = Orientation.Vertical, gap = 8)
|
||||
|
||||
override val icon: IconSource = IconSource.SettingsKeymap
|
||||
override val label: String = "Keymap"
|
||||
|
||||
private def section(title: String, keybinds: Seq[Keybind]): Widget = new PaddingBox(new Widget {
|
||||
override val layout = new LinearLayout(this, orientation = Orientation.Vertical)
|
||||
|
||||
override def maximumSize: Size2D = minimumSize.copy(width = 257)
|
||||
|
||||
children :+= new PaddingBox(new Label(title, small = true) {
|
||||
override def maximumSize: Size2D = minimumSize
|
||||
override def color: Color = ColorScheme("LabelDisabled")
|
||||
}, Padding2D(top = 4, bottom = 8))
|
||||
|
||||
keybinds.foreach(keybind => {
|
||||
children :+= new PaddingBox(new Widget {
|
||||
children :+= new PaddingBox(new Label(keybind.description), Padding2D(top = 4, right = 8))
|
||||
children :+= new Button {
|
||||
private var listening: Boolean = false
|
||||
|
||||
eventHandlers += {
|
||||
case KeyEvent(KeyEvent.State.Release, code, _) if listening =>
|
||||
Settings.get.keymap.set(keybind, code)
|
||||
listening = false
|
||||
}
|
||||
|
||||
override def text: String = if (listening) "..." else Keyboard.getKeyName(Settings.get.keymap(keybind))
|
||||
override def onClick(): Unit = {
|
||||
listening = !listening
|
||||
}
|
||||
}
|
||||
}, Padding2D(bottom = 4))
|
||||
})
|
||||
}, Padding2D(bottom = 8))
|
||||
|
||||
children :+= new PaddingBox(new Widget {
|
||||
children :+= new Widget {
|
||||
override val layout = new LinearLayout(this, orientation = Orientation.Vertical)
|
||||
children :+= section("OpenComputers", Seq(
|
||||
Keybind.Insert,
|
||||
))
|
||||
children :+= section("Ocelot", Seq(
|
||||
Keybind.UIDebug,
|
||||
Keybind.FPSCounter,
|
||||
Keybind.ReloadWorkspace,
|
||||
Keybind.Profiler,
|
||||
Keybind.Fullscreen,
|
||||
))
|
||||
}
|
||||
children :+= new Widget {
|
||||
override def maximumSize: Size2D = Size2D(16, 8)
|
||||
}
|
||||
children :+= section("Workspace", Seq(
|
||||
Keybind.Center,
|
||||
Keybind.QuickSave,
|
||||
Keybind.QuickLoad,
|
||||
Keybind.Screenshot,
|
||||
))
|
||||
}, Padding2D(bottom = 8))
|
||||
}
|
||||
@ -16,6 +16,7 @@ class SettingsDialog extends ModalDialog {
|
||||
private val tabs = Seq(
|
||||
new UISettingsTab,
|
||||
new SoundSettingsTab,
|
||||
new KeymapSettingsTab,
|
||||
new SystemSettingsTab,
|
||||
)
|
||||
|
||||
|
||||
@ -5,17 +5,19 @@ import ocelot.desktop.geometry.{Padding2D, Size2D}
|
||||
import ocelot.desktop.graphics.{Graphics, IconSource}
|
||||
import ocelot.desktop.ui.UiHandler
|
||||
import ocelot.desktop.ui.event.handlers.{HoverHandler, MouseHandler}
|
||||
import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, KeyEvent, MouseEvent}
|
||||
import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent}
|
||||
import ocelot.desktop.ui.layout.{AlignItems, LinearLayout}
|
||||
import ocelot.desktop.ui.widget._
|
||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
||||
import ocelot.desktop.ui.widget.traits.HoverAnimation
|
||||
import ocelot.desktop.util.Keybind.FPSCounter
|
||||
import ocelot.desktop.util.Keymap.Press
|
||||
import ocelot.desktop.{ColorScheme, OcelotDesktop}
|
||||
import org.lwjgl.input.Keyboard
|
||||
|
||||
import scala.collection.immutable.ArraySeq
|
||||
import scala.concurrent.duration.DurationInt
|
||||
|
||||
|
||||
class StatusBar extends Widget {
|
||||
override protected val layout: LinearLayout = new LinearLayout(this, alignItems = AlignItems.Center)
|
||||
|
||||
@ -28,7 +30,7 @@ class StatusBar extends Widget {
|
||||
private var showFPS = false
|
||||
|
||||
eventHandlers += {
|
||||
case KeyEvent(KeyEvent.State.Press, Keyboard.KEY_F2, _) =>
|
||||
case Press(FPSCounter) =>
|
||||
showFPS = !showFPS
|
||||
if (showFPS) {
|
||||
children :+= new PaddingBox(
|
||||
|
||||
@ -6,6 +6,26 @@ package ocelot.desktop.util
|
||||
*/
|
||||
|
||||
object Keybind extends Enumeration {
|
||||
type Keybind = Value
|
||||
val Insert: Keybind = Value
|
||||
type Keybind = KeybindVal
|
||||
|
||||
// OpenComputers
|
||||
val Insert: Keybind = KeybindVal("Insert text")
|
||||
|
||||
// Workspace
|
||||
val Center: Keybind = KeybindVal("Center camera")
|
||||
val QuickSave: Keybind = KeybindVal("Quick save")
|
||||
val QuickLoad: Keybind = KeybindVal("Quick load")
|
||||
val Screenshot: Keybind = KeybindVal("Save screenshot")
|
||||
|
||||
// Ocelot
|
||||
val UIDebug: Keybind = KeybindVal("UI Debug Mode")
|
||||
val FPSCounter: Keybind = KeybindVal("FPS counter")
|
||||
val ReloadWorkspace: Keybind = KeybindVal("Reload workspace")
|
||||
val Profiler: Keybind = KeybindVal("Ocelot profiler")
|
||||
val Fullscreen: Keybind = KeybindVal("Toggle fullscreen mode")
|
||||
|
||||
protected class KeybindVal(val description: String) extends super.Val
|
||||
private object KeybindVal {
|
||||
def apply(description: String): KeybindVal = new KeybindVal(description)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,37 @@
|
||||
package ocelot.desktop.util
|
||||
|
||||
import com.typesafe.config.{Config, ConfigValue, ConfigValueFactory}
|
||||
import ocelot.desktop.Settings
|
||||
import ocelot.desktop.ui.event.KeyEvent
|
||||
import ocelot.desktop.ui.event.KeyEvent.State
|
||||
import ocelot.desktop.util.Keybind.Keybind
|
||||
import org.lwjgl.input.Keyboard
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.jdk.CollectionConverters._
|
||||
|
||||
|
||||
class Keymap {
|
||||
// default mappings
|
||||
val map: mutable.Map[Keybind, Int] = mutable.Map(
|
||||
Keybind.Insert -> Keyboard.KEY_INSERT
|
||||
val map: mutable.Map[Keybind.Value, Int] = mutable.Map(
|
||||
// OpenComputers
|
||||
Keybind.Insert -> Keyboard.KEY_INSERT,
|
||||
|
||||
// Workspace
|
||||
Keybind.Center -> Keyboard.KEY_HOME,
|
||||
Keybind.QuickSave -> Keyboard.KEY_F5,
|
||||
Keybind.QuickLoad -> Keyboard.KEY_F9,
|
||||
Keybind.Screenshot -> Keyboard.KEY_F12,
|
||||
|
||||
// Ocelot
|
||||
Keybind.UIDebug -> Keyboard.KEY_F1,
|
||||
Keybind.FPSCounter -> Keyboard.KEY_F2,
|
||||
Keybind.ReloadWorkspace -> Keyboard.KEY_F3,
|
||||
Keybind.Profiler -> Keyboard.KEY_F4,
|
||||
Keybind.Fullscreen -> Keyboard.KEY_F11,
|
||||
)
|
||||
|
||||
|
||||
/** Retrieves the LWJGL keycode which is associated with the given keybind.
|
||||
* Will return `Keyboard.KEY_NONE` if the binding is not found.
|
||||
*
|
||||
@ -32,7 +51,30 @@ class Keymap {
|
||||
* before the `set` operation was executed, or `None` if this keybind
|
||||
* was not defined in the keymap before.
|
||||
*/
|
||||
def set(keybind: Keybind, key: Int): Option[Int] = map.put(keybind, key)
|
||||
def set(keybind: Keybind.Value, key: Int): Option[Int] = map.put(keybind, key)
|
||||
|
||||
/**
|
||||
* Retrieves the name for a keyboard key associated with the given keybind.
|
||||
* @param keybind the keybind
|
||||
* @return the name of the button on the keyboard, for example "HOME", or "F1"
|
||||
*/
|
||||
def name(keybind: Keybind): String = Keyboard.getKeyName(apply(keybind))
|
||||
|
||||
|
||||
override def clone(): Keymap = {
|
||||
val clone = new Keymap
|
||||
clone.map.addAll(this.map)
|
||||
clone
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tries to find a keybind that corresponds to the specific LWJGL key code
|
||||
* @param key the LWJGL key code
|
||||
* @return Option containing the keybind (if found)
|
||||
*/
|
||||
private def findByCode(key: Int): Option[Keybind] = map.iterator.collectFirst { case (keybind: Keybind, `key`) => keybind }
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to read known keybindings from a config.
|
||||
@ -55,3 +97,20 @@ class Keymap {
|
||||
case (key: Keybind, value: Int) => (key.toString.toLowerCase(), value)
|
||||
}).toMap.asJava)
|
||||
}
|
||||
|
||||
object Keymap {
|
||||
object Press {
|
||||
def unapply(event: KeyEvent): Option[Keybind] = event match {
|
||||
case KeyEvent(State.Press, code, _) =>
|
||||
Settings.get.keymap.findByCode(code)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
object Release {
|
||||
def unapply(event: KeyEvent): Option[Keybind] = event match {
|
||||
case KeyEvent(State.Release, code, _) =>
|
||||
Settings.get.keymap.findByCode(code)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ class SettingsData {
|
||||
def this(data: SettingsData) {
|
||||
this()
|
||||
updateWith(data)
|
||||
keymap = data.keymap.clone()
|
||||
}
|
||||
|
||||
var brainCustomConfigPath: Option[String] = None
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user