separate view files; B93Funge stores Value objects
This commit is contained in:
@@ -3,64 +3,48 @@ package befide.befunge.b93
|
|||||||
import befide.befunge.core.*
|
import befide.befunge.core.*
|
||||||
import befide.befunge.state.*
|
import befide.befunge.state.*
|
||||||
|
|
||||||
|
fun <T> List<T>.padEnd(size: Int, factory: (Int) -> (T)): List<T> = this + (this.size until size).map { factory(it) }
|
||||||
|
|
||||||
class B93Funge : Funge {
|
class B93Funge : Funge {
|
||||||
override val width = 80
|
override val width = 80
|
||||||
override val height = 25
|
override val height = 25
|
||||||
private var cars = Array(height) { Array(width) { ' '.toLong() } }
|
|
||||||
|
val bounds = Vec(width, height)
|
||||||
|
|
||||||
|
private var cars = Array(height) { Array(width) { Value(' ') } }
|
||||||
|
|
||||||
override fun get(vec: Vec): Value {
|
override fun get(vec: Vec): Value {
|
||||||
return Value(cars[vec.y][vec.x])
|
return cars[vec.y][vec.x]
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun set(vec: Vec, value: Value) {
|
override fun set(vec: Vec, value: Value) {
|
||||||
cars[vec.y][vec.x] = value.value
|
cars[vec.y][vec.x] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun nextVec(vec: Vec, delta: Vec): Vec {
|
override fun nextVec(vec: Vec, delta: Vec): Vec {
|
||||||
var x = vec.x + delta.x
|
return (vec + delta) mod bounds
|
||||||
var y = vec.y + delta.y
|
|
||||||
if (x >= width || x < 0) {
|
|
||||||
x %= width
|
|
||||||
}
|
|
||||||
if (x < 0) {
|
|
||||||
x += width
|
|
||||||
}
|
|
||||||
if (y >= height || y < 0) {
|
|
||||||
y %= height
|
|
||||||
}
|
|
||||||
if (y < 0) {
|
|
||||||
y += height
|
|
||||||
}
|
|
||||||
|
|
||||||
return Vec(x, y)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setString(data: String) {
|
override fun setString(data: String) {
|
||||||
val strings = data.split('\n')
|
cars = data.split("\n").map {
|
||||||
for (i in strings.size until height) {
|
it.map {
|
||||||
cars[i] = Array(width) { ' '.toLong() }
|
Value(it)
|
||||||
}
|
}.padEnd(width) {
|
||||||
strings.map {
|
Value(' ')
|
||||||
it.toList().map { it.toLong() }
|
}.toTypedArray()
|
||||||
}
|
}.padEnd(height) {
|
||||||
.forEachIndexed { index, list ->
|
Array(width) {
|
||||||
if (index > height) {
|
Value(' ')
|
||||||
return
|
}
|
||||||
}
|
}.toTypedArray()
|
||||||
cars[index] = (
|
|
||||||
list.toList() + List(
|
|
||||||
if (list.size <= width) width - list.size else 0
|
|
||||||
) {
|
|
||||||
' '.toLong()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.subList(0, width)
|
|
||||||
.toTypedArray()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return cars.map { it.map { Value(it).asChar ?: '?' }.joinToString("") }.joinToString("\n")
|
return cars.joinToString("\n") { row ->
|
||||||
|
row.joinToString("") { value ->
|
||||||
|
(value.asChar ?: '?').toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
package befide.befunge.state
|
package befide.befunge.state
|
||||||
|
|
||||||
|
infix fun Int.mod(other: Int): Int {
|
||||||
|
val x = this % other
|
||||||
|
return if (x >= 0) x else (x + other)
|
||||||
|
}
|
||||||
|
|
||||||
data class Vec(val x: Int, val y: Int) {
|
data class Vec(val x: Int, val y: Int) {
|
||||||
operator fun plus(other: Vec) = Vec(x + other.x, y + other.y)
|
operator fun plus(other: Vec) = Vec(x + other.x, y + other.y)
|
||||||
operator fun times(c: Int) = Vec(x * c, y * c)
|
operator fun times(c: Int) = Vec(x * c, y * c)
|
||||||
|
|
||||||
|
infix fun mod(other: Vec) = Vec(x mod other.x, y mod other.y)
|
||||||
}
|
}
|
||||||
51
ide/src/main/kotlin/befide/ide/ActionView.kt
Normal file
51
ide/src/main/kotlin/befide/ide/ActionView.kt
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package befide.ide
|
||||||
|
|
||||||
|
import befide.befunge.core.Interpreter
|
||||||
|
import javafx.animation.Animation
|
||||||
|
import javafx.animation.Timeline
|
||||||
|
import javafx.util.Duration
|
||||||
|
import tornadofx.*
|
||||||
|
|
||||||
|
class ActionView(val interp: Interpreter) : View() {
|
||||||
|
var runTimeline: Timeline = timeline(false) {
|
||||||
|
keyframe(Duration.seconds(0.0)) {
|
||||||
|
setOnFinished {
|
||||||
|
if (!interp.step())
|
||||||
|
this@timeline.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyframe(Duration.seconds(1.0)) {}
|
||||||
|
|
||||||
|
cycleCount = Animation.INDEFINITE
|
||||||
|
}
|
||||||
|
|
||||||
|
override val root = hbox {
|
||||||
|
button("step") {
|
||||||
|
setOnAction { interp.step() }
|
||||||
|
}
|
||||||
|
|
||||||
|
button("reset") {
|
||||||
|
setOnAction { interp.reset() }
|
||||||
|
}
|
||||||
|
|
||||||
|
button("run") {
|
||||||
|
setOnAction {
|
||||||
|
runTimeline.rate = 1000.0
|
||||||
|
runTimeline.playFromStart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button("crawl") {
|
||||||
|
setOnAction {
|
||||||
|
runTimeline.rate = 2.0
|
||||||
|
runTimeline.playFromStart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button("stop") {
|
||||||
|
setOnAction {
|
||||||
|
runTimeline.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
ide/src/main/kotlin/befide/ide/CodeView.kt
Normal file
19
ide/src/main/kotlin/befide/ide/CodeView.kt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package befide.ide
|
||||||
|
|
||||||
|
import befide.befunge.core.Interpreter
|
||||||
|
import javafx.beans.property.SimpleStringProperty
|
||||||
|
import tornadofx.*
|
||||||
|
|
||||||
|
class CodeView(val interp: Interpreter) : View() {
|
||||||
|
val srcProperty = SimpleStringProperty("")
|
||||||
|
var src by srcProperty
|
||||||
|
|
||||||
|
init {
|
||||||
|
interp.fungeChanged += { src = interp.funge.toString() }
|
||||||
|
srcProperty.addListener { _, _, newValue -> interp.funge.setString(newValue) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val root = textarea(srcProperty) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
34
ide/src/main/kotlin/befide/ide/EditorView.kt
Normal file
34
ide/src/main/kotlin/befide/ide/EditorView.kt
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package befide.ide
|
||||||
|
|
||||||
|
import befide.befunge.b93.B93Interpreter
|
||||||
|
import befide.befunge.core.Interpreter
|
||||||
|
import tornadofx.*
|
||||||
|
|
||||||
|
class EditorView : View("Befide") {
|
||||||
|
private var interp: Interpreter = B93Interpreter()
|
||||||
|
|
||||||
|
private val codeView = CodeView(interp)
|
||||||
|
private val actionView = ActionView(interp)
|
||||||
|
private val stackView = StackView(interp)
|
||||||
|
private val ioView = IOView(interp)
|
||||||
|
|
||||||
|
override val root = borderpane {
|
||||||
|
addClass("editor-root")
|
||||||
|
|
||||||
|
top { add(actionView) }
|
||||||
|
|
||||||
|
center {
|
||||||
|
add(codeView)
|
||||||
|
}
|
||||||
|
|
||||||
|
right {
|
||||||
|
add(stackView)
|
||||||
|
}
|
||||||
|
|
||||||
|
bottom { add(ioView) }
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
codeView.src = """64+"!dlroW ,olleH">:#,_@"""
|
||||||
|
}
|
||||||
|
}
|
||||||
25
ide/src/main/kotlin/befide/ide/IOView.kt
Normal file
25
ide/src/main/kotlin/befide/ide/IOView.kt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package befide.ide
|
||||||
|
|
||||||
|
import befide.befunge.core.Interpreter
|
||||||
|
import javafx.beans.property.SimpleStringProperty
|
||||||
|
import tornadofx.*
|
||||||
|
|
||||||
|
class IOView(val interp: Interpreter) : View() {
|
||||||
|
val outputProperty = SimpleStringProperty("")
|
||||||
|
var output by outputProperty
|
||||||
|
|
||||||
|
init {
|
||||||
|
// add listeners to interp, handle streams, idk
|
||||||
|
}
|
||||||
|
|
||||||
|
override val root = vbox {
|
||||||
|
addClass("")
|
||||||
|
textarea(outputProperty) {
|
||||||
|
// width, height, idk
|
||||||
|
prefHeight = 200.0
|
||||||
|
}
|
||||||
|
textfield {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,128 +1,6 @@
|
|||||||
package befide.ide
|
package befide.ide
|
||||||
|
|
||||||
import befide.befunge.b93.B93Interpreter
|
|
||||||
import befide.befunge.core.Interpreter
|
|
||||||
import befide.befunge.core.Pointer
|
|
||||||
import javafx.animation.Animation
|
|
||||||
import javafx.animation.Timeline
|
|
||||||
import javafx.beans.property.SimpleObjectProperty
|
|
||||||
import javafx.beans.property.SimpleStringProperty
|
|
||||||
import javafx.util.Duration
|
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import tornadofx.getValue
|
|
||||||
import tornadofx.setValue
|
|
||||||
|
|
||||||
class IOView(val interp: Interpreter) : View() {
|
|
||||||
val textProperty = SimpleStringProperty("")
|
|
||||||
var text by textProperty
|
|
||||||
|
|
||||||
init {
|
|
||||||
// add listeners to interp, handle streams, idk
|
|
||||||
}
|
|
||||||
|
|
||||||
override val root = vbox {
|
|
||||||
textarea(textProperty) {
|
|
||||||
// width, height, idk
|
|
||||||
prefHeight = 200.0
|
|
||||||
}
|
|
||||||
textfield {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ActionView(val interp: Interpreter) : View() {
|
|
||||||
var runTimeline: Timeline = timeline(false) {
|
|
||||||
keyframe(Duration.seconds(0.0)) {
|
|
||||||
setOnFinished {
|
|
||||||
if (!interp.step())
|
|
||||||
this@timeline.stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keyframe(Duration.seconds(1.0)) {}
|
|
||||||
|
|
||||||
cycleCount = Animation.INDEFINITE
|
|
||||||
}
|
|
||||||
|
|
||||||
override val root = hbox {
|
|
||||||
button("step") {
|
|
||||||
setOnAction { interp.step() }
|
|
||||||
}
|
|
||||||
|
|
||||||
button("reset") {
|
|
||||||
setOnAction { interp.reset() }
|
|
||||||
}
|
|
||||||
|
|
||||||
button("run") {
|
|
||||||
setOnAction {
|
|
||||||
runTimeline.rate = 1000.0
|
|
||||||
runTimeline.playFromStart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button("crawl") {
|
|
||||||
setOnAction {
|
|
||||||
runTimeline.rate = 2.0
|
|
||||||
runTimeline.playFromStart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button("stop") {
|
|
||||||
setOnAction {
|
|
||||||
runTimeline.stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CodeView(val interp: Interpreter) : View() {
|
|
||||||
val srcProperty = SimpleStringProperty("")
|
|
||||||
var src by srcProperty
|
|
||||||
|
|
||||||
init {
|
|
||||||
interp.fungeChanged += { src = interp.funge.toString() }
|
|
||||||
srcProperty.addListener { _, _, newValue -> interp.funge.setString(newValue) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override val root = textarea(srcProperty) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StackView(val interp: Interpreter) : View() {
|
|
||||||
override val root = textarea {
|
|
||||||
prefWidth = 100.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class EditorView : View("Befide") {
|
|
||||||
private var interp: Interpreter = B93Interpreter()
|
|
||||||
|
|
||||||
private val codeView = CodeView(interp)
|
|
||||||
private val actionView = ActionView(interp)
|
|
||||||
private val stackView = StackView(interp)
|
|
||||||
private val ioView = IOView(interp)
|
|
||||||
|
|
||||||
override val root = borderpane {
|
|
||||||
addClass("editor-root")
|
|
||||||
|
|
||||||
top { add(actionView) }
|
|
||||||
|
|
||||||
center {
|
|
||||||
add(codeView)
|
|
||||||
}
|
|
||||||
|
|
||||||
right {
|
|
||||||
add(stackView)
|
|
||||||
}
|
|
||||||
|
|
||||||
bottom { add(ioView) }
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
codeView.src = """64+"!dlroW ,olleH">:#,_@"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MainApp : App(EditorView::class) {
|
class MainApp : App(EditorView::class) {
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
package befide.ide
|
|
||||||
|
|
||||||
import befide.befunge.b93.B93Interpreter
|
|
||||||
import befide.befunge.core.Interpreter
|
|
||||||
import javafx.beans.property.SimpleIntegerProperty
|
|
||||||
import javafx.scene.Parent
|
|
||||||
import javafx.scene.control.Label
|
|
||||||
import tornadofx.*
|
|
||||||
|
|
||||||
|
|
||||||
class SampleView : View() {
|
|
||||||
private val controller: SampleController by inject()
|
|
||||||
|
|
||||||
override val root: Parent by fxml()
|
|
||||||
|
|
||||||
private val width: Label by fxid()
|
|
||||||
private val height: Label by fxid()
|
|
||||||
|
|
||||||
init {
|
|
||||||
importStylesheet(resources["style.css"])
|
|
||||||
|
|
||||||
width.bind(controller.width)
|
|
||||||
height.bind(controller.height)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SampleController : Controller() {
|
|
||||||
private val bf: Interpreter = B93Interpreter()
|
|
||||||
|
|
||||||
val width = SimpleIntegerProperty()
|
|
||||||
val height = SimpleIntegerProperty()
|
|
||||||
|
|
||||||
init {
|
|
||||||
// sample event subscription. this is not necessary, but would update the
|
|
||||||
// width and height labels every time a value in the funge is changed
|
|
||||||
bf.fungeChanged += { updateFungeLabels() }
|
|
||||||
|
|
||||||
updateFungeLabels()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateFungeLabels() {
|
|
||||||
width.set(bf.funge.width)
|
|
||||||
height.set(bf.funge.height)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SampleApp : App() {
|
|
||||||
override val primaryView = SampleView::class
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
launch<SampleApp>(args)
|
|
||||||
}
|
|
||||||
10
ide/src/main/kotlin/befide/ide/StackView.kt
Normal file
10
ide/src/main/kotlin/befide/ide/StackView.kt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package befide.ide
|
||||||
|
|
||||||
|
import befide.befunge.core.Interpreter
|
||||||
|
import tornadofx.*
|
||||||
|
|
||||||
|
class StackView(val interp: Interpreter) : View() {
|
||||||
|
override val root = textarea {
|
||||||
|
prefWidth = 100.0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<?import javafx.scene.control.Label?>
|
|
||||||
<?import javafx.scene.layout.*?>
|
|
||||||
|
|
||||||
<GridPane alignment="CENTER" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="300.0"
|
|
||||||
xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1">
|
|
||||||
<Label text="Width: " styleClass="lbl"
|
|
||||||
fx:id="widthLabel"/>
|
|
||||||
<Label text="Height: " styleClass="lbl"
|
|
||||||
fx:id="heightLabel" GridPane.rowIndex="1"/>
|
|
||||||
<Label text="{width}" styleClass="val"
|
|
||||||
fx:id="width" GridPane.columnIndex="1"/>
|
|
||||||
<Label text="{height}" styleClass="val"
|
|
||||||
fx:id="height" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
|
|
||||||
</GridPane>
|
|
||||||
@@ -7,3 +7,7 @@
|
|||||||
-fx-font-family: monospace;
|
-fx-font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.editor-root {
|
||||||
|
-fx-padding: 4px;
|
||||||
|
-fx-border-insets: 4px;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user