Compare commits
67 Commits
6b6ef67122
...
1.0.1
Author | SHA1 | Date | |
---|---|---|---|
b8ca5dc498
|
|||
dbdba120c3 | |||
33a46c4cbf
|
|||
d81aa56e49 | |||
95496536db | |||
8f3b61462a | |||
cff5ec76bf | |||
1bbfe800e1 | |||
c722a39116
|
|||
911983bff4
|
|||
6feb1c3dad | |||
7da58c7dbe | |||
86c05c0363
|
|||
a3c03c4bc7 | |||
9444e8198f | |||
730a0ab383 | |||
a10e2aceb6 | |||
f0fe4bb981 | |||
32883a2639 | |||
0e293768d7 | |||
6a5b2f555c | |||
8d210d756d | |||
8c6a43fc22
|
|||
7f4182bfad
|
|||
5fff4023f9
|
|||
dfad679e6e | |||
391dfe4282
|
|||
225316abb9 | |||
f5dbcc0134 | |||
cac4807357 | |||
33fa741a2a | |||
37406acd98 | |||
56c62422cc | |||
bc43b33536 | |||
1ac13f80d5 | |||
8dfbbae559 | |||
cc03b32ade | |||
a2f5b65e30 | |||
f094a68b04 | |||
b5545e1bae | |||
9a9a1e0056 | |||
0f23749001 | |||
c1dbd8ffb7 | |||
ebc6449e48 | |||
bef56f978c | |||
50ea54c8d6 | |||
24b9755089 | |||
6fbfa050b3 | |||
9a3524143a | |||
10076fcef2 | |||
6219ad93d0 | |||
8109782e4e | |||
c2d01760c7 | |||
2cac52b48d | |||
35f8145112 | |||
e26d54e96f | |||
7e3ce9ce56
|
|||
9975364621 | |||
491578806e | |||
b1052fa894
|
|||
36c4805061
|
|||
ee7fbae29c | |||
07f2682a2d
|
|||
efc28455c1 | |||
5d223ba72b
|
|||
15cbbb1bac | |||
08840c4c2b |
@ -27,7 +27,7 @@ compileTestKotlin {
|
||||
}
|
||||
|
||||
group 'org.hso'
|
||||
version '1.0-SNAPSHOT'
|
||||
version '1.0.1'
|
||||
archivesBaseName = 'TextureSync'
|
||||
mainClassName = 'org.hso.texturesyncclient.app.Main'
|
||||
|
||||
|
@ -2,25 +2,35 @@ package org.hso.texturesyncclient.app
|
||||
|
||||
import javafx.scene.image.Image
|
||||
import javafx.stage.Stage
|
||||
import org.hso.texturesyncclient.controller.SettingsController
|
||||
import org.hso.texturesyncclient.view.startupView.StartupView
|
||||
import org.hso.texturesyncclient.view.startupView.StartupViewController
|
||||
import tornadofx.App
|
||||
|
||||
class Main: App(StartupView::class){
|
||||
class Main : App(StartupView::class) {
|
||||
|
||||
//start first controller
|
||||
private val svc = StartupViewController()
|
||||
private val svc: StartupViewController by inject()
|
||||
|
||||
override fun start(stage: Stage) {
|
||||
|
||||
stage.minWidth = 1000.00
|
||||
stage.minHeight = 500.00
|
||||
stage.isResizable = false
|
||||
stage.icons.add(Image("icons/TextureSync_Icon_256x256.jpeg"))
|
||||
// Calling super.start early prevents a weird layouting bug
|
||||
// were the button of the window is white.
|
||||
// This could(?) be caused by stage and StartupView having
|
||||
// a different min-size.
|
||||
super.start(stage)
|
||||
|
||||
stage.minWidth = 1050.00
|
||||
stage.minHeight = 700.00
|
||||
stage.width = 1050.00
|
||||
stage.height = 700.00
|
||||
stage.isResizable = true
|
||||
stage.icons.add(Image("icons/TextureSync_Icon_256x256.png"))
|
||||
stage.setOnCloseRequest { System.exit(0) }
|
||||
|
||||
super.start(stage)
|
||||
stage.scene.stylesheets.add("/css/Styles.css") // this call must be after the super call
|
||||
stage.scene.stylesheets.add("/css/Styles.css")
|
||||
|
||||
SettingsController.init()
|
||||
svc.initConnection()
|
||||
}
|
||||
|
||||
}
|
@ -3,6 +3,7 @@ package org.hso.texturesyncclient.controller
|
||||
import javafx.application.Platform
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.event.EventHandler
|
||||
import javafx.scene.image.Image
|
||||
import javafx.stage.DirectoryChooser
|
||||
import org.hso.texturesyncclient.alerts.JFXInfoAlert
|
||||
import org.hso.texturesyncclient.alerts.JFXOkayCancelAlert
|
||||
@ -13,33 +14,27 @@ import org.hso.texturesyncclient.model.Sha256
|
||||
import org.hso.texturesyncclient.model.Texture
|
||||
import org.hso.texturesyncclient.model.TextureFormat
|
||||
import org.hso.texturesyncclient.view.importView.ImportView
|
||||
import org.hso.texturesyncclient.view.importView.ImportViewController
|
||||
import org.hso.texturesyncclient.view.mainView.MainView
|
||||
import org.hso.texturesyncclient.view.mainView.MainViewController
|
||||
import org.hso.texturesyncclient.view.startupView.StartupView
|
||||
import org.hso.texturesyncclient.view.startupView.StartupViewController
|
||||
import tornadofx.Controller
|
||||
import tornadofx.observable
|
||||
import java.net.InetAddress
|
||||
import java.util.Calendar
|
||||
import tornadofx.*
|
||||
import java.io.File
|
||||
import javax.imageio.ImageIO
|
||||
import java.util.UUID
|
||||
import java.nio.file.Files
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.net.InetAddress
|
||||
import java.nio.file.Files
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
class RootController : Controller() {
|
||||
|
||||
private val mvc: MainViewController by inject()
|
||||
private val svc: StartupViewController by inject()
|
||||
private val ivc: ImportViewController by inject()
|
||||
|
||||
private lateinit var con: Connection
|
||||
|
||||
private lateinit var selectedTexture: Texture
|
||||
|
||||
private lateinit var selectedTextureModel: GUIModel
|
||||
private var lastExportDir: String = System.getProperty("user.home")
|
||||
|
||||
/**
|
||||
@ -49,12 +44,12 @@ class RootController : Controller() {
|
||||
* @param tags all tags for the file
|
||||
*/
|
||||
fun importTexture(path: String, name: String, tags: ObservableList<String>) {
|
||||
var data = Files.readAllBytes(File(path).toPath()) // this is the image as byte array
|
||||
val data = Files.readAllBytes(File(path).toPath()) // this is the image as byte array
|
||||
|
||||
val uuid = UUID.randomUUID()
|
||||
val format = if (File(path).extension.toLowerCase() == "png") TextureFormat.PNG else TextureFormat.JPEG
|
||||
val bimg = ImageIO.read(File(path)) //image for obtaining resolution
|
||||
val resolution = Pair(bimg.height, bimg.width)
|
||||
val resolution = Pair(bimg.width, bimg.height)
|
||||
val cal = Calendar.getInstance() //calendar obj with current time
|
||||
val hash = Sha256(data)
|
||||
|
||||
@ -73,7 +68,6 @@ class RootController : Controller() {
|
||||
"-fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000;"
|
||||
)
|
||||
|
||||
data = null //Free image
|
||||
|
||||
val newTexture = Texture(uuid, name, tags.toTypedArray(), format, resolution, cal, hash)
|
||||
|
||||
@ -85,7 +79,9 @@ class RootController : Controller() {
|
||||
alertImportHash.showAndWait()
|
||||
} catch (e: Exception) {
|
||||
alertImport.showAndWait()
|
||||
println(e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,15 +98,17 @@ class RootController : Controller() {
|
||||
println("[auto] server found")
|
||||
con = foundServer
|
||||
con.ping()
|
||||
println("auto Connection to Server successful")
|
||||
println("[auto] Connection to Server successful")
|
||||
switchStartupToMain()
|
||||
showAll()
|
||||
|
||||
return // abort
|
||||
} else {
|
||||
println("[auto] no server found")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(e)
|
||||
println("auto Connection to Server NOT successful")
|
||||
println("[auto] Connection to Server NOT successful")
|
||||
}
|
||||
if (SettingsController.serverAddressIsSet()) {
|
||||
println("[file] try connect with settings file")
|
||||
@ -121,6 +119,8 @@ class RootController : Controller() {
|
||||
println("[file] Connection to Server successful")
|
||||
switchStartupToMain()
|
||||
showAll()
|
||||
|
||||
return // abort
|
||||
} catch (e: Exception) {
|
||||
println(e)
|
||||
println("[file] Connection to Server NOT successful")
|
||||
@ -139,9 +139,22 @@ class RootController : Controller() {
|
||||
switchStartupToMain()
|
||||
showAll()
|
||||
println("swithing to MainView @ initCon")
|
||||
|
||||
return // abort
|
||||
} catch (e: Exception) {
|
||||
println(e)
|
||||
println("Connection to Server NOT successful")
|
||||
|
||||
Platform.runLater {
|
||||
JFXInfoAlert(
|
||||
"Verbinden fehlgeschlagen",
|
||||
"Mögliche Ursachen:" +
|
||||
"\n- der angegebene Server ist offline" +
|
||||
"\n- die benötigten Ports sind nicht offen",
|
||||
"-fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000;"
|
||||
).showAndWait()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -167,26 +180,6 @@ class RootController : Controller() {
|
||||
return previewList
|
||||
}
|
||||
|
||||
// TODO this could be a companion object
|
||||
fun switchStartupToMain() {
|
||||
Platform.runLater {
|
||||
find(StartupView::class).replaceWith(MainView::class, sizeToScene = true, centerOnScreen = true)
|
||||
}
|
||||
}
|
||||
|
||||
// These runLater calls should be unnecessary
|
||||
fun switchMainToImport() {
|
||||
Platform.runLater {
|
||||
find(MainView::class).replaceWith(ImportView::class, sizeToScene = true, centerOnScreen = true)
|
||||
}
|
||||
}
|
||||
|
||||
fun switchImportToMain() {
|
||||
Platform.runLater {
|
||||
find(ImportView::class).replaceWith(MainView::class, sizeToScene = true, centerOnScreen = true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* save the texture file to a local directory
|
||||
* @param data the texture as meta element
|
||||
@ -194,7 +187,7 @@ class RootController : Controller() {
|
||||
fun exportTexture(data: Texture) {
|
||||
val directoryChooser = DirectoryChooser()
|
||||
directoryChooser.title = "Export Verzeichnis wählen"
|
||||
directoryChooser.initialDirectory = File(lastExportDir)
|
||||
directoryChooser.initialDirectory = if(File(lastExportDir).exists()) File(lastExportDir) else File(System.getProperty("user.home"))
|
||||
|
||||
|
||||
val alertExport = JFXInfoAlert(
|
||||
@ -241,23 +234,24 @@ class RootController : Controller() {
|
||||
sdf.format(data.addedOn.time)
|
||||
)
|
||||
mvc.setTags(data.tags.toList().observable())
|
||||
selectedTexture = data
|
||||
mvc.setVisibleMetaTags(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a texture from the FolderView and the server
|
||||
* @param data the texture as meta element
|
||||
*/
|
||||
fun deleteTexture(data: Texture) {
|
||||
fun deleteTexture() {
|
||||
val dialogDelete = JFXOkayCancelAlert(
|
||||
"Löschen",
|
||||
"Textur wirklich löschen?",
|
||||
"Textur ${selectedTextureModel.data.name} wirklich löschen?",
|
||||
"-fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000;"
|
||||
)
|
||||
dialogDelete.okayAction = EventHandler {
|
||||
mvc.removeTextureFromView(data)
|
||||
con.deleteTexture(data)
|
||||
con.deleteTexture(selectedTextureModel.data)
|
||||
mvc.removeTextureFromView(selectedTextureModel.data)
|
||||
// reset the DetailView
|
||||
mvc.setVisibleMetaTags(false)
|
||||
mvc.setPreview3DTexture(Image("icons/TextureSync_Icon_256x256.jpeg"))
|
||||
}
|
||||
dialogDelete.cancelAction = EventHandler {
|
||||
// Do nothing
|
||||
@ -265,28 +259,61 @@ class RootController : Controller() {
|
||||
dialogDelete.showAndWait()
|
||||
}
|
||||
|
||||
/**
|
||||
* send a changed texture to the server
|
||||
* @param chips the new tag list
|
||||
*/
|
||||
fun updateTexture(chips: ObservableList<String>) {
|
||||
val uuid = UUID.randomUUID()
|
||||
val newTexture = Texture(
|
||||
uuid,
|
||||
selectedTexture.name,
|
||||
chips.toTypedArray(),
|
||||
selectedTexture.format,
|
||||
selectedTexture.resolution,
|
||||
selectedTexture.addedOn,
|
||||
selectedTexture.textureHash
|
||||
fun updateTexture(name: String, tags: Array<String>) {
|
||||
val newTexture = selectedTextureModel.data.copy(
|
||||
tags = tags,
|
||||
name = name
|
||||
)
|
||||
con.updateTexture(selectedTexture, newTexture, con.getTextureFile(selectedTexture.textureHash))
|
||||
try {
|
||||
con.updateTexture(
|
||||
selectedTextureModel.data,
|
||||
newTexture,
|
||||
con.getTextureFile(selectedTextureModel.data.textureHash)
|
||||
)
|
||||
selectedTextureModel.data = newTexture
|
||||
} catch (e: Exception) {
|
||||
println(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* show all available textures at start
|
||||
*/
|
||||
fun showAll() {
|
||||
private fun showAll() {
|
||||
queryElements(mvc.getTags())
|
||||
}
|
||||
|
||||
/**
|
||||
* set the last selected texture-GUIModell
|
||||
* @param model the last selected element
|
||||
*/
|
||||
fun setSelectedTexture(model: GUIModel) {
|
||||
selectedTextureModel = model
|
||||
selectedTexture = model.data
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
var selectedTexture: Texture? = null
|
||||
|
||||
fun switchStartupToMain() {
|
||||
Platform.runLater {
|
||||
find(StartupView::class).replaceWith(MainView::class, ViewTransition.FadeThrough(0.01.seconds))
|
||||
}
|
||||
}
|
||||
|
||||
// These runLater calls should be unnecessary
|
||||
fun switchMainToImport() {
|
||||
Platform.runLater {
|
||||
find(MainView::class).replaceWith(ImportView::class, ViewTransition.FadeThrough(0.01.seconds))
|
||||
}
|
||||
}
|
||||
|
||||
fun switchImportToMain() {
|
||||
Platform.runLater {
|
||||
find(ImportView::class).replaceWith(MainView::class, ViewTransition.FadeThrough(0.01.seconds))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ class SettingsController {
|
||||
dirPath = if (osName.contains("Windows")) {
|
||||
"$userHome/Documents/TextureSync"
|
||||
} else {
|
||||
"$userHome/.TextureSync"
|
||||
"$userHome/.config/TextureSync"
|
||||
}
|
||||
|
||||
settingsFile = File("$dirPath/config.xml") //open Settings file
|
||||
|
@ -329,4 +329,4 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ internal data class InternalTexture(
|
||||
resolution = arrayOf(tex.resolution.first, tex.resolution.second),
|
||||
added_on = arrayOf(
|
||||
tex.addedOn.get(Calendar.YEAR), //
|
||||
tex.addedOn.get(Calendar.MONTH), //
|
||||
tex.addedOn.get(Calendar.MONTH) + 1, //
|
||||
tex.addedOn.get(Calendar.DAY_OF_MONTH)
|
||||
),
|
||||
texture_hash = tex.textureHash.toString()
|
||||
@ -57,4 +57,4 @@ internal data class InternalTexture(
|
||||
throw ConnectionInvalidJsonException()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ enum class TextureFormat {
|
||||
data class Texture(
|
||||
val id : UUID,
|
||||
val name : String,
|
||||
val tags : Array<String>,
|
||||
var tags : Array<String>,
|
||||
val format : TextureFormat,
|
||||
val resolution : Pair<Int, Int>,
|
||||
val addedOn : Calendar,
|
||||
|
@ -12,9 +12,11 @@ import javafx.scene.layout.BackgroundFill
|
||||
import javafx.scene.layout.CornerRadii
|
||||
import javafx.scene.layout.VBox
|
||||
import javafx.scene.paint.Paint
|
||||
import tornadofx.*
|
||||
import tornadofx.addClass
|
||||
import tornadofx.find
|
||||
import tornadofx.paddingTop
|
||||
|
||||
class GUIModel constructor(var data: Texture, img: Image) : VBox(){
|
||||
class GUIModel constructor(var data: Texture, img: Image) : VBox() {
|
||||
|
||||
private var image = ImageView()
|
||||
private var label = Label()
|
||||
@ -22,13 +24,13 @@ class GUIModel constructor(var data: Texture, img: Image) : VBox(){
|
||||
private var exportItem = MenuItem("exportiern")
|
||||
private var deleteItem = MenuItem("löschen")
|
||||
|
||||
private val gmc = find(GUIModelController::class)
|
||||
private val gmc = find(GUIModelController::class)
|
||||
|
||||
init {
|
||||
super.setPadding(Insets(5.0, 5.0, 5.0, 5.0))
|
||||
super.getChildren().addAll(image, label)
|
||||
super.setOnContextMenuRequested { p0 -> contextMenu.show(this@GUIModel, p0.screenX, p0.screenY) }
|
||||
super.setOnMouseClicked{
|
||||
super.setOnMouseClicked {
|
||||
if (gmc.isLastSelectedInitialized()) {
|
||||
gmc.lastSelected.background = Background.EMPTY
|
||||
this.background = Background(BackgroundFill(Paint.valueOf("#2b7bbb"), CornerRadii.EMPTY, Insets.EMPTY))
|
||||
@ -38,13 +40,22 @@ class GUIModel constructor(var data: Texture, img: Image) : VBox(){
|
||||
gmc.lastSelected = this
|
||||
}
|
||||
gmc.previewSelectedAction(data)
|
||||
gmc.setSelected(this)
|
||||
|
||||
}
|
||||
|
||||
label.addClass("metadata")
|
||||
label.paddingTop = 5.0
|
||||
label.prefWidth = 128.0
|
||||
label.alignment = Pos.CENTER
|
||||
label.text = data.name
|
||||
label.background = Background(BackgroundFill(Paint.valueOf("#FFFF2b"), CornerRadii.EMPTY, Insets.EMPTY))
|
||||
|
||||
label.text = if (data.name.length > 15) {
|
||||
"${data.name.subSequence(0, 14)}.."
|
||||
} else {
|
||||
data.name
|
||||
}
|
||||
|
||||
label.background = Background(BackgroundFill(Paint.valueOf("#3a3a3a"), CornerRadii.EMPTY, Insets.EMPTY))
|
||||
|
||||
image.fitHeight = 128.0
|
||||
image.fitWidth = 128.0
|
||||
@ -55,7 +66,7 @@ class GUIModel constructor(var data: Texture, img: Image) : VBox(){
|
||||
}
|
||||
|
||||
deleteItem.setOnAction {
|
||||
gmc.delete(data)
|
||||
gmc.delete()
|
||||
}
|
||||
|
||||
contextMenu.items.add(exportItem)
|
||||
|
@ -3,7 +3,7 @@ package org.hso.texturesyncclient.model
|
||||
import org.hso.texturesyncclient.controller.RootController
|
||||
import tornadofx.Controller
|
||||
|
||||
class GUIModelController: Controller() {
|
||||
class GUIModelController : Controller() {
|
||||
|
||||
private val rootc = find(RootController::class)
|
||||
|
||||
@ -14,11 +14,15 @@ class GUIModelController: Controller() {
|
||||
rootc.exportTexture(data)
|
||||
}
|
||||
|
||||
fun delete(data: Texture) {
|
||||
rootc.deleteTexture(data)
|
||||
fun delete() {
|
||||
rootc.deleteTexture()
|
||||
}
|
||||
|
||||
fun previewSelectedAction(data: Texture) {
|
||||
rootc.showDetail(data)
|
||||
}
|
||||
|
||||
fun setSelected(model: GUIModel) {
|
||||
rootc.setSelectedTexture(model)
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ import javafx.scene.layout.BackgroundFill
|
||||
import javafx.scene.layout.CornerRadii
|
||||
import javafx.scene.paint.Paint
|
||||
import javafx.scene.layout.Priority
|
||||
import org.hso.texturesyncclient.view.mainView.Preview3D
|
||||
import tornadofx.*
|
||||
|
||||
class ImportView : View("TextureSync") {
|
||||
@ -18,17 +19,21 @@ class ImportView : View("TextureSync") {
|
||||
val tfName = JFXTextField()
|
||||
val cvTags = JFXChipView<String>()
|
||||
val btnImport = JFXButton("Importieren")
|
||||
val btnBack = JFXButton("Zurück")
|
||||
|
||||
val preview = Preview3D()
|
||||
|
||||
private val btnBack = JFXButton("Zurück")
|
||||
|
||||
private val ivc: ImportViewController by inject()
|
||||
|
||||
init {
|
||||
btnImport.isVisible = false
|
||||
preview.root.isVisible = false
|
||||
}
|
||||
|
||||
override val root = borderpane {
|
||||
minWidth = 1000.0
|
||||
minHeight = 500.0
|
||||
prefWidth = FX.primaryStage.width
|
||||
prefHeight = FX.primaryStage.height
|
||||
background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY))
|
||||
|
||||
center = vbox(50) {
|
||||
@ -39,6 +44,8 @@ class ImportView : View("TextureSync") {
|
||||
style = "-fx-font: 20px Verdana; -fx-text-fill: #2b7bbb;"
|
||||
}
|
||||
|
||||
add(preview)
|
||||
|
||||
vbox(20) {
|
||||
hbox(10) {
|
||||
add(tfFilePath)
|
||||
|
@ -1,9 +1,11 @@
|
||||
package org.hso.texturesyncclient.view.importView
|
||||
|
||||
import javafx.scene.image.Image
|
||||
import javafx.stage.FileChooser
|
||||
import org.hso.texturesyncclient.controller.RootController
|
||||
import tornadofx.Controller
|
||||
import javafx.stage.FileChooser
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
|
||||
|
||||
class ImportViewController : Controller() {
|
||||
@ -29,15 +31,25 @@ class ImportViewController : Controller() {
|
||||
iv.tfFilePath.text = file.absolutePath
|
||||
iv.tfName.text = file.nameWithoutExtension
|
||||
lastImportDir = file.parent.toString() //store last user chosen dir
|
||||
|
||||
runAsync {
|
||||
try {
|
||||
val fileInput = FileInputStream(file.absolutePath)
|
||||
val img = Image(fileInput)
|
||||
iv.preview.setTexture(img)
|
||||
iv.preview.root.isVisible = true
|
||||
} catch (e: Exception) {
|
||||
// Got a catch'em all
|
||||
println(e.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun btnImportAction() {
|
||||
rootc.importTexture(iv.tfFilePath.text, iv.tfName.text, iv.cvTags.chips)
|
||||
rootc.switchImportToMain()
|
||||
iv.tfFilePath.clear()
|
||||
iv.tfName.clear()
|
||||
iv.cvTags.chips.clear()
|
||||
RootController.switchImportToMain()
|
||||
reset()
|
||||
}
|
||||
|
||||
fun validateImport() {
|
||||
@ -46,9 +58,14 @@ class ImportViewController : Controller() {
|
||||
}
|
||||
|
||||
fun btnBackAction() {
|
||||
rootc.switchImportToMain()
|
||||
RootController.switchImportToMain()
|
||||
reset()
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
iv.tfFilePath.clear()
|
||||
iv.tfName.clear()
|
||||
iv.cvTags.chips.clear()
|
||||
iv.preview.root.isVisible = false
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,9 @@ package org.hso.texturesyncclient.view.mainView
|
||||
|
||||
import com.jfoenix.controls.JFXButton
|
||||
import com.jfoenix.controls.JFXChipView
|
||||
import com.jfoenix.controls.JFXTextField
|
||||
import javafx.geometry.Insets
|
||||
import javafx.geometry.Orientation
|
||||
import javafx.geometry.Pos
|
||||
import javafx.scene.control.Label
|
||||
import javafx.scene.image.Image
|
||||
import javafx.scene.layout.Background
|
||||
import javafx.scene.layout.BackgroundFill
|
||||
@ -13,16 +12,35 @@ import javafx.scene.layout.CornerRadii
|
||||
import javafx.scene.paint.Paint
|
||||
import tornadofx.*
|
||||
|
||||
class DetailView: View() {
|
||||
class DetailView : View() {
|
||||
|
||||
val preview = Preview3D()
|
||||
val metaLabel = Label("Auflösung: 8MP\nName: Texture.png\nAndere: was anderes\nEinfügedatum: 31.02.2019")
|
||||
val cvTags = JFXChipView<String>()
|
||||
val btnImport = JFXButton("+")
|
||||
|
||||
init {
|
||||
// set a default texture
|
||||
preview.setTexture(Image("icons/TextureSync_Icon_256x256.jpeg"))
|
||||
val nameInfo = JFXTextField().addClass("metadata")
|
||||
val resolutionInfo = label().addClass("metadata")
|
||||
val formatInfo = label().addClass("metadata")
|
||||
val dateInfo = label().addClass("metadata")
|
||||
|
||||
val btnSubmit = JFXButton("Ändern").addClass("btn-blue")
|
||||
|
||||
val metadataPanel = gridpane {
|
||||
row {
|
||||
label("Name ").addClass("metadata")
|
||||
add(nameInfo)
|
||||
}
|
||||
row {
|
||||
label("Auflösung ").addClass("metadata")
|
||||
add(resolutionInfo)
|
||||
}
|
||||
row {
|
||||
label("Format ").addClass("metadata")
|
||||
add(formatInfo)
|
||||
}
|
||||
row {
|
||||
label("Einfügedatum ").addClass("metadata")
|
||||
add(dateInfo)
|
||||
}
|
||||
}
|
||||
|
||||
override val root = form {
|
||||
@ -31,42 +49,32 @@ class DetailView: View() {
|
||||
|
||||
fieldset(labelPosition = Orientation.VERTICAL) {
|
||||
|
||||
field{
|
||||
field {
|
||||
vbox(7) {
|
||||
add(preview)
|
||||
}
|
||||
}
|
||||
|
||||
field {
|
||||
paddingTop = 2
|
||||
paddingBottom = 3
|
||||
add(metaLabel)
|
||||
add(metadataPanel)
|
||||
}
|
||||
|
||||
field {
|
||||
minHeight = 155.0
|
||||
add(cvTags)
|
||||
|
||||
}
|
||||
|
||||
field {
|
||||
hbox(alignment = Pos.CENTER_RIGHT) {
|
||||
add(btnImport)
|
||||
}
|
||||
add(btnSubmit)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
style {
|
||||
metaLabel.style = "-fx-text-fill: #2b7bbb;"
|
||||
|
||||
cvTags.minHeight = 145.0
|
||||
cvTags.paddingAll = 3.0
|
||||
cvTags.style = "-fx-background-color: #53585b; -fx-text-inner-color: #b15b2e;"
|
||||
|
||||
btnImport.buttonType = JFXButton.ButtonType.RAISED
|
||||
btnImport.styleClass.add("jfx-floating-action-button")
|
||||
}
|
||||
init {
|
||||
// set a default texture
|
||||
preview.setTexture(Image("icons/TextureSync_Icon_256x256.jpeg"))
|
||||
btnSubmit.useMaxWidth = true
|
||||
|
||||
}
|
||||
}
|
@ -13,12 +13,7 @@ class FolderView : View("FolderView"){
|
||||
hgap = 5.0
|
||||
vgap = 5.0
|
||||
paddingAll = 10.0
|
||||
prefWidth = 732.0
|
||||
prefHeight = 401.0
|
||||
background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY))
|
||||
|
||||
style {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package org.hso.texturesyncclient.view.mainView
|
||||
|
||||
import com.jfoenix.controls.JFXButton
|
||||
import com.jfoenix.controls.JFXChipView
|
||||
import javafx.geometry.Insets
|
||||
import javafx.scene.control.ScrollPane
|
||||
|
||||
import javafx.scene.layout.Background
|
||||
import javafx.scene.layout.BackgroundFill
|
||||
@ -13,51 +13,53 @@ import tornadofx.*
|
||||
class MainView : View("TextureSync") {
|
||||
|
||||
val cvSearch = JFXChipView<String>()
|
||||
private val btnImport = JFXButton("+")
|
||||
val folderView = find(FolderView::class)
|
||||
val detailView = find(DetailView::class)
|
||||
|
||||
private val mvc: MainViewController by inject()
|
||||
|
||||
override val root = borderpane {
|
||||
override val root = anchorpane {
|
||||
|
||||
background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY))
|
||||
minWidth = 1000.0
|
||||
maxWidth = 1000.0
|
||||
minHeight = 500.0
|
||||
maxHeight = 500.0
|
||||
prefWidth = FX.primaryStage.width
|
||||
prefHeight = FX.primaryStage.height
|
||||
|
||||
left = vbox {
|
||||
//background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY))
|
||||
anchorpane{
|
||||
this.fitToParentWidth()
|
||||
paddingAll = 5.0
|
||||
borderpane {
|
||||
right = detailView.root
|
||||
center = vbox {
|
||||
add(cvSearch)
|
||||
}
|
||||
anchorpane {
|
||||
scrollpane {
|
||||
this.fitToParentSize()
|
||||
this.vbarPolicy = ScrollPane.ScrollBarPolicy.ALWAYS
|
||||
add(folderView.root)
|
||||
|
||||
style = "-fx-background-color:transparent;"
|
||||
isFitToWidth = true
|
||||
isFitToHeight = true
|
||||
|
||||
add(folderView.root)
|
||||
}
|
||||
}
|
||||
|
||||
anchorpaneConstraints {
|
||||
topAnchor = 0
|
||||
bottomAnchor = 0
|
||||
rightAnchor = 0
|
||||
leftAnchor = 0
|
||||
}
|
||||
}
|
||||
|
||||
right = detailView.root
|
||||
add(btnImport)
|
||||
|
||||
style {
|
||||
cvSearch.promptText = "Suche"
|
||||
cvSearch.paddingAll = 5.0
|
||||
cvSearch.minHeight = 70.0
|
||||
cvSearch.minHeight = 65.0
|
||||
cvSearch.style = "-fx-background-color: #53585b; -fx-text-inner-color: #b15b2e;"
|
||||
cvSearch.anchorpaneConstraints {
|
||||
topAnchor = 3
|
||||
bottomAnchor = 3
|
||||
leftAnchor = 3
|
||||
rightAnchor = -5
|
||||
}
|
||||
|
||||
btnImport.buttonType = JFXButton.ButtonType.RAISED
|
||||
btnImport.styleClass.add("jfx-floating-action-button")
|
||||
btnImport.anchorpaneConstraints {
|
||||
bottomAnchor = 5
|
||||
rightAnchor = 5
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
@ -65,14 +67,33 @@ class MainView : View("TextureSync") {
|
||||
mvc.cvSearchAction(cvSearch.chips)
|
||||
}
|
||||
|
||||
detailView.cvTags.chips.onChange {
|
||||
mvc.updateTags()
|
||||
}
|
||||
|
||||
detailView.btnImport.setOnAction {
|
||||
btnImport.setOnAction {
|
||||
mvc.btnImportAction()
|
||||
}
|
||||
|
||||
// TODO: on chipview update on name update
|
||||
|
||||
detailView.cvTags.chips.onChange {
|
||||
detailView.btnSubmit.isVisible = true
|
||||
}
|
||||
|
||||
detailView.nameInfo.textProperty().onChange {
|
||||
detailView.btnSubmit.isVisible = true
|
||||
}
|
||||
|
||||
detailView.btnSubmit.setOnAction {
|
||||
mvc.updateTags()
|
||||
detailView.btnSubmit.isVisible = false
|
||||
}
|
||||
|
||||
//keyboard actions
|
||||
shortcut("Ctrl+I") {
|
||||
mvc.btnImportAction()
|
||||
}
|
||||
|
||||
shortcut("Ctrl+E") {
|
||||
mvc.scExport()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -2,10 +2,10 @@ package org.hso.texturesyncclient.view.mainView
|
||||
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.scene.image.Image
|
||||
import org.hso.texturesyncclient.model.GUIModel
|
||||
import tornadofx.Controller
|
||||
import org.hso.texturesyncclient.controller.RootController
|
||||
import org.hso.texturesyncclient.model.GUIModel
|
||||
import org.hso.texturesyncclient.model.Texture
|
||||
import tornadofx.Controller
|
||||
|
||||
class MainViewController : Controller() {
|
||||
|
||||
@ -17,7 +17,6 @@ class MainViewController : Controller() {
|
||||
|
||||
// DetailView elements
|
||||
private val preview = mv.detailView.preview
|
||||
private val metaLabel = mv.detailView.metaLabel
|
||||
private val cvTags = mv.detailView.cvTags
|
||||
private var lockUpdate: Boolean = false //lock update func when the system changes the detailview chipview
|
||||
|
||||
@ -32,7 +31,12 @@ class MainViewController : Controller() {
|
||||
}
|
||||
|
||||
fun setMeta(name: String, res: String, format: String, date: String) {
|
||||
metaLabel.text = "Name: $name\nAuflösung: $res\nFormat: $format\nEinfügedatum: $date"
|
||||
with(mv.detailView) {
|
||||
nameInfo.text = name
|
||||
formatInfo.text = format
|
||||
resolutionInfo.text = res
|
||||
dateInfo.text = date
|
||||
}
|
||||
}
|
||||
|
||||
fun setTags(chips: ObservableList<String>) {
|
||||
@ -42,24 +46,28 @@ class MainViewController : Controller() {
|
||||
lockUpdate = true //allow update with onChange
|
||||
}
|
||||
|
||||
fun getTags(): ObservableList<String>{
|
||||
fun getTags(): ObservableList<String> {
|
||||
return cvTags.chips
|
||||
}
|
||||
|
||||
fun updateTags() {
|
||||
if (lockUpdate) { //the chipView was changed by the user
|
||||
println("Tags changed")
|
||||
rootc.updateTexture(cvTags.chips)
|
||||
rootc.updateTexture(
|
||||
tags = cvTags.chips.toTypedArray(),
|
||||
name = mv.detailView.nameInfo.text
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// DetailView actions
|
||||
// MainView actions
|
||||
|
||||
fun cvSearchAction(tags: ObservableList<String>) {
|
||||
// show spinner, block ui
|
||||
folderView.children.clear()
|
||||
mv.cvSearch.isDisable = true
|
||||
setPreview3DTexture(Image("icons/TextureSync_Icon_256x256.jpeg")) // reset the 3DPreview to the logo
|
||||
RootController.selectedTexture = null
|
||||
|
||||
runAsync {
|
||||
rootc.queryElements(tags)
|
||||
@ -70,7 +78,7 @@ class MainViewController : Controller() {
|
||||
}
|
||||
|
||||
fun btnImportAction() {
|
||||
rootc.switchMainToImport()
|
||||
RootController.switchMainToImport()
|
||||
}
|
||||
|
||||
fun removeTextureFromView(data: Texture) {
|
||||
@ -79,14 +87,20 @@ class MainViewController : Controller() {
|
||||
.ifPresent { x -> folderView.children.remove(x) }
|
||||
}
|
||||
|
||||
fun setVisibleMetaTags(bool: Boolean){
|
||||
if(bool){
|
||||
metaLabel.isVisible = true
|
||||
fun setVisibleMetaTags(bool: Boolean) {
|
||||
if (bool) {
|
||||
mv.detailView.metadataPanel.isVisible = true
|
||||
mv.detailView.btnSubmit.isVisible = false
|
||||
cvTags.isVisible = true
|
||||
}else{
|
||||
metaLabel.isVisible = false
|
||||
} else {
|
||||
mv.detailView.metadataPanel.isVisible = false
|
||||
mv.detailView.btnSubmit.isVisible = false
|
||||
cvTags.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
fun scExport() {
|
||||
RootController.selectedTexture?.let { rootc.exportTexture(RootController.selectedTexture!!) }
|
||||
}
|
||||
|
||||
}
|
@ -36,7 +36,6 @@ class Preview3D : View("Preview3D") {
|
||||
pointLightFront.rotate = 90.0
|
||||
}
|
||||
|
||||
|
||||
override val root = stackpane {
|
||||
|
||||
add(dBox).apply {
|
||||
|
@ -22,6 +22,7 @@ class StartupView : View("TextureSync") {
|
||||
|
||||
private val svc: StartupViewController by inject()
|
||||
|
||||
|
||||
override val root = borderpane {
|
||||
minWidth = 1000.0
|
||||
minHeight = 500.0
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.hso.texturesyncclient.view.startupView
|
||||
|
||||
import org.hso.texturesyncclient.controller.RootController
|
||||
import org.hso.texturesyncclient.controller.SettingsController
|
||||
import tornadofx.Controller
|
||||
|
||||
|
||||
@ -10,9 +9,8 @@ class StartupViewController : Controller() {
|
||||
private val sv = find(StartupView::class)
|
||||
private val rootc = find(RootController::class)
|
||||
|
||||
init {
|
||||
fun initConnection() {
|
||||
println("init StartupViewController")
|
||||
SettingsController.init()
|
||||
startConnectionUI()
|
||||
runAsync {
|
||||
rootc.initConnection(" ")
|
||||
|
@ -88,7 +88,9 @@
|
||||
-fx-min-height: -fx-pref-height;
|
||||
-fx-max-height: -fx-pref-height;
|
||||
-jfx-button-type: RAISED;
|
||||
-fx-font-size: 25px
|
||||
|
||||
-fx-text-inner-color: #2b2b2b;
|
||||
-fx-font-size: 20px;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -107,3 +109,37 @@
|
||||
-fx-alignment: center-left;
|
||||
-fx-spacing: 8;
|
||||
}
|
||||
|
||||
.jfx-chip-view {
|
||||
-fx-text-inner-color: #E0E0E0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Buttons *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
.btn-blue {
|
||||
-fx-button-type: RAISED;
|
||||
-fx-background-color: #3c3f41;
|
||||
-fx-text-fill: #2b7bbb;
|
||||
-fx-padding: 10;
|
||||
}
|
||||
|
||||
.btn-orange {
|
||||
-fx-button-type: RAISED;
|
||||
-fx-background-color: #b15b2e;
|
||||
-fx-text-fill: #3c3f41;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* DetailView *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
.metadata {
|
||||
-fx-font: 14px Verdana;
|
||||
-fx-text-fill: #E0E0E0;
|
||||
}
|
1
client/src/main/resources/icons/TextureSync_Icon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="640" height="640" xmlns="http://www.w3.org/2000/svg"><defs><radialGradient id="a" cx="0.2" cy="-0.5" r="1.7"><stop offset="40%" stop-color="#8c8c8c"/><stop offset="100%" stop-color="#4c4c4c"/></radialGradient><radialGradient id="b" cx="0.2" cy="0.2" fx="0.34" fy="0.32" r="0.9"><stop offset="0%" stop-color="#fbf6f0"/><stop offset="50%" stop-color="#eadec4"/><stop offset="100%" stop-color="#aba390"/></radialGradient><radialGradient id="c" cx="0.2" cy="0.2" fx="0.34" fy="0.32" r="0.9"><stop offset="5%" stop-color="#fbf1cd"/><stop offset="50%" stop-color="#ffba00"/><stop offset="100%" stop-color="#bc8602"/></radialGradient></defs><path d="M158.58 102.89C144.48 110.79 143.14 130.93 155.49 141.35C169.62 153.27 184.17 164.75 199.13 175.69C138.27 240.95 105.0 337.14 105.0 426.0C105.0 525.49 179.5 590.92 278.99 591.0C342.5 591.05 406.69 553.62 449.59 506.78C501.0 450.65 531.88 370.14 532.0 294.02C532.06 254.61 524.06 213.61 505.46 178.86C487.92 146.11 450.51 118.09 413.38 117.01C388.12 116.27 362.24 125.41 340.98 139.06C331.11 145.4 321.78 152.65 313.04 160.6C313.88 131.47 312.82 102.25 309.97 73.31C308.35 56.96 293.5 46.31 277.86 51.34C236.62 64.58 196.37 81.72 158.58 102.89Z" fill="#000"/><path d="M165.42 115.11C158.26 119.12 158.24 125.36 164.51 130.65C201.33 161.71 241.11 189.73 283.36 212.86C290.09 216.54 295.26 213.92 296.04 206.29C300.48 162.65 300.34 118.34 296.03 74.69C295.17 65.95 290.5 61.98 282.14 64.66C241.79 77.63 202.4 94.39 165.42 115.11Z" fill="url(#a)"/><path d="M220.6 190.82C238.75 203.14 257.44 214.63 276.64 225.14C282.11 228.13 288.25 228.46 293.76 226.78L496.27 366.27C484.19 411.93 461.33 455.47 430.41 489.22C397.54 525.11 350.51 555.58 301.99 563.18L136.05 367.03C147.1 301.77 176.06 237.27 220.6 190.82Z" fill="url(#b)"/><path d="M293.76 226.78C302.1 224.23 309.01 217.1 309.96 207.71C310.21 205.29 310.44 202.86 310.66 200.43C323.57 185.24 338.43 171.6 355.02 160.94C371.91 150.09 392.56 142.41 412.62 142.99C440.73 143.82 469.27 166.35 482.54 191.14C499.13 222.12 506.06 258.84 506.0 293.98C505.96 317.93 502.59 342.39 496.27 366.27L330.0 369.0L301.99 563.18C294.35 564.38 286.68 565.01 279.01 565.0C192.51 564.93 131.0 512.5 131.0 426.0C131.0 406.59 132.7 386.78 136.05 367.03L290.0 332.0L293.76 226.78Z" fill="url(#c)"/></svg>
|
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 11 KiB |
BIN
client/src/main/resources/icons/TextureSync_Icon_256x256.png
Normal file
After Width: | Height: | Size: 17 KiB |
15
doc/kurzanleitungen/client/inhalt.txt
Normal file
@ -0,0 +1,15 @@
|
||||
- herunterladen (Release Gitea)
|
||||
- installiern (Java VM)
|
||||
- starten
|
||||
- connecten
|
||||
- neue textur einfügen
|
||||
- query mit Tags
|
||||
- query mit Name
|
||||
- query mit Auflösung
|
||||
- query mit Datum
|
||||
- query mit Kombination
|
||||
- exportieren
|
||||
- ändern
|
||||
- löschen
|
||||
- settings file löschen
|
||||
|
7
doc/kurzanleitungen/server/inhalt.txt
Normal file
@ -0,0 +1,7 @@
|
||||
- herunterladen (Release Gitea)
|
||||
- installiern (service daemon)
|
||||
- starten
|
||||
- loggen
|
||||
- stoppen
|
||||
- backups machen
|
||||
- backups wieder einspielen
|
39525
doc/praesentation/TextureSync.fodp
Normal file
BIN
doc/praesentation/TextureSync.pdf
Normal file
4
doc/praesentation/vorgaben.txt
Normal file
@ -0,0 +1,4 @@
|
||||
- kleine Präsentation über Projekt
|
||||
- Idee (Problem der Verwaltung vieler Texturen)
|
||||
- Ziele (einfach, lokale Daten, gemeinschafftlicher Zugriff)
|
||||
- Gelerntes (gute Planung, Tests, Versionsverwaltung, Issue-Tracker)
|
@ -4,9 +4,9 @@
|
||||
<phases/>
|
||||
<calendars>
|
||||
<day-types>
|
||||
<day-type id="0" name="Working" description="A default working day"/>
|
||||
<day-type id="1" name="Nonworking" description="A default non working day"/>
|
||||
<day-type id="2" name="Use base" description="Use day from base calendar"/>
|
||||
<day-type id="0" name="Arbeiten" description="Ein Vorgabe-Arbeitstag"/>
|
||||
<day-type id="1" name="Nicht Arbeiten" description="Ein Vorgabetag, an dem nicht gearbeitet wird"/>
|
||||
<day-type id="2" name="Basis verwenden" description="Tag vom Basiskalender verwenden"/>
|
||||
</day-types>
|
||||
<calendar id="1" name="Vorgabe">
|
||||
<default-week mon="1" tue="0" wed="0" thu="1" fri="1" sat="0" sun="1"/>
|
||||
@ -16,7 +16,9 @@
|
||||
<interval start="1300" end="1700"/>
|
||||
</overridden-day-type>
|
||||
</overridden-day-types>
|
||||
<days/>
|
||||
<days>
|
||||
<day date="20190613" type="day-type" id="0"/>
|
||||
</days>
|
||||
</calendar>
|
||||
</calendars>
|
||||
<tasks>
|
||||
@ -92,88 +94,82 @@
|
||||
<predecessor id="1" predecessor-id="10" type="FS"/>
|
||||
</predecessors>
|
||||
</task>
|
||||
<task id="19" name="Realisation" note="" work="1065600" start="20190423T000000Z" end="20190511T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="19" name="Realisation" note="" work="1641600" start="20190416T133640Z" end="20190612T170000Z" work-start="20190416T133640Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="18" type="FS"/>
|
||||
</predecessors>
|
||||
<task id="20" name="Einrichtung von Tests" note="" work="28800" start="20190423T000000Z" end="20190423T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="20" name="Einrichtung von Tests" note="" work="28800" start="20190416T133640Z" end="20190417T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="11" type="FS"/>
|
||||
</predecessors>
|
||||
<task id="21" name="Client Tests" note="" work="28800" start="20190423T000000Z" end="20190423T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
</task>
|
||||
<task id="21" name="Client" note="" work="1123200" start="20190416T133640Z" end="20190612T170000Z" work-start="20190416T133640Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="11" type="FS"/>
|
||||
</predecessors>
|
||||
<task id="22" name="UI" note="" work="288000" start="20190416T133640Z" end="20190423T133640Z" work-start="20190416T133640Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="23" name="Previews" note="" work="86400" start="20190416T133640Z" end="20190423T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"/>
|
||||
<task id="24" name="Filter UI" note="" work="86400" start="20190416T133640Z" end="20190423T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"/>
|
||||
<task id="25" name="3D Visualisierung" note="" work="57600" start="20190416T133640Z" end="20190420T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"/>
|
||||
<task id="26" name="Dateien hinzufügen" note="" work="28800" start="20190416T133640Z" end="20190417T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"/>
|
||||
<task id="27" name="Dateien lokal abspeichern" note="" work="28800" start="20190416T133640Z" end="20190417T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"/>
|
||||
</task>
|
||||
<task id="28" name="Grund Architektur" note="" work="662400" start="20190423T000000Z" end="20190612T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<constraint type="start-no-earlier-than" time="20190423T000000Z"/>
|
||||
</task>
|
||||
<task id="29" name="Protokoll implementieren" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<constraint type="start-no-earlier-than" time="20190423T000000Z"/>
|
||||
</task>
|
||||
</task>
|
||||
<task id="22" name="Client" note="" work="547200" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="30" name="Server" note="" work="489600" start="20190423T000000Z" end="20190511T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="11" type="FS"/>
|
||||
</predecessors>
|
||||
<task id="23" name="UI" note="" work="288000" start="20190423T170000Z" end="20190430T170000Z" work-start="20190424T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="21" type="FS"/>
|
||||
</predecessors>
|
||||
<task id="24" name="Previews" note="" work="86400" start="20190423T170000Z" end="20190430T170000Z" work-start="20190424T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"/>
|
||||
<task id="25" name="Filter UI" note="" work="86400" start="20190423T170000Z" end="20190430T170000Z" work-start="20190424T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"/>
|
||||
<task id="26" name="3D Visualisierung" note="" work="57600" start="20190423T170000Z" end="20190427T170000Z" work-start="20190424T080000Z" percent-complete="50" priority="0" type="normal" scheduling="fixed-work"/>
|
||||
<task id="27" name="Dateien hinzufügen" note="" work="28800" start="20190423T170000Z" end="20190424T170000Z" work-start="20190424T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"/>
|
||||
<task id="28" name="Dateien lokal abspeichern" note="" work="28800" start="20190423T170000Z" end="20190424T170000Z" work-start="20190424T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"/>
|
||||
</task>
|
||||
<task id="29" name="Grund Architektur" note="" work="86400" start="20190423T000000Z" end="20190427T170000Z" work-start="20190423T080000Z" percent-complete="70" priority="0" type="normal" scheduling="fixed-work">
|
||||
<constraint type="start-no-earlier-than" time="20190423T000000Z"/>
|
||||
</task>
|
||||
<task id="30" name="Protokoll implementieren" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<constraint type="start-no-earlier-than" time="20190423T000000Z"/>
|
||||
</task>
|
||||
</task>
|
||||
<task id="31" name="Server" note="" work="489600" start="20190423T000000Z" end="20190511T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="11" type="FS"/>
|
||||
</predecessors>
|
||||
<task id="32" name="Dateien speichern/verwalten" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="31" name="Dateien speichern/verwalten" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<constraint type="must-start-on" time="20190423T000000Z"/>
|
||||
</task>
|
||||
<task id="33" name="Protokoll implementieren" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="32" name="Protokoll implementieren" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<constraint type="must-start-on" time="20190423T000000Z"/>
|
||||
</task>
|
||||
<task id="34" name="Suche implementieren" note="" work="86400" start="20190504T170000Z" end="20190511T170000Z" work-start="20190507T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="33" name="Suche implementieren" note="" work="86400" start="20190504T170000Z" end="20190511T170000Z" work-start="20190507T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="32" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="31" type="FS"/>
|
||||
</predecessors>
|
||||
</task>
|
||||
<task id="35" name="Hauptlogik implementieren" note="Hauptsächlich Glue-Code " work="57600" start="20190504T170000Z" end="20190508T170000Z" work-start="20190507T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="34" name="Hauptlogik implementieren" note="Hauptsächlich Glue-Code " work="57600" start="20190504T170000Z" end="20190508T170000Z" work-start="20190507T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="33" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="32" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="31" type="FS"/>
|
||||
</predecessors>
|
||||
</task>
|
||||
</task>
|
||||
</task>
|
||||
<task id="36" name="End of Implementation" note="" work="0" start="20190511T170000Z" end="20190511T170000Z" work-start="20190511T170000Z" percent-complete="0" priority="0" type="milestone" scheduling="fixed-work">
|
||||
<task id="35" name="End of Implementation" note="" work="0" start="20190612T170000Z" end="20190612T170000Z" work-start="20190612T170000Z" percent-complete="0" priority="0" type="milestone" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="31" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="22" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="30" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="21" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="20" type="FS"/>
|
||||
</predecessors>
|
||||
</task>
|
||||
<task id="37" name="Abnahme" note="" work="374400" start="20190511T170000Z" end="20190611T170000Z" work-start="20190514T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="38" name="Modultests [M]" note="" work="115200" start="20190511T170000Z" end="20190521T170000Z" work-start="20190514T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="36" name="Abnahme" note="" work="115200" start="20190612T170000Z" end="20190613T170000Z" work-start="20190613T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="37" name="Modultests [M]" note="" work="28800" start="20190612T170000Z" end="20190613T170000Z" work-start="20190613T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="36" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="35" type="FS"/>
|
||||
</predecessors>
|
||||
</task>
|
||||
<task id="39" name="Integrationstests [M]" note="" work="115200" start="20190521T170000Z" end="20190529T170000Z" work-start="20190522T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="38" name="Integrationstests [M]" note="" work="28800" start="20190612T170000Z" end="20190613T170000Z" work-start="20190613T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="38" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="35" type="FS"/>
|
||||
</predecessors>
|
||||
</task>
|
||||
<task id="40" name="Systemtests [M]" note="" work="115200" start="20190529T170000Z" end="20190608T170000Z" work-start="20190601T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="39" name="Systemtests [M]" note="" work="28800" start="20190612T170000Z" end="20190613T170000Z" work-start="20190613T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="39" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="35" type="FS"/>
|
||||
</predecessors>
|
||||
</task>
|
||||
<task id="41" name="Akzeptanztest [M]" note="" work="28800" start="20190608T170000Z" end="20190611T170000Z" work-start="20190611T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<task id="40" name="Akzeptanztest [M]" note="" work="28800" start="20190612T170000Z" end="20190613T170000Z" work-start="20190613T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
|
||||
<predecessors>
|
||||
<predecessor id="1" predecessor-id="40" type="FS"/>
|
||||
<predecessor id="1" predecessor-id="35" type="FS"/>
|
||||
</predecessors>
|
||||
</task>
|
||||
</task>
|
||||
@ -186,16 +182,17 @@
|
||||
<resource id="4" name="Lukas" short-name="L" type="1" units="0" email="" note="" std-rate="0"/>
|
||||
</resources>
|
||||
<allocations>
|
||||
<allocation task-id="33" resource-id="1" units="100"/>
|
||||
<allocation task-id="29" resource-id="1" units="100"/>
|
||||
<allocation task-id="32" resource-id="1" units="100"/>
|
||||
<allocation task-id="8" resource-id="1" units="100"/>
|
||||
<allocation task-id="13" resource-id="1" units="100"/>
|
||||
<allocation task-id="11" resource-id="1" units="100"/>
|
||||
<allocation task-id="5" resource-id="1" units="50"/>
|
||||
<allocation task-id="29" resource-id="2" units="50"/>
|
||||
<allocation task-id="28" resource-id="2" units="50"/>
|
||||
<allocation task-id="8" resource-id="2" units="10"/>
|
||||
<allocation task-id="17" resource-id="2" units="100"/>
|
||||
<allocation task-id="5" resource-id="2" units="50"/>
|
||||
<allocation task-id="29" resource-id="3" units="50"/>
|
||||
<allocation task-id="28" resource-id="3" units="50"/>
|
||||
<allocation task-id="15" resource-id="3" units="100"/>
|
||||
<allocation task-id="12" resource-id="3" units="100"/>
|
||||
<allocation task-id="10" resource-id="3" units="100"/>
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "texture-sync-server"
|
||||
version = "0.1.0"
|
||||
version = "1.0.1"
|
||||
authors = ["CodeSteak <codesteak@shellf.art>"]
|
||||
edition = "2018"
|
||||
|
||||
@ -10,4 +10,4 @@ serde = { version = "1.0.90", features = ["derive"] }
|
||||
serde_json = "1.0.39"
|
||||
sha2 = "0.8.0"
|
||||
lovecraft = "0.2.0"
|
||||
num_cpus = "1.0"
|
||||
num_cpus = "1.0"
|
||||
|
@ -24,6 +24,8 @@ use std::path::*;
|
||||
fn main() -> std::io::Result<()> {
|
||||
lovecraft::invoke();
|
||||
|
||||
println!("\n\n\t=== TextureSync Server {} ===\t\n\n\n", env!("CARGO_PKG_VERSION"));
|
||||
|
||||
let data_path = Path::new("./data");
|
||||
println!("loading files from {:?}", data_path);
|
||||
let server_state = ServerState::new(data_path)?;
|
||||
|
@ -66,7 +66,7 @@ impl QueryFilter {
|
||||
|
||||
SpecialInName(name) => Score::RequiredMatch(
|
||||
//
|
||||
texture.name.contains(name),
|
||||
texture.name.to_lowercase().contains(&name.to_lowercase()),
|
||||
),
|
||||
|
||||
SpecialBeforeDate(date) => Score::RequiredMatch(texture.added_on <= *date),
|
||||
|