forked from nova/jmonkey-test
Rohan Sircar
3 years ago
41 changed files with 2415 additions and 463 deletions
-
20build.sbt
-
BINlib/jme-jfx-11-1.1.5.jar
-
10src/main/scala/com/jayfella/jme/jfx/package.scala
-
24src/main/scala/com/jme3/animation/package.scala
-
5src/main/scala/com/jme3/app/package.scala
-
6src/main/scala/com/jme3/input/controls/package.scala
-
3src/main/scala/com/jme3/input/package.scala
-
4src/main/scala/com/jme3/scene/package.scala
-
3src/main/scala/org/slf4j/impl/StaticLoggerBuilder.scala
-
88src/main/scala/wow/doge/mygame/Main.scala
-
109src/main/scala/wow/doge/mygame/MainApp.scala
-
142src/main/scala/wow/doge/mygame/game/GameApp.scala
-
38src/main/scala/wow/doge/mygame/game/GameApp2.scala
-
13src/main/scala/wow/doge/mygame/game/GameModule.scala
-
4src/main/scala/wow/doge/mygame/game/GameSystemsInitializer.scala
-
8src/main/scala/wow/doge/mygame/game/nodes/PlayerController.scala
-
4src/main/scala/wow/doge/mygame/game/nodes/PlayerEventListeners.scala
-
33src/main/scala/wow/doge/mygame/game/subsystems/ai/GdxAiTest.scala
-
43src/main/scala/wow/doge/mygame/game/subsystems/ai/gdx/Graph.java
-
371src/main/scala/wow/doge/mygame/game/subsystems/ai/gdx/IndexedAStarPathFinder.java
-
41src/main/scala/wow/doge/mygame/game/subsystems/ai/gdx/MyIndexedGraph.java
-
24src/main/scala/wow/doge/mygame/game/subsystems/input/GameInputHandler.scala
-
6src/main/scala/wow/doge/mygame/game/subsystems/level/DefaultGameLevel.scala
-
12src/main/scala/wow/doge/mygame/game/subsystems/level/GameLevel.scala
-
43src/main/scala/wow/doge/mygame/game/subsystems/ui/JmeJfx.scala
-
88src/main/scala/wow/doge/mygame/implicits/JavaFXMonixObservables.scala
-
43src/main/scala/wow/doge/mygame/implicits/TestEnum.scala
-
18src/main/scala/wow/doge/mygame/implicits/observables/package.scala
-
69src/main/scala/wow/doge/mygame/implicits/package.scala
-
102src/main/scala/wow/doge/mygame/launcher/DefaultUI.scala
-
153src/main/scala/wow/doge/mygame/launcher/Launcher.scala
-
2src/main/scala/wow/doge/mygame/subsystems/events/MovementEvents.scala
-
3src/main/scala/wow/doge/mygame/subsystems/moddingsystem/ModdingSystem.scala
-
35src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptActor.scala
-
73src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptCachingActor.scala
-
1src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptSystemModule.scala
-
750src/main/scala/wow/doge/mygame/utils/BorderlessScene.scala
-
104src/main/scala/wow/doge/mygame/utils/GenericConsoleStream.scala
-
71src/main/scala/wow/doge/mygame/utils/JFXConsoleStream.scala
-
130src/main/scala/wow/doge/mygame/utils/ResizeHelper.java
-
24src/main/scala/wow/doge/mygame/utils/TreeTest.scala
@ -0,0 +1,10 @@ |
|||
package com.jayfella.jme |
|||
|
|||
package object jfx { |
|||
// object JavaFxUI { |
|||
// def apply(app: Application) = { |
|||
// JavaFxUI.initialize(app) |
|||
// JavaFxUI.getInstance() |
|||
// } |
|||
// } |
|||
} |
@ -0,0 +1,33 @@ |
|||
package wow.doge.mygame.game.subsystems.ai |
|||
|
|||
import com.badlogic.gdx.ai.pfa.Connection |
|||
import wow.doge.mygame.game.subsystems.ai.gdx.MyIndexedGraph |
|||
import scala.collection.immutable.ArraySeq |
|||
// import com.badlogic.gdx.ai.pfa.indexed.IndexedGraph |
|||
// import scala.jdk.javaapi.CollectionConverters._ |
|||
|
|||
case class City(x: Float, y: Float, name: String, index: Int) |
|||
case class Street(fromNode: City, toNode: City, cost: Float) |
|||
extends Connection[City] { |
|||
|
|||
override def getCost(): Float = cost |
|||
|
|||
override def getFromNode(): City = fromNode |
|||
|
|||
override def getToNode(): City = toNode |
|||
|
|||
} |
|||
|
|||
class CityGraph extends MyIndexedGraph[City] { |
|||
|
|||
override def getConnections( |
|||
city: City |
|||
): IndexedSeq[Connection[City]] = |
|||
ArraySeq(Street(City(0f, 0f, "egw", 0), City(0f, 0f, "egw", 0), 1)) |
|||
// or Vector(Street(City(0f, 0f, "egw", 0), City(0f, 0f, "egw", 0), 1)) |
|||
|
|||
override def getIndex(city: City): Int = ??? |
|||
|
|||
override def getNodeCount(): Int = ??? |
|||
|
|||
} |
@ -0,0 +1,43 @@ |
|||
/******************************************************************************* |
|||
* Copyright 2014 See AUTHORS file. |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0 |
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
******************************************************************************/ |
|||
|
|||
package wow.doge.mygame.game.subsystems.ai.gdx; |
|||
|
|||
import com.badlogic.gdx.ai.pfa.Connection; |
|||
|
|||
import com.badlogic.gdx.utils.Array; |
|||
// import java.lang.Iterable; |
|||
import java.util.List; |
|||
import scala.collection.immutable.IndexedSeq; |
|||
|
|||
/** |
|||
* A graph is a collection of nodes, each one having a collection of outgoing |
|||
* {@link Connection connections}. |
|||
* |
|||
* @param <N> Type of node |
|||
* |
|||
* @author davebaol |
|||
*/ |
|||
public interface Graph<N> { |
|||
|
|||
/** |
|||
* Returns the connections outgoing from the given node. |
|||
* |
|||
* @param fromNode the node whose outgoing connections will be returned |
|||
* @return the array of connections outgoing from the given node. |
|||
*/ |
|||
public IndexedSeq<Connection<N>> getConnections(N fromNode); |
|||
} |
@ -0,0 +1,371 @@ |
|||
/******************************************************************************* |
|||
* Copyright 2014 See AUTHORS file. |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0 |
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
******************************************************************************/ |
|||
|
|||
package wow.doge.mygame.game.subsystems.ai.gdx; |
|||
|
|||
import com.badlogic.gdx.ai.pfa.Connection; |
|||
import com.badlogic.gdx.ai.pfa.GraphPath; |
|||
import com.badlogic.gdx.ai.pfa.Heuristic; |
|||
import com.badlogic.gdx.ai.pfa.PathFinder; |
|||
import com.badlogic.gdx.ai.pfa.PathFinderQueue; |
|||
import com.badlogic.gdx.ai.pfa.PathFinderRequest; |
|||
import com.badlogic.gdx.utils.Array; |
|||
import com.badlogic.gdx.utils.BinaryHeap; |
|||
import com.badlogic.gdx.utils.TimeUtils; |
|||
import java.util.List; |
|||
import wow.doge.mygame.game.subsystems.ai.gdx.Graph; |
|||
import wow.doge.mygame.game.subsystems.ai.gdx.MyIndexedGraph; |
|||
import scala.collection.immutable.IndexedSeq; |
|||
|
|||
/** |
|||
* A fully implemented {@link PathFinder} that can perform both interruptible |
|||
* and non-interruptible pathfinding. |
|||
* <p> |
|||
* This implementation is a common variation of the A* algorithm that is faster |
|||
* than the general A*. |
|||
* <p> |
|||
* In the general A* implementation, data are held for each node in the open or |
|||
* closed lists, and these data are held as a NodeRecord instance. Records are |
|||
* created when a node is first considered and then moved between the open and |
|||
* closed lists, as required. There is a key step in the algorithm where the |
|||
* lists are searched for a node record corresponding to a particular node. This |
|||
* operation is something time-consuming. |
|||
* <p> |
|||
* The indexed A* algorithm improves execution speed by using an array of all |
|||
* the node records for every node in the graph. Nodes must be numbered using |
|||
* sequential integers (see {@link MyIndexedGraph#getIndex(Object)}), so we |
|||
* don't need to search for a node in the two lists at all. We can simply use |
|||
* the node index to look up its record in the array (creating it if it is |
|||
* missing). This means that the close list is no longer needed. To know whether |
|||
* a node is open or closed, we use the {@link NodeRecord#category category} of |
|||
* the node record. This makes the search step very fast indeed (in fact, there |
|||
* is no search, and we can go straight to the information we need). |
|||
* Unfortunately, we can't get rid of the open list because we still need to be |
|||
* able to retrieve the element with the lowest cost. However, we use a |
|||
* {@link BinaryHeap} for the open list in order to keep performance as high as |
|||
* possible. |
|||
* |
|||
* @param <N> Type of node |
|||
* |
|||
* @author davebaol |
|||
*/ |
|||
public class IndexedAStarPathFinder<N> implements PathFinder<N> { |
|||
MyIndexedGraph<N> graph; |
|||
NodeRecord<N>[] nodeRecords; |
|||
BinaryHeap<NodeRecord<N>> openList; |
|||
NodeRecord<N> current; |
|||
public Metrics metrics; |
|||
|
|||
/** The unique ID for each search run. Used to mark nodes. */ |
|||
private int searchId; |
|||
|
|||
private static final int UNVISITED = 0; |
|||
private static final int OPEN = 1; |
|||
private static final int CLOSED = 2; |
|||
|
|||
public IndexedAStarPathFinder(MyIndexedGraph<N> graph) { |
|||
this(graph, false); |
|||
} |
|||
|
|||
@SuppressWarnings("unchecked") |
|||
public IndexedAStarPathFinder(MyIndexedGraph<N> graph, boolean calculateMetrics) { |
|||
this.graph = graph; |
|||
this.nodeRecords = (NodeRecord<N>[]) new NodeRecord[graph.getNodeCount()]; |
|||
this.openList = new BinaryHeap<NodeRecord<N>>(); |
|||
if (calculateMetrics) |
|||
this.metrics = new Metrics(); |
|||
} |
|||
|
|||
@Override |
|||
public boolean searchConnectionPath(N startNode, N endNode, Heuristic<N> heuristic, |
|||
GraphPath<Connection<N>> outPath) { |
|||
|
|||
// Perform AStar |
|||
boolean found = search(startNode, endNode, heuristic); |
|||
|
|||
if (found) { |
|||
// Create a path made of connections |
|||
generateConnectionPath(startNode, outPath); |
|||
} |
|||
|
|||
return found; |
|||
} |
|||
|
|||
@Override |
|||
public boolean searchNodePath(N startNode, N endNode, Heuristic<N> heuristic, GraphPath<N> outPath) { |
|||
|
|||
// Perform AStar |
|||
boolean found = search(startNode, endNode, heuristic); |
|||
|
|||
if (found) { |
|||
// Create a path made of nodes |
|||
generateNodePath(startNode, outPath); |
|||
} |
|||
|
|||
return found; |
|||
} |
|||
|
|||
protected boolean search(N startNode, N endNode, Heuristic<N> heuristic) { |
|||
|
|||
initSearch(startNode, endNode, heuristic); |
|||
|
|||
// Iterate through processing each node |
|||
do { |
|||
// Retrieve the node with smallest estimated total cost from the open list |
|||
current = openList.pop(); |
|||
current.category = CLOSED; |
|||
|
|||
// Terminate if we reached the goal node |
|||
if (current.node == endNode) |
|||
return true; |
|||
|
|||
visitChildren(endNode, heuristic); |
|||
|
|||
} while (openList.size > 0); |
|||
|
|||
// We've run out of nodes without finding the goal, so there's no solution |
|||
return false; |
|||
} |
|||
|
|||
@Override |
|||
public boolean search(PathFinderRequest<N> request, long timeToRun) { |
|||
|
|||
long lastTime = TimeUtils.nanoTime(); |
|||
|
|||
// We have to initialize the search if the status has just changed |
|||
if (request.statusChanged) { |
|||
initSearch(request.startNode, request.endNode, request.heuristic); |
|||
request.statusChanged = false; |
|||
} |
|||
|
|||
// Iterate through processing each node |
|||
do { |
|||
|
|||
// Check the available time |
|||
long currentTime = TimeUtils.nanoTime(); |
|||
timeToRun -= currentTime - lastTime; |
|||
if (timeToRun <= PathFinderQueue.TIME_TOLERANCE) |
|||
return false; |
|||
|
|||
// Retrieve the node with smallest estimated total cost from the open list |
|||
current = openList.pop(); |
|||
current.category = CLOSED; |
|||
|
|||
// Terminate if we reached the goal node; we've found a path. |
|||
if (current.node == request.endNode) { |
|||
request.pathFound = true; |
|||
|
|||
generateNodePath(request.startNode, request.resultPath); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
// Visit current node's children |
|||
visitChildren(request.endNode, request.heuristic); |
|||
|
|||
// Store the current time |
|||
lastTime = currentTime; |
|||
|
|||
} while (openList.size > 0); |
|||
|
|||
// The open list is empty and we've not found a path. |
|||
request.pathFound = false; |
|||
return true; |
|||
} |
|||
|
|||
protected void initSearch(N startNode, N endNode, Heuristic<N> heuristic) { |
|||
if (metrics != null) |
|||
metrics.reset(); |
|||
|
|||
// Increment the search id |
|||
if (++searchId < 0) |
|||
searchId = 1; |
|||
|
|||
// Initialize the open list |
|||
openList.clear(); |
|||
|
|||
// Initialize the record for the start node and add it to the open list |
|||
NodeRecord<N> startRecord = getNodeRecord(startNode); |
|||
startRecord.node = startNode; |
|||
startRecord.connection = null; |
|||
startRecord.costSoFar = 0; |
|||
addToOpenList(startRecord, heuristic.estimate(startNode, endNode)); |
|||
|
|||
current = null; |
|||
} |
|||
|
|||
protected void visitChildren(N endNode, Heuristic<N> heuristic) { |
|||
// Get current node's outgoing connections |
|||
IndexedSeq<Connection<N>> connections = graph.getConnections(current.node); |
|||
|
|||
// Loop through each connection in turn |
|||
for (int i = 0; i < connections.size(); i++) { |
|||
if (metrics != null) |
|||
metrics.visitedNodes++; |
|||
|
|||
Connection<N> connection = connections.apply(i); |
|||
|
|||
// Get the cost estimate for the node |
|||
N node = connection.getToNode(); |
|||
float nodeCost = current.costSoFar + connection.getCost(); |
|||
|
|||
float nodeHeuristic; |
|||
NodeRecord<N> nodeRecord = getNodeRecord(node); |
|||
if (nodeRecord.category == CLOSED) { // The node is closed |
|||
|
|||
// If we didn't find a shorter route, skip |
|||
if (nodeRecord.costSoFar <= nodeCost) |
|||
continue; |
|||
|
|||
// We can use the node's old cost values to calculate its heuristic |
|||
// without calling the possibly expensive heuristic function |
|||
nodeHeuristic = nodeRecord.getEstimatedTotalCost() - nodeRecord.costSoFar; |
|||
} else if (nodeRecord.category == OPEN) { // The node is open |
|||
|
|||
// If our route is no better, then skip |
|||
if (nodeRecord.costSoFar <= nodeCost) |
|||
continue; |
|||
|
|||
// Remove it from the open list (it will be re-added with the new cost) |
|||
openList.remove(nodeRecord); |
|||
|
|||
// We can use the node's old cost values to calculate its heuristic |
|||
// without calling the possibly expensive heuristic function |
|||
nodeHeuristic = nodeRecord.getEstimatedTotalCost() - nodeRecord.costSoFar; |
|||
} else { // the node is unvisited |
|||
|
|||
// We'll need to calculate the heuristic value using the function, |
|||
// since we don't have a node record with a previously calculated value |
|||
nodeHeuristic = heuristic.estimate(node, endNode); |
|||
} |
|||
|
|||
// Update node record's cost and connection |
|||
nodeRecord.costSoFar = nodeCost; |
|||
nodeRecord.connection = connection; |
|||
|
|||
// Add it to the open list with the estimated total cost |
|||
addToOpenList(nodeRecord, nodeCost + nodeHeuristic); |
|||
} |
|||
|
|||
} |
|||
|
|||
protected void generateConnectionPath(N startNode, GraphPath<Connection<N>> outPath) { |
|||
|
|||
// Work back along the path, accumulating connections |
|||
// outPath.clear(); |
|||
while (current.node != startNode) { |
|||
outPath.add(current.connection); |
|||
current = nodeRecords[graph.getIndex(current.connection.getFromNode())]; |
|||
} |
|||
|
|||
// Reverse the path |
|||
outPath.reverse(); |
|||
} |
|||
|
|||
protected void generateNodePath(N startNode, GraphPath<N> outPath) { |
|||
|
|||
// Work back along the path, accumulating nodes |
|||
// outPath.clear(); |
|||
while (current.connection != null) { |
|||
outPath.add(current.node); |
|||
current = nodeRecords[graph.getIndex(current.connection.getFromNode())]; |
|||
} |
|||
outPath.add(startNode); |
|||
|
|||
// Reverse the path |
|||
outPath.reverse(); |
|||
} |
|||
|
|||
protected void addToOpenList(NodeRecord<N> nodeRecord, float estimatedTotalCost) { |
|||
openList.add(nodeRecord, estimatedTotalCost); |
|||
nodeRecord.category = OPEN; |
|||
if (metrics != null) { |
|||
metrics.openListAdditions++; |
|||
metrics.openListPeak = Math.max(metrics.openListPeak, openList.size); |
|||
} |
|||
} |
|||
|
|||
protected NodeRecord<N> getNodeRecord(N node) { |
|||
int index = graph.getIndex(node); |
|||
NodeRecord<N> nr = nodeRecords[index]; |
|||
if (nr != null) { |
|||
if (nr.searchId != searchId) { |
|||
nr.category = UNVISITED; |
|||
nr.searchId = searchId; |
|||
} |
|||
return nr; |
|||
} |
|||
nr = nodeRecords[index] = new NodeRecord<N>(); |
|||
nr.node = node; |
|||
nr.searchId = searchId; |
|||
return nr; |
|||
} |
|||
|
|||
/** |
|||
* This nested class is used to keep track of the information we need for each |
|||
* node during the search. |
|||
* |
|||
* @param <N> Type of node |
|||
* |
|||
* @author davebaol |
|||
*/ |
|||
static class NodeRecord<N> extends BinaryHeap.Node { |
|||
/** The reference to the node. */ |
|||
N node; |
|||
|
|||
/** The incoming connection to the node */ |
|||
Connection<N> connection; |
|||
|
|||
/** The actual cost from the start node. */ |
|||
float costSoFar; |
|||
|
|||
/** The node category: {@link #UNVISITED}, {@link #OPEN} or {@link #CLOSED}. */ |
|||
int category; |
|||
|
|||
/** ID of the current search. */ |
|||
int searchId; |
|||
|
|||
/** Creates a {@code NodeRecord}. */ |
|||
public NodeRecord() { |
|||
super(0); |
|||
} |
|||
|
|||
/** Returns the estimated total cost. */ |
|||
public float getEstimatedTotalCost() { |
|||
return getValue(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* A class used by {@link IndexedAStarPathFinder} to collect search metrics. |
|||
* |
|||
* @author davebaol |
|||
*/ |
|||
public static class Metrics { |
|||
public int visitedNodes; |
|||
public int openListAdditions; |
|||
public int openListPeak; |
|||
|
|||
public Metrics() { |
|||
} |
|||
|
|||
public void reset() { |
|||
visitedNodes = 0; |
|||
openListAdditions = 0; |
|||
openListPeak = 0; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,41 @@ |
|||
/******************************************************************************* |
|||
* Copyright 2014 See AUTHORS file. |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0 |
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
******************************************************************************/ |
|||
|
|||
package wow.doge.mygame.game.subsystems.ai.gdx; |
|||
|
|||
import wow.doge.mygame.game.subsystems.ai.gdx.Graph; |
|||
|
|||
/** |
|||
* A graph for the {@link IndexedAStarPathFinder}. |
|||
* |
|||
* @param <N> Type of node |
|||
* |
|||
* @author davebaol |
|||
*/ |
|||
public interface MyIndexedGraph<N> extends Graph<N> { |
|||
|
|||
/** |
|||
* Returns the unique index of the given node. |
|||
* |
|||
* @param node the node whose index will be returned |
|||
* @return the unique index of the given node. |
|||
*/ |
|||
public int getIndex(N node); |
|||
|
|||
/** Returns the number of nodes in this graph. */ |
|||
public int getNodeCount(); |
|||
|
|||
} |
@ -0,0 +1,43 @@ |
|||
package wow.doge.mygame.game.subsystems.ui |
|||
|
|||
import com.jme3.app.Application |
|||
import com.jayfella.jme.jfx.JavaFxUI |
|||
import scalafx.application.Platform |
|||
import monix.execution.CancelablePromise |
|||
import monix.bio.Task |
|||
import cats.effect.concurrent.Deferred |
|||
import scala.concurrent.duration._ |
|||
import wow.doge.mygame.game.GameApp |
|||
|
|||
object JFxUI { |
|||
def apply(app: GameApp) = |
|||
Task(JavaFxUI.initialize(app)) |
|||
.executeOn(app.scheduler) >> Task.sleep(500.millis) >> Task( |
|||
JavaFxUI.getInstance() |
|||
) |
|||
// Task { |
|||
// Platform.runLater(() => { |
|||
// println("here jfx") |
|||
// JavaFxUI.initialize(app) |
|||
// println("here2 jfx2") |
|||
// val inst = JavaFxUI.getInstance() |
|||
// println(inst) |
|||
// }) |
|||
// } |
|||
// Task.fromFuture { |
|||
// val p = CancelablePromise[JavaFxUI]() |
|||
// Platform.runLater(() => { |
|||
// println("here") |
|||
// JavaFxUI.initialize(app) |
|||
// println("here2") |
|||
// val inst = JavaFxUI.getInstance() |
|||
// println(inst) |
|||
// p.success(inst) |
|||
// }) |
|||
// p.future |
|||
// } |
|||
// for { |
|||
// d <- Deferred[Task, JavaFxUI] |
|||
// _ <- Task(JavaFxUI.initialize(app)) |
|||
// } yield () |
|||
} |
@ -0,0 +1,88 @@ |
|||
package wow.doge.mygame.implicits |
|||
|
|||
import javafx.{ |
|||
collections => jfxc, |
|||
event => jfxe, |
|||
geometry => jfxg, |
|||
scene => jfxs, |
|||
util => jfxu |
|||
} |
|||
import javafx.scene.{input => jfxsi, layout => jfxsl, paint => jfxsp} |
|||
import scalafx.scene.Scene |
|||
import monix.execution.Cancelable |
|||
import monix.reactive.OverflowStrategy |
|||
import monix.reactive.Observable |
|||
import monix.execution.Ack |
|||
import scalafx.scene.control.ButtonBase |
|||
|
|||
object JavaFXMonixObservables { |
|||
|
|||
implicit final class SceneObservables(private val scene: Scene) |
|||
extends AnyVal { |
|||
def observableMousePressed(): Observable[jfxsi.MouseEvent] = { |
|||
import monix.execution.cancelables.SingleAssignCancelable |
|||
Observable.create(OverflowStrategy.Unbounded) { sub => |
|||
val c = SingleAssignCancelable() |
|||
val l = new jfxe.EventHandler[jfxsi.MouseEvent] { |
|||
override def handle(event: jfxsi.MouseEvent): Unit = { |
|||
if (sub.onNext(event) == Ack.Stop) c.cancel() |
|||
} |
|||
} |
|||
|
|||
scene.onMousePressed = l |
|||
c := Cancelable(() => |
|||
scene.removeEventHandler( |
|||
jfxsi.MouseEvent.MOUSE_PRESSED, |
|||
l |
|||
) |
|||
) |
|||
c |
|||
} |
|||
} |
|||
def observableMouseDragged(): Observable[jfxsi.MouseEvent] = { |
|||
import monix.execution.cancelables.SingleAssignCancelable |
|||
Observable.create(OverflowStrategy.Unbounded) { sub => |
|||
val c = SingleAssignCancelable() |
|||
val l = new jfxe.EventHandler[jfxsi.MouseEvent] { |
|||
override def handle(event: jfxsi.MouseEvent): Unit = { |
|||
if (sub.onNext(event) == Ack.Stop) c.cancel() |
|||
} |
|||
} |
|||
|
|||
scene.onMouseDragged = l |
|||
c := Cancelable(() => |
|||
scene.removeEventHandler( |
|||
jfxsi.MouseEvent.MOUSE_DRAGGED, |
|||
l |
|||
) |
|||
) |
|||
c |
|||
} |
|||
} |
|||
} |
|||
|
|||
implicit final class OnActionObservable( |
|||
private val button: ButtonBase |
|||
) extends AnyVal { |
|||
def observableAction(): Observable[jfxe.ActionEvent] = { |
|||
import monix.execution.cancelables.SingleAssignCancelable |
|||
Observable.create(OverflowStrategy.Unbounded) { sub => |
|||
val c = SingleAssignCancelable() |
|||
val l = new jfxe.EventHandler[jfxe.ActionEvent] { |
|||
override def handle(event: jfxe.ActionEvent): Unit = { |
|||
if (sub.onNext(event) == Ack.Stop) c.cancel() |
|||
} |
|||
} |
|||
|
|||
button.onAction = l |
|||
c := Cancelable(() => |
|||
button.removeEventHandler( |
|||
jfxe.ActionEvent.ACTION, |
|||
l |
|||
) |
|||
) |
|||
c |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,43 +0,0 @@ |
|||
package wow.doge.mygame.implicits |
|||
|
|||
import enumeratum._ |
|||
|
|||
sealed trait TestEnum extends EnumEntry |
|||
|
|||
object TestEnum extends Enum[TestEnum] { |
|||
val values = findValues |
|||
case object Test2 extends TestEnum |
|||
} |
|||
|
|||
sealed trait Greeting extends EnumEntry |
|||
|
|||
object Greeting extends Enum[Greeting] { |
|||
|
|||
/* |
|||
`findValues` is a protected method that invokes a macro to find all `Greeting` object declarations inside an `Enum` |
|||
|
|||
You use it to implement the `val values` member |
|||
*/ |
|||
val values = findValues |
|||
|
|||
case object Hello extends Greeting |
|||
case object GoodBye extends Greeting |
|||
case object Hi extends Greeting |
|||
case object Bye extends Greeting |
|||
|
|||
} |
|||
object ObsTest {} |
|||
|
|||
sealed trait PlayerMovementEnum extends EnumEntry { |
|||
def test: String |
|||
} |
|||
|
|||
object PlayerMovementEnum extends Enum[PlayerMovementEnum] { |
|||
val values = findValues |
|||
case object MOVE_RIGHT extends PlayerMovementEnum { |
|||
val test = "hmm" |
|||
} |
|||
case object MOVE_LEFT extends PlayerMovementEnum { |
|||
val test = "mmh" |
|||
} |
|||
} |
@ -0,0 +1,18 @@ |
|||
package wow.doge.mygame.implicits |
|||
|
|||
import javafx.{ |
|||
collections => jfxc, |
|||
event => jfxe, |
|||
geometry => jfxg, |
|||
scene => jfxs, |
|||
util => jfxu |
|||
} |
|||
import javafx.scene.{input => jfxsi, layout => jfxsl, paint => jfxsp} |
|||
import scalafx.scene.Scene |
|||
import monix.execution.Cancelable |
|||
import monix.reactive.OverflowStrategy |
|||
import monix.reactive.Observable |
|||
import monix.execution.Ack |
|||
import scalafx.scene.control.Button |
|||
|
|||
package object observables {} |
@ -0,0 +1,102 @@ |
|||
package wow.doge.mygame.launcher |
|||
|
|||
import scalafx.geometry.Insets |
|||
import scalafx.scene.Scene |
|||
import scalafx.scene.effect.DropShadow |
|||
import scalafx.scene.layout.HBox |
|||
import scalafx.scene.paint.Color._ |
|||
import scalafx.scene.paint._ |
|||
import scalafx.scene.text.Text |
|||
import scalafx.scene.control.Button |
|||
import scalafx.scene.layout.VBox |
|||
import scalafx.scene.layout.FlowPane |
|||
import scalafx.geometry.Orientation |
|||
import scalafx.geometry.Pos |
|||
import scalafx.stage.Stage |
|||
|
|||
object DefaultUI { |
|||
def scene( |
|||
// stage: Stage, |
|||
launchButton: Button, |
|||
exitButton: Button |
|||
) = |
|||
new Scene { |
|||
fill = Color.rgb(38, 38, 38) |
|||
content = new VBox { |
|||
children = Seq( |
|||
new HBox { |
|||
padding = Insets(50, 80, 50, 80) |
|||
children = Seq( |
|||
new Text { |
|||
text = "JMonkeyEngine" |
|||
style = "-fx-font: normal bold 50pt sans-serif" |
|||
fill = new LinearGradient(endX = 0, stops = Stops(Red, DarkRed)) |
|||
}, |
|||
new Text { |
|||
text = " Game" |
|||
style = "-fx-font: italic bold 50pt sans-serif" |
|||
fill = new LinearGradient( |
|||
endX = 0, |
|||
stops = Stops(White, DarkGray) |
|||
) |
|||
effect = new DropShadow { |
|||
color = DarkGray |
|||
radius = 15 |
|||
spread = 0.25 |
|||
} |
|||
} |
|||
) |
|||
}, |
|||
new FlowPane { |
|||
hgap = 10 |
|||
padding = Insets(50, 80, 50, 80) |
|||
orientation = Orientation.Horizontal |
|||
alignment = Pos.Center |
|||
children = Seq(launchButton, exitButton) |
|||
} |
|||
) |
|||
} |
|||
// onMousePressed = (pressEvent) => { |
|||
// onMouseDragged = (dragEvent) => { |
|||
// stage.setX(dragEvent.getScreenX() - pressEvent.getSceneX()) |
|||
// stage.setY(dragEvent.getScreenY() - pressEvent.getSceneY()) |
|||
// } |
|||
// } |
|||
} |
|||
|
|||
def box(launchButton: Button, exitButton: Button) = |
|||
new VBox { |
|||
children = Seq( |
|||
new HBox { |
|||
padding = Insets(50, 80, 50, 80) |
|||
children = Seq( |
|||
new Text { |
|||
text = "JMonkeyEngine" |
|||
style = "-fx-font: normal bold 50pt sans-serif" |
|||
fill = new LinearGradient(endX = 0, stops = Stops(Red, DarkRed)) |
|||
}, |
|||
new Text { |
|||
text = " Game" |
|||
style = "-fx-font: italic bold 50pt sans-serif" |
|||
fill = new LinearGradient( |
|||
endX = 0, |
|||
stops = Stops(White, DarkGray) |
|||
) |
|||
effect = new DropShadow { |
|||
color = DarkGray |
|||
radius = 15 |
|||
spread = 0.25 |
|||
} |
|||
} |
|||
) |
|||
}, |
|||
new FlowPane { |
|||
hgap = 10 |
|||
padding = Insets(50, 80, 50, 80) |
|||
orientation = Orientation.Horizontal |
|||
alignment = Pos.Center |
|||
children = Seq(launchButton, exitButton) |
|||
} |
|||
) |
|||
} |
|||
} |
@ -0,0 +1,153 @@ |
|||
package wow.doge.mygame.launcher |
|||
|
|||
import scala.concurrent.duration.FiniteDuration |
|||
import scalafx.application.JFXApp |
|||
import scalafx.application.JFXApp.PrimaryStage |
|||
import wow.doge.mygame.executors.Schedulers |
|||
import cats.effect.Resource |
|||
import monix.bio.Task |
|||
import scala.concurrent.duration._ |
|||
import javafx.application.Platform |
|||
import scalafx.scene.control.Button |
|||
import cats.effect.concurrent.Deferred |
|||
import wow.doge.mygame.utils.IOUtils._ |
|||
import monix.eval.{Task => ETask} |
|||
import monix.reactive.Observable |
|||
import monix.bio.Fiber |
|||
import scalafx.stage.StageStyle |
|||
import scalafx.Includes._ |
|||
import wow.doge.mygame.utils.ResizeHelper |
|||
import scalafx.scene.Scene |
|||
import scalafx.scene.layout.VBox |
|||
import wow.doge.mygame.implicits.JavaFXMonixObservables._ |
|||
import monix.catnap.cancelables.SingleAssignCancelableF |
|||
import monix.catnap.CancelableF |
|||
// import wow.doge.mygame.implicits.JavaFXMonixObservables._ |
|||
|
|||
// import scala.language.implicitConversions |
|||
|
|||
// object Stage { |
|||
// implicit def sfxStage2jfx(v: Stage): jfxs.Stage = if (v != null) v.delegate else null |
|||
// } |
|||
|
|||
object Launcher { |
|||
sealed trait LauncherResult |
|||
object LauncherResult { |
|||
case object LaunchGame extends LauncherResult |
|||
case object Exit extends LauncherResult |
|||
} |
|||
|
|||
class Props( |
|||
val schedulers: Schedulers, |
|||
val signal: Deferred[Task, LauncherResult] |
|||
) { |
|||
// val resource2 |
|||
// : Resource[Task, (LauncherApp, Task[Ref[Task, Stage]], Fiber[Unit])] = |
|||
// Resource.make(for { |
|||
// app <- Task(new LauncherApp(this)) |
|||
// fib <- app.init.start |
|||
// } yield ((app, app.stageRef, fib)))(_._3.cancel) |
|||
val create = Task(new Launcher(this)) |
|||
|
|||
val resource: Resource[Task, Launcher] = |
|||
Resource.make(for { |
|||
app <- Task(new Launcher(this)) |
|||
// fib <- app.init.start |
|||
} yield (app))(_ => Task.unit) |
|||
} |
|||
} |
|||
class Launcher private (props: Launcher.Props) { |
|||
import Launcher._ |
|||
|
|||
private lazy val launchButton = new Button { |
|||
text = "Launch" |
|||
} |
|||
// private lazy val launchButtonObs = |
|||
|
|||
private lazy val launchAction = |
|||
launchButton |
|||
.observableAction() |
|||
.doOnNext(_ => toTask(props.signal.complete(LauncherResult.LaunchGame))) |
|||
|
|||
private lazy val exitButton = new Button { |
|||
text = "Exit" |
|||
} |
|||
// private lazy val exitButtonObs = |
|||
|
|||
private lazy val exitAction = |
|||
exitButton |
|||
.observableAction() |
|||
.doOnNext(_ => toTask(props.signal.complete(LauncherResult.Exit))) |
|||
|
|||
private lazy val _scene = |
|||
// new Scene { |
|||
// content = new VBox |
|||
// } |
|||
DefaultUI.scene(launchButton, exitButton) |
|||
|
|||
private lazy val _stage = new PrimaryStage { |
|||
scene = _scene |
|||
} |
|||
|
|||
private lazy val internal = new JFXApp { |
|||
stage = _stage |
|||
stage.initStyle(StageStyle.Undecorated) |
|||
// ResizeHelper.addResizeListener(stage) |
|||
} |
|||
|
|||
private lazy val sceneDragObservable = { |
|||
lazy val mpo = _scene.observableMousePressed() |
|||
lazy val mdo = _scene.observableMouseDragged() |
|||
|
|||
mpo.mergeMap(pressEvent => |
|||
mdo.doOnNext(dragEvent => |
|||
ETask( |
|||
_stage.setX(dragEvent.screenX - pressEvent.sceneX) |
|||
) >> |
|||
ETask( |
|||
_stage.setY( |
|||
dragEvent.screenY - pressEvent.sceneY |
|||
) |
|||
) |
|||
) |
|||
) |
|||
} |
|||
|
|||
// var stage = internal.stage |
|||
|
|||
// lazy val stageRef = Ref.of[Task, Stage](internal.stage) |
|||
// stage: => PrimaryStage |
|||
def init(delay: FiniteDuration = 2000.millis) = |
|||
for { |
|||
_ <- Task(Platform.setImplicitExit(false)) |
|||
|
|||
fib <- Task(internal.main(Array.empty)).start |
|||
_ <- Task.sleep(500.millis) |
|||
// _ <- Task { |
|||
// // lazy val _stage = new CustomStageBuilder() |
|||
// // .setWindowTitle("CustomStage example") |
|||
// // .setWindowColor("rgb(34,54,122)") |
|||
// // .build() |
|||
// internal.stage.scene = |
|||
// DefaultUI.scene(internal.stage, launchButton, exitButton) |
|||
// // _stage.setScene(DefaultUI.scene(launchButton, exitButton)) |
|||
// // JFXApp.Stage = _stage |
|||
// }.executeOn(props.schedulers.fx) |
|||
// c <- SingleAssignCancelableF[Task] |
|||
sceneDragFib <- toIO(sceneDragObservable.completedL).start |
|||
fib2 <- toIO( |
|||
Observable(launchAction, exitAction).merge |
|||
.doOnNext(_ => |
|||
ETask(internal.stage.close()).executeOn(props.schedulers.fx) |
|||
) |
|||
// .doOnNext(_ => toTask(fib.cancel)) |
|||
.completedL |
|||
).start |
|||
c <- CancelableF[Task](fib.cancel >> fib2.cancel >> sceneDragFib.cancel) |
|||
// _ <- Task { |
|||
// internal.stage = stage |
|||
// }.executeOn(props.schedulers.fx) |
|||
// .delayExecution(delay) |
|||
} yield (c) |
|||
|
|||
} |
@ -0,0 +1,750 @@ |
|||
package wow.doge.mygame.utils |
|||
|
|||
/* |
|||
* Copyright (c) 2011-2019, ScalaFX Project |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* * Redistributions of source code must retain the above copyright |
|||
* notice, this list of conditions and the following disclaimer. |
|||
* * Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* * Neither the name of the ScalaFX Project nor the |
|||
* names of its contributors may be used to endorse or promote products |
|||
* derived from this software without specific prior written permission. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
|||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|||
* DISCLAIMED. IN NO EVENT SHALL THE SCALAFX PROJECT OR ITS CONTRIBUTORS BE LIABLE |
|||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
import javafx.scene.{input => jfxsi, layout => jfxsl, paint => jfxsp} |
|||
import javafx.{ |
|||
collections => jfxc, |
|||
event => jfxe, |
|||
geometry => jfxg, |
|||
scene => jfxs, |
|||
util => jfxu |
|||
} |
|||
import scalafx.Includes._ |
|||
import scalafx.beans.property.{ |
|||
ObjectProperty, |
|||
ReadOnlyDoubleProperty, |
|||
ReadOnlyObjectProperty |
|||
} |
|||
import scalafx.collections._ |
|||
import scalafx.delegate.SFXDelegate |
|||
import scalafx.geometry.NodeOrientation |
|||
import scalafx.scene.image.WritableImage |
|||
import scalafx.scene.input.{Dragboard, Mnemonic, TransferMode} |
|||
import scalafx.scene.paint.Paint |
|||
import com.goxr3plus.fxborderlessscene.borderless.{BorderlessScene => BScene} |
|||
|
|||
import scala.language.implicitConversions |
|||
import scalafx.scene.Cursor |
|||
import scalafx.scene._ |
|||
import scalafx.stage.Stage |
|||
import scalafx.stage.StageStyle |
|||
|
|||
object BorderlessScene { |
|||
implicit def sfxScene2jfx(v: BorderlessScene): Scene = |
|||
if (v != null) v.delegate else null |
|||
} |
|||
|
|||
/** |
|||
* Wraps [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Scene.html]]. |
|||
* |
|||
* @constructor Create a new ScalaFX Scene with JavaFX Scene as delegate. |
|||
* @param delegate JavaFX Scene delegated. Its default value is a JavaFX Scene with a |
|||
* [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Group.html Group]] as root Node. |
|||
*/ |
|||
class BorderlessScene( |
|||
override val delegate: BScene |
|||
) extends SFXDelegate[BScene] { |
|||
|
|||
def this(stage: Stage, stageStyle: StageStyle, parent: Parent) = |
|||
this(new BScene(stage, stageStyle, parent)) |
|||
|
|||
/** |
|||
* Returns the root Node of the scene graph |
|||
*/ |
|||
def root: ObjectProperty[jfxs.Parent] = delegate.rootProperty |
|||
|
|||
/** |
|||
* Sets the root Node of the scene graph |
|||
*/ |
|||
def root_=(v: Parent): Unit = { |
|||
root() = v |
|||
} |
|||
|
|||
/** |
|||
* Returns Nodes children from this Scene's `root`. |
|||
*/ |
|||
def getChildren = |
|||
root.value match { |
|||
case group: jfxs.Group => group.getChildren |
|||
case pane: jfxsl.Pane => pane.getChildren |
|||
case _ => |
|||
throw new IllegalStateException( |
|||
"Cannot access children of root: " + root + "\n" + |
|||
"Use a class that extends Group or Pane, or override the getChildren method." |
|||
) |
|||
} |
|||
|
|||
/** |
|||
* Returns scene's antialiasing setting. |
|||
*/ |
|||
def antialiasing: SceneAntialiasing = delegate.getAntiAliasing |
|||
|
|||
/** |
|||
* Returns Content's Node children from this Scene's `root`. |
|||
*/ |
|||
def content: jfxc.ObservableList[jfxs.Node] = getChildren |
|||
|
|||
/** |
|||
* Sets the list of Nodes children from this Scene's `root`, replacing the prior content. If you want append to |
|||
* current content, use `add` or similar. |
|||
* |
|||
* @param c list of Nodes children from this Scene's `root` to replace prior content. |
|||
*/ |
|||
def content_=(c: Iterable[Node]): Unit = { |
|||
fillSFXCollection(this.content, c) |
|||
} |
|||
|
|||
/** |
|||
* Sets a Node child, replacing the prior content. If you want append to current content, use `add` or similar. |
|||
* |
|||
* @param n Node child to replace prior content. |
|||
*/ |
|||
def content_=(n: Node): Unit = { |
|||
fillSFXCollectionWithOne(this.content, n) |
|||
} |
|||
|
|||
/** |
|||
* Specifies the type of camera use for rendering this `Scene`. |
|||
*/ |
|||
def camera: ObjectProperty[jfxs.Camera] = delegate.cameraProperty |
|||
|
|||
def camera_=(v: Camera): Unit = { |
|||
camera() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines the mouse cursor for this `Scene`. |
|||
*/ |
|||
def cursor: ObjectProperty[jfxs.Cursor] = delegate.cursorProperty |
|||
|
|||
def cursor_=(v: Cursor): Unit = { |
|||
cursor() = v |
|||
} |
|||
|
|||
/** The effective node orientation of a scene resolves the inheritance of node orientation, returning either left-to-right or right-to-left. */ |
|||
def effectiveNodeOrientation: ReadOnlyObjectProperty[jfxg.NodeOrientation] = |
|||
delegate.effectiveNodeOrientationProperty |
|||
|
|||
/** |
|||
* Specifies the event dispatcher for this scene. |
|||
*/ |
|||
def eventDispatcher: ObjectProperty[jfxe.EventDispatcher] = |
|||
delegate.eventDispatcherProperty |
|||
|
|||
def eventDispatcher_=(v: jfxe.EventDispatcher): Unit = { |
|||
eventDispatcher() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines the background fill of this Scene. |
|||
*/ |
|||
def fill: ObjectProperty[jfxsp.Paint] = delegate.fillProperty |
|||
|
|||
def fill_=(v: Paint): Unit = { |
|||
fill() = v |
|||
} |
|||
|
|||
/** |
|||
* The height of this Scene |
|||
*/ |
|||
def height: ReadOnlyDoubleProperty = delegate.heightProperty |
|||
|
|||
/** |
|||
* The width of this Scene |
|||
*/ |
|||
def width: ReadOnlyDoubleProperty = delegate.widthProperty |
|||
|
|||
def nodeOrientation: ObjectProperty[jfxg.NodeOrientation] = |
|||
delegate.nodeOrientationProperty |
|||
|
|||
def nodeOrientation_=(v: NodeOrientation): Unit = { |
|||
ObjectProperty.fillProperty[jfxg.NodeOrientation](this.nodeOrientation, v) |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a mouse button has been clicked (pressed and released) on this `Scene`. |
|||
*/ |
|||
def onContextMenuRequested = delegate.onContextMenuRequestedProperty |
|||
|
|||
def onContextMenuRequested_=( |
|||
v: jfxe.EventHandler[_ >: jfxsi.ContextMenuEvent] |
|||
): Unit = { |
|||
onContextMenuRequested() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when drag gesture has been detected. |
|||
*/ |
|||
def onDragDetected = delegate.onDragDetectedProperty |
|||
|
|||
def onDragDetected_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = { |
|||
onDragDetected() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when this `Scene` is a drag and drop gesture source after its data has been |
|||
* dropped on a drop target. |
|||
*/ |
|||
def onDragDone = delegate.onDragDoneProperty |
|||
|
|||
def onDragDone_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = { |
|||
onDragDone() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when the mouse button is released on this `Scene` during drag and drop gesture. |
|||
*/ |
|||
def onDragDropped = delegate.onDragDroppedProperty |
|||
|
|||
def onDragDropped_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = { |
|||
onDragDropped() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when drag gesture enters this Scene. |
|||
*/ |
|||
def onDragEntered = delegate.onDragEnteredProperty |
|||
|
|||
def onDragEntered_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = { |
|||
onDragEntered() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when drag gesture exits this Scene. |
|||
*/ |
|||
def onDragExited = delegate.onDragExitedProperty |
|||
|
|||
def onDragExited_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = { |
|||
onDragExited() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when drag gesture progresses within this `Scene`. |
|||
*/ |
|||
def onDragOver = delegate.onDragOverProperty |
|||
|
|||
def onDragOver_=(v: jfxe.EventHandler[_ >: jfxsi.DragEvent]): Unit = { |
|||
onDragOver() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when this `Node` has input focus and the input method text has changed. |
|||
*/ |
|||
def onInputMethodTextChanged = delegate.onInputMethodTextChangedProperty |
|||
|
|||
def onInputMethodTextChanged_=( |
|||
v: jfxe.EventHandler[_ >: jfxsi.InputMethodEvent] |
|||
): Unit = { |
|||
onInputMethodTextChanged() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when some `Node` of this `Scene` has input focus and a key has been pressed. |
|||
*/ |
|||
def onKeyPressed = delegate.onKeyPressedProperty |
|||
|
|||
def onKeyPressed_=(v: jfxe.EventHandler[_ >: jfxsi.KeyEvent]): Unit = { |
|||
onKeyPressed() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when some `Node` of this `Scene` has input focus and a key has been released. |
|||
*/ |
|||
def onKeyReleased = delegate.onKeyReleasedProperty |
|||
|
|||
def onKeyReleased_=(v: jfxe.EventHandler[_ >: jfxsi.KeyEvent]): Unit = { |
|||
onKeyReleased() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when some `Node` of this `Scene` has input focus and a key has been typed. |
|||
*/ |
|||
def onKeyTyped = delegate.onKeyTypedProperty |
|||
|
|||
def onKeyTyped_=(v: jfxe.EventHandler[_ >: jfxsi.KeyEvent]): Unit = { |
|||
onKeyTyped() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a mouse button has been clicked (pressed and released) on this `Scene`. |
|||
*/ |
|||
def onMouseClicked = delegate.onMouseClickedProperty |
|||
|
|||
def onMouseClicked_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = { |
|||
onMouseClicked() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a mouse button is pressed on this `Scene` and then dragged. |
|||
*/ |
|||
def onMouseDragged = delegate.onMouseDraggedProperty |
|||
|
|||
def onMouseDragged_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = { |
|||
onMouseDragged() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a full press-drag-release gesture enters this `Scene`. |
|||
*/ |
|||
def onMouseDragEntered = delegate.onMouseDragEnteredProperty |
|||
|
|||
def onMouseDragEntered_=( |
|||
v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent] |
|||
): Unit = { |
|||
onMouseDragEntered() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a full press-drag-release gesture exits this `Scene`. |
|||
*/ |
|||
def onMouseDragExited = delegate.onMouseDragExitedProperty |
|||
|
|||
def onMouseDragExited_=( |
|||
v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent] |
|||
): Unit = { |
|||
onMouseDragExited() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a full press-drag-release gesture progresses within this `Scene`. |
|||
*/ |
|||
def onMouseDragOver = delegate.onMouseDragOverProperty |
|||
|
|||
def onMouseDragOver_=( |
|||
v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent] |
|||
): Unit = { |
|||
onMouseDragOver() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a full press-drag-release gesture ends within this `Scene`. |
|||
*/ |
|||
def onMouseDragReleased = delegate.onMouseDragReleasedProperty |
|||
|
|||
def onMouseDragReleased_=( |
|||
v: jfxe.EventHandler[_ >: jfxsi.MouseDragEvent] |
|||
): Unit = { |
|||
onMouseDragReleased() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when the mouse enters this `Scene`. |
|||
*/ |
|||
def onMouseEntered = delegate.onMouseEnteredProperty |
|||
|
|||
def onMouseEntered_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = { |
|||
onMouseEntered() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when the mouse exits this `Scene`. |
|||
*/ |
|||
def onMouseExited = delegate.onMouseExitedProperty |
|||
|
|||
def onMouseExited_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = { |
|||
onMouseExited() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when mouse cursor moves within this `Scene` but no buttons have been pushed. |
|||
*/ |
|||
def onMouseMoved = delegate.onMouseMovedProperty |
|||
|
|||
def onMouseMoved_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = { |
|||
onMouseMoved() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a mouse button has been pressed on this `Scene`. |
|||
*/ |
|||
def onMousePressed = delegate.onMousePressedProperty |
|||
|
|||
def onMousePressed_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = { |
|||
onMousePressed() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a mouse button has been released on this `Scene`. |
|||
*/ |
|||
def onMouseReleased = delegate.onMouseReleasedProperty |
|||
|
|||
def onMouseReleased_=(v: jfxe.EventHandler[_ >: jfxsi.MouseEvent]): Unit = { |
|||
onMouseReleased() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when user performs a scrolling action. |
|||
*/ |
|||
def onScroll = delegate.onScrollProperty |
|||
|
|||
def onScroll_=(v: jfxe.EventHandler[_ >: jfxsi.ScrollEvent]): Unit = { |
|||
onScroll() = v |
|||
} |
|||
|
|||
/** |
|||
* The URL of the user-agent stylesheet that will be used by this Scene in place of the the platform-default |
|||
* user-agent stylesheet. If the URL does not resolve to a valid location, the platform-default user-agent |
|||
* stylesheet will be used. |
|||
* |
|||
* For additional information about using CSS with the scene graph, see the |
|||
* [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html CSS Reference Guide]]. |
|||
* |
|||
* @return The URL of the user-agent stylesheet that will be used by this SubScene, or null if has not been set. |
|||
*/ |
|||
def userAgentStylesheet: ObjectProperty[String] = |
|||
delegate.userAgentStylesheetProperty |
|||
|
|||
/** |
|||
* Set the URL of the user-agent stylesheet that will be used by this Scene in place of the the platform-default |
|||
* user-agent stylesheet. If the URL does not resolve to a valid location, the platform-default user-agent |
|||
* stylesheet will be used. |
|||
* |
|||
* For additional information about using CSS with the scene graph, see the |
|||
* [[http://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html CSS Reference Guide]]. |
|||
* |
|||
* @param url The URL is a hierarchical URI of the form `[scheme:][//authority][path]`. |
|||
* If the URL does not have a `[scheme:]` component, the URL is considered to be the `[path]` |
|||
* component only. Any leading '/' character of the `[path]` is ignored and the `[path]` is |
|||
* treated as a path relative to the root of the application's classpath. |
|||
*/ |
|||
def userAgentStylesheet_=(url: String): Unit = { |
|||
ObjectProperty.fillProperty[String](userAgentStylesheet, url) |
|||
} |
|||
|
|||
/** |
|||
* The `Window` for this Scene |
|||
*/ |
|||
def window: ReadOnlyObjectProperty[javafx.stage.Window] = |
|||
delegate.windowProperty |
|||
|
|||
/** |
|||
* The horizontal location of this `Scene` on the `Window`. |
|||
*/ |
|||
def x: ReadOnlyDoubleProperty = delegate.xProperty |
|||
|
|||
/** |
|||
* The vertical location of this `Scene` on the `Window`. |
|||
*/ |
|||
def y: ReadOnlyDoubleProperty = delegate.yProperty |
|||
|
|||
/** |
|||
* Retrieves the depth buffer attribute for this scene. |
|||
*/ |
|||
def depthBuffer = delegate.isDepthBuffer |
|||
|
|||
/** |
|||
* Gets an observable list of string URLs linking to the stylesheets to use with this Parent's contents. |
|||
*/ |
|||
def stylesheets: jfxc.ObservableList[String] = delegate.getStylesheets |
|||
|
|||
/** |
|||
* Sets the list of stylesheets URLs, replacing the prior content. If you want append to current content, use `add` or |
|||
* similar. |
|||
* |
|||
* @param c list of stylesheets URLs to replace prior content. |
|||
*/ |
|||
def stylesheets_=(c: Iterable[String]): Unit = { |
|||
fillCollection(stylesheets, c) |
|||
} |
|||
|
|||
/** |
|||
* Looks for any node within the scene graph based on the specified CSS selector. |
|||
* |
|||
* @param selector The css selector to look up |
|||
* @return A [[scala.Some]] containing the Node in the scene which matches the CSS selector, or [[scala.None]] |
|||
* if none is found. |
|||
*/ |
|||
def lookup(selector: String): Option[Node] = Option(delegate.lookup(selector)) |
|||
|
|||
/** |
|||
* Registers the specified mnemonic. |
|||
* |
|||
* @param m The Mnemonic |
|||
*/ |
|||
def addMnemonic(m: Mnemonic): Unit = { |
|||
delegate.addMnemonic(m) |
|||
} |
|||
|
|||
/** |
|||
* Unregisters the specified mnemonic. |
|||
* |
|||
* @param m The Mnemonic to be removed. |
|||
*/ |
|||
def removeMnemonic(m: Mnemonic): Unit = { |
|||
delegate.removeMnemonic(m) |
|||
} |
|||
|
|||
/** |
|||
* Gets the list of mnemonics for this `Scene`. |
|||
*/ |
|||
def getMnemonics |
|||
: jfxc.ObservableMap[jfxsi.KeyCombination, jfxc.ObservableList[ |
|||
jfxsi.Mnemonic |
|||
]] = delegate.getMnemonics |
|||
|
|||
/** |
|||
* Gets the list of accelerators for this Scene. |
|||
*/ |
|||
def accelerators: jfxc.ObservableMap[jfxsi.KeyCombination, Runnable] = |
|||
delegate.getAccelerators |
|||
|
|||
/** |
|||
* Confirms a potential drag and drop gesture that is recognized over this `Scene`. |
|||
* |
|||
* @param transferModes The supported `TransferMode`(s) of this `Node` |
|||
* @return A `Dragboard` to place this `Scene`'s data on |
|||
*/ |
|||
def startDragAndDrop(transferModes: TransferMode*): Dragboard = |
|||
delegate.startDragAndDrop(transferModes.map(_.delegate): _*) |
|||
|
|||
/** |
|||
* Starts a full press-drag-release gesture with this scene as gesture source. |
|||
*/ |
|||
def startFullDrag(): Unit = { |
|||
delegate.startFullDrag() |
|||
} |
|||
|
|||
/** |
|||
* The scene's current focus owner node. This node's "focused" variable might be false if this scene has no window, |
|||
* or if the window is inactive (window.focused == false). |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def focusOwner: ReadOnlyObjectProperty[jfxs.Node] = |
|||
delegate.focusOwnerProperty() |
|||
|
|||
/** |
|||
* Defines a function to be called when user performs a rotation action. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onRotate = delegate.onRotateProperty |
|||
|
|||
def onRotate_=(v: jfxe.EventHandler[_ >: jfxsi.RotateEvent]): Unit = { |
|||
onRotate() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a rotation gesture ends. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onRotationFinished = delegate.onRotationFinishedProperty() |
|||
|
|||
def onRotationFinished_=( |
|||
v: jfxe.EventHandler[_ >: jfxsi.RotateEvent] |
|||
): Unit = { |
|||
onRotationFinished() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a rotation gesture starts. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onRotationStarted = delegate.onRotationFinishedProperty() |
|||
|
|||
def onRotationStarted_=( |
|||
v: jfxe.EventHandler[_ >: jfxsi.RotateEvent] |
|||
): Unit = { |
|||
onRotationStarted() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a Scroll gesture ends. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onScrollFinished = delegate.onScrollFinishedProperty() |
|||
|
|||
def onScrollFinished_=(v: jfxe.EventHandler[_ >: jfxsi.ScrollEvent]): Unit = { |
|||
onScrollFinished() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a Scroll gesture starts. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onScrollStarted = delegate.onScrollStartedProperty() |
|||
|
|||
def onScrollStarted_=(v: jfxe.EventHandler[_ >: jfxsi.ScrollEvent]): Unit = { |
|||
onScrollStarted() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a Swipe Down gesture starts. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onSwipeDown = delegate.onSwipeDownProperty() |
|||
|
|||
def onSwipeDown_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = { |
|||
onSwipeDown() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a Swipe Down gesture starts. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onSwipeLeft = delegate.onSwipeLeftProperty() |
|||
|
|||
def onSwipeLeft_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = { |
|||
onSwipeLeft() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a Swipe Up gesture starts. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onSwipeUp = delegate.onSwipeUpProperty() |
|||
|
|||
def onSwipeUp_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = { |
|||
onSwipeUp() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a Swipe Right gesture starts. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onSwipeRight = delegate.onSwipeRightProperty() |
|||
|
|||
def onSwipeRight_=(v: jfxe.EventHandler[_ >: jfxsi.SwipeEvent]): Unit = { |
|||
onSwipeRight() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when user performs a Touch action. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onZoom = delegate.onZoomProperty() |
|||
|
|||
def onZoom_=(v: jfxe.EventHandler[_ >: jfxsi.ZoomEvent]): Unit = { |
|||
onZoom() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a Zoom gesture ends. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onZoomFinished = delegate.onZoomFinishedProperty() |
|||
|
|||
def onZoomFinished_=(v: jfxe.EventHandler[_ >: jfxsi.ZoomEvent]): Unit = { |
|||
onZoomFinished() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when a Zoom gesture starts. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onZoomStarted = delegate.onZoomStartedProperty() |
|||
|
|||
def onZoomStarted_=(v: jfxe.EventHandler[_ >: jfxsi.ZoomEvent]): Unit = { |
|||
onZoomStarted() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when user performs a Touch Moved action. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onTouchMoved = delegate.onTouchMovedProperty() |
|||
|
|||
def onTouchMoved_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = { |
|||
onTouchMoved() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when user performs a Touch Pressed action. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onTouchPressed = delegate.onTouchPressedProperty() |
|||
|
|||
def onTouchPressed_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = { |
|||
onTouchPressed() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when user performs a Touch Released action. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onTouchReleased = delegate.onTouchReleasedProperty() |
|||
|
|||
def onTouchReleased_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = { |
|||
onTouchReleased() = v |
|||
} |
|||
|
|||
/** |
|||
* Defines a function to be called when user performs a Touch Stationary action. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def onTouchStationary = delegate.onTouchStationaryProperty() |
|||
|
|||
def onTouchStationary_=(v: jfxe.EventHandler[_ >: jfxsi.TouchEvent]): Unit = { |
|||
onTouchStationary() = v |
|||
} |
|||
|
|||
/** |
|||
* Takes a snapshot of this scene and returns the rendered image when it is ready. |
|||
* |
|||
* @param image The writable image that will be used to hold the rendered scene. |
|||
* @return the rendered image |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def snapshot(image: WritableImage): WritableImage = delegate.snapshot(image) |
|||
|
|||
/** |
|||
* Takes a snapshot of this scene at the next frame and calls the specified callback method when the image is ready. |
|||
* |
|||
* @param callback A function to be called when the image is ready. |
|||
* @param image The writable image that will be used to hold the rendered scene. |
|||
* |
|||
* @since 2.2 |
|||
*/ |
|||
def snapshot(callback: SnapshotResult => Unit, image: WritableImage): Unit = { |
|||
val javaCallback = new jfxu.Callback[jfxs.SnapshotResult, java.lang.Void] { |
|||
def call(result: jfxs.SnapshotResult): java.lang.Void = { |
|||
callback(new SnapshotResult(result)) |
|||
null |
|||
} |
|||
} |
|||
delegate.snapshot(javaCallback, image) |
|||
} |
|||
|
|||
} |
@ -0,0 +1,104 @@ |
|||
package wow.doge.mygame.utils |
|||
|
|||
import java.io.ByteArrayOutputStream |
|||
import java.io.OutputStream |
|||
import java.io.PrintStream |
|||
|
|||
import cats.effect.Resource |
|||
import monix.bio.Task |
|||
import scalafx.scene.control.TextArea |
|||
import scalafx.application.Platform |
|||
|
|||
trait ConsoleStreamable[T] { |
|||
def println(inst: T, text: String): Unit |
|||
def print(inst: T, text: String): Unit |
|||
} |
|||
|
|||
class GenericConsoleStream[T]( |
|||
outputStream: OutputStream, |
|||
val config: GenericConsoleStream.Config = |
|||
GenericConsoleStream.Config.default, |
|||
private var streamable: Option[T] = None |
|||
)(implicit |
|||
cs: ConsoleStreamable[T] |
|||
) extends PrintStream(outputStream, true) { |
|||
private lazy val defaultOut = System.out |
|||
|
|||
def printToStreamable(stble: Option[T], text: String) = |
|||
stble.foreach(s => cs.println(s, text)) |
|||
|
|||
override def println(text: String): Unit = |
|||
if (config.exclusive) { |
|||
printToStreamable(streamable, text) |
|||
} else { |
|||
defaultOut.println(text) |
|||
printToStreamable(streamable, text) |
|||
} |
|||
|
|||
override def print(text: String): Unit = |
|||
streamable.foreach(s => |
|||
if (config.exclusive) { |
|||
printToStreamable(streamable, text) |
|||
} else { |
|||
defaultOut.println(text) |
|||
printToStreamable(streamable, text) |
|||
} |
|||
) |
|||
|
|||
def :=(s: T) = { |
|||
streamable match { |
|||
case Some(value) => |
|||
case None => streamable = Some(s) |
|||
} |
|||
} |
|||
} |
|||
|
|||
object GenericConsoleStream { |
|||
|
|||
/** |
|||
* for future use |
|||
*/ |
|||
case class Config(exclusive: Boolean = false) |
|||
object Config { |
|||
lazy val default = Config() |
|||
} |
|||
|
|||
implicit val implJFXConsoleStreamForTextArea = |
|||
new ConsoleStreamable[scalafx.scene.control.TextArea] { |
|||
|
|||
override def println( |
|||
ta: scalafx.scene.control.TextArea, |
|||
text: String |
|||
): Unit = |
|||
ta.appendText(text + "\n") |
|||
|
|||
override def print( |
|||
ta: scalafx.scene.control.TextArea, |
|||
text: String |
|||
): Unit = |
|||
ta.appendText(text) |
|||
|
|||
} |
|||
|
|||
// def textAreaStreamResource(ta: TextArea) = |
|||
// Resource.make( |
|||
// Task( |
|||
// new GenericConsoleStream( |
|||
// outputStream = new ByteArrayOutputStream(), |
|||
// streamable = ta |
|||
// ) |
|||
// ) |
|||
// )(s => Task(s.close())) |
|||
|
|||
def textAreaStream( |
|||
// ta: TextArea |
|||
) = |
|||
// Task( |
|||
new GenericConsoleStream[TextArea]( |
|||
outputStream = new ByteArrayOutputStream() |
|||
// streamable = ta |
|||
) |
|||
// ) |
|||
// (s => Task(s.close())) |
|||
|
|||
} |
@ -1,71 +0,0 @@ |
|||
package wow.doge.mygame.utils |
|||
|
|||
import java.io.ByteArrayOutputStream |
|||
import java.io.OutputStream |
|||
import java.io.PrintStream |
|||
|
|||
import cats.effect.Resource |
|||
import monix.bio.Task |
|||
import scalafx.scene.control.TextArea |
|||
|
|||
trait JFXConsoleStreamable[T] { |
|||
def println(inst: T, text: String): Unit |
|||
def print(inst: T, text: String): Unit |
|||
} |
|||
|
|||
class JFXConsoleStream[T]( |
|||
outputStream: OutputStream, |
|||
val config: JFXConsoleStream.Config = JFXConsoleStream.Config.default, |
|||
control: T |
|||
)(implicit |
|||
jcs: JFXConsoleStreamable[T] |
|||
) extends PrintStream(outputStream, true) { |
|||
private lazy val defaultOut = System.out |
|||
override def println(text: String): Unit = |
|||
if (config.exclusive) { |
|||
jcs.println(control, text + "\n") |
|||
} else { |
|||
defaultOut.println(text) |
|||
jcs.println(control, text + "\n") |
|||
} |
|||
override def print(text: String): Unit = jcs.println(control, text) |
|||
} |
|||
|
|||
object JFXConsoleStream { |
|||
|
|||
/** |
|||
* for future use |
|||
*/ |
|||
case class Config(exclusive: Boolean = false) |
|||
object Config { |
|||
lazy val default = Config() |
|||
} |
|||
|
|||
implicit val implJFXConsoleStreamForTextArea = |
|||
new JFXConsoleStreamable[scalafx.scene.control.TextArea] { |
|||
|
|||
override def println( |
|||
ta: scalafx.scene.control.TextArea, |
|||
text: String |
|||
): Unit = |
|||
ta.appendText(text + "\n") |
|||
|
|||
override def print( |
|||
ta: scalafx.scene.control.TextArea, |
|||
text: String |
|||
): Unit = |
|||
ta.appendText(text) |
|||
|
|||
} |
|||
|
|||
def textAreaStream(ta: TextArea) = |
|||
Resource.make( |
|||
Task( |
|||
new JFXConsoleStream( |
|||
outputStream = new ByteArrayOutputStream(), |
|||
control = ta |
|||
) |
|||
) |
|||
)(s => Task(s.close())) |
|||
|
|||
} |
@ -0,0 +1,130 @@ |
|||
package wow.doge.mygame.utils; |
|||
|
|||
import javafx.event.EventHandler; |
|||
import javafx.event.EventType; |
|||
import javafx.geometry.Insets; |
|||
import javafx.scene.Cursor; |
|||
import javafx.scene.Scene; |
|||
import javafx.scene.input.MouseEvent; |
|||
import javafx.stage.Stage; |
|||
|
|||
//created by Alexander Berg |
|||
public class ResizeHelper { |
|||
|
|||
public static ResizeListener addResizeListener(Stage stage) { |
|||
ResizeListener resizeListener = new ResizeListener(stage); |
|||
Scene scene = stage.getScene(); |
|||
scene.addEventHandler(MouseEvent.MOUSE_MOVED, resizeListener); |
|||
scene.addEventHandler(MouseEvent.MOUSE_PRESSED, resizeListener); |
|||
scene.addEventHandler(MouseEvent.MOUSE_DRAGGED, resizeListener); |
|||
scene.addEventHandler(MouseEvent.MOUSE_EXITED, resizeListener); |
|||
scene.addEventHandler(MouseEvent.MOUSE_EXITED_TARGET, resizeListener); |
|||
|
|||
return resizeListener; |
|||
} |
|||
|
|||
public static class ResizeListener implements EventHandler<MouseEvent> { |
|||
private Stage stage; |
|||
private Scene scene; |
|||
private Cursor cursorEvent = Cursor.DEFAULT; |
|||
private int border = 4; |
|||
private double startX = 0; |
|||
private double startY = 0; |
|||
private double sceneOffsetX = 0; |
|||
private double sceneOffsetY = 0; |
|||
private double padTop = 0; |
|||
private double padRight = 0; |
|||
private double padBottom = 0; |
|||
private double padLeft = 0; |
|||
|
|||
public ResizeListener(Stage stage) { |
|||
this.stage = stage; |
|||
this.scene = stage.getScene(); |
|||
} |
|||
|
|||
public void setPadding(Insets padding) { |
|||
padTop = padding.getTop(); |
|||
padRight = padding.getRight(); |
|||
padBottom = padding.getBottom(); |
|||
padLeft = padding.getLeft(); |
|||
} |
|||
|
|||
@Override |
|||
public void handle(MouseEvent mouseEvent) { |
|||
EventType<? extends MouseEvent> mouseEventType = mouseEvent.getEventType(); |
|||
|
|||
double mouseEventX = mouseEvent.getSceneX(), mouseEventY = mouseEvent.getSceneY(), |
|||
viewWidth = stage.getWidth() - padLeft - padRight, |
|||
viewHeight = stage.getHeight() - padTop - padBottom; |
|||
|
|||
if (MouseEvent.MOUSE_MOVED.equals(mouseEventType)) { |
|||
if (mouseEventX < border + padLeft && mouseEventY < border + padTop) { |
|||
cursorEvent = Cursor.NW_RESIZE; |
|||
} else if (mouseEventX < border + padLeft && mouseEventY > viewHeight - border + padTop) { |
|||
cursorEvent = Cursor.SW_RESIZE; |
|||
} else if (mouseEventX > viewWidth - border + padLeft && mouseEventY < border + padTop) { |
|||
cursorEvent = Cursor.NE_RESIZE; |
|||
} else if (mouseEventX > viewWidth - border + padLeft && mouseEventY > viewHeight - border + padTop) { |
|||
cursorEvent = Cursor.SE_RESIZE; |
|||
} else if (mouseEventX < border + padLeft) { |
|||
cursorEvent = Cursor.W_RESIZE; |
|||
} else if (mouseEventX > viewWidth - border + padLeft) { |
|||
cursorEvent = Cursor.E_RESIZE; |
|||
} else if (mouseEventY < border + padTop) { |
|||
cursorEvent = Cursor.N_RESIZE; |
|||
} else if (mouseEventY > viewHeight - border + padTop) { |
|||
cursorEvent = Cursor.S_RESIZE; |
|||
} else { |
|||
cursorEvent = Cursor.DEFAULT; |
|||
} |
|||
|
|||
scene.setCursor(cursorEvent); |
|||
} else if (MouseEvent.MOUSE_EXITED.equals(mouseEventType) |
|||
|| MouseEvent.MOUSE_EXITED_TARGET.equals(mouseEventType)) { |
|||
scene.setCursor(Cursor.DEFAULT); |
|||
} else if (MouseEvent.MOUSE_PRESSED.equals(mouseEventType)) { |
|||
startX = viewWidth - mouseEventX; |
|||
startY = viewHeight - mouseEventY; |
|||
sceneOffsetX = mouseEvent.getSceneX(); |
|||
sceneOffsetY = mouseEvent.getSceneY(); |
|||
} else if (MouseEvent.MOUSE_DRAGGED.equals(mouseEventType) && !Cursor.DEFAULT.equals(cursorEvent)) { |
|||
if (!Cursor.W_RESIZE.equals(cursorEvent) && !Cursor.E_RESIZE.equals(cursorEvent)) { |
|||
double minHeight = stage.getMinHeight() > (border * 2) ? stage.getMinHeight() : (border * 2); |
|||
|
|||
if (Cursor.NW_RESIZE.equals(cursorEvent) || Cursor.N_RESIZE.equals(cursorEvent) |
|||
|| Cursor.NE_RESIZE.equals(cursorEvent)) { |
|||
if (stage.getHeight() > minHeight || mouseEventY < 0) { |
|||
double height = stage.getY() - mouseEvent.getScreenY() + stage.getHeight() + sceneOffsetY; |
|||
double y = mouseEvent.getScreenY() - sceneOffsetY; |
|||
|
|||
stage.setHeight(height); |
|||
stage.setY(y); |
|||
} |
|||
} else { |
|||
if (stage.getHeight() > minHeight || mouseEventY + startY - stage.getHeight() > 0) { |
|||
stage.setHeight(mouseEventY + startY + padBottom + padTop); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (!Cursor.N_RESIZE.equals(cursorEvent) && !Cursor.S_RESIZE.equals(cursorEvent)) { |
|||
double minWidth = stage.getMinWidth() > (border * 2) ? stage.getMinWidth() : (border * 2); |
|||
if (Cursor.NW_RESIZE.equals(cursorEvent) || Cursor.W_RESIZE.equals(cursorEvent) |
|||
|| Cursor.SW_RESIZE.equals(cursorEvent)) { |
|||
if (stage.getWidth() > minWidth || mouseEventX < 0) { |
|||
double width = stage.getX() - mouseEvent.getScreenX() + stage.getWidth() + sceneOffsetX; |
|||
double x = mouseEvent.getScreenX() - sceneOffsetX; |
|||
|
|||
stage.setWidth(width); |
|||
stage.setX(x); |
|||
} |
|||
} else { |
|||
if (stage.getWidth() > minWidth || mouseEventX + startX - stage.getWidth() > 0) { |
|||
stage.setWidth(mouseEventX + startX + padLeft + padRight); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,24 @@ |
|||
package wow.doge.mygame.utils |
|||
|
|||
import monix.execution.atomic.AtomicAny |
|||
|
|||
/** |
|||
* Useless |
|||
*/ |
|||
sealed abstract class Tree[+T] |
|||
case class Node[T](data: T, children: AtomicAny[LazyList[Tree[T]]]) |
|||
extends Tree[T] { |
|||
def add(data: T) = { |
|||
children.transform(children => |
|||
Node(data, AtomicAny(LazyList[Tree[T]]())) #:: children |
|||
) |
|||
} |
|||
} |
|||
// case object Leaf extends Tree[Nothing] |
|||
case class Data(data: Int) |
|||
|
|||
class TreeManager[T] { |
|||
// val root: AtomicAny[Tree[T]] = AtomicAny(Leaf) |
|||
|
|||
def add(data: T, node: Node[T]) = {} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue