Commit vor dem Einfügen von Gebierge über Voxels
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 205 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 223 KiB After Width: | Height: | Size: 223 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 272 KiB After Width: | Height: | Size: 272 KiB |
|
Before Width: | Height: | Size: 262 KiB After Width: | Height: | Size: 262 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 205 KiB |
|
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 205 KiB |
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 209 KiB |
|
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 205 KiB |
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 172 KiB |
|
Before Width: | Height: | Size: 506 KiB After Width: | Height: | Size: 506 KiB |
|
Before Width: | Height: | Size: 695 KiB After Width: | Height: | Size: 695 KiB |
|
Before Width: | Height: | Size: 535 KiB After Width: | Height: | Size: 535 KiB |
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 213 KiB |
|
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 211 KiB |
|
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 278 KiB |
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 207 KiB After Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 277 KiB After Width: | Height: | Size: 277 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
BIN
blight-assets/src/main/resources/Models/manatrank.j3o
Normal file
20
blight-assets/src/main/resources/Models/manatrank.j3o.meta
Normal file
@@ -0,0 +1,20 @@
|
||||
#Tue Jun 09 21:42:20 CEST 2026
|
||||
castShadow=true
|
||||
category=
|
||||
cullDistance=120.0
|
||||
lod1Distance=30.0
|
||||
lod1Path=
|
||||
lod2Distance=80.0
|
||||
lod2Path=
|
||||
name=manatrank
|
||||
pivotOffsetY=0.0
|
||||
placementOffsetY=0.0
|
||||
randomScaleMax=1.0
|
||||
randomScaleMin=1.0
|
||||
receiveShadow=true
|
||||
scaleX=0.2
|
||||
scaleY=0.2
|
||||
scaleZ=0.2
|
||||
solid=false
|
||||
tags=
|
||||
uniformScale=true
|
||||
BIN
blight-assets/src/main/resources/Models/schwachermanatrank.j3o
Normal file
BIN
blight-assets/src/main/resources/Models/starkermanatrank.j3o
Normal file
|
Before Width: | Height: | Size: 384 KiB After Width: | Height: | Size: 384 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 2.4 MiB |
@@ -3549,6 +3549,7 @@ public class EditorApp extends Application {
|
||||
Files.deleteIfExists(p);
|
||||
item.getParent().getChildren().remove(item);
|
||||
itemPaths.remove(item);
|
||||
if (pStr.endsWith(".j3o")) deleteJ3oSideFiles(p);
|
||||
setStatus("Gelöscht: " + p.getFileName());
|
||||
} catch (IOException ex) {
|
||||
setStatus("Fehler: " + ex.getMessage());
|
||||
@@ -3837,6 +3838,32 @@ public class EditorApp extends Application {
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Löscht Thumbnail und Impostor-Textur, die zu einer .j3o-Datei gehören.
|
||||
* Impostor-Dateien werden anhand des Zeitstempel-Suffixes (_YYYYMMDD_HHMMSS) ermittelt.
|
||||
*/
|
||||
private void deleteJ3oSideFiles(Path j3oPath) {
|
||||
// Thumbnail
|
||||
try {
|
||||
Files.deleteIfExists(
|
||||
de.blight.editor.state.ThumbnailRenderer.sidecarPath(j3oPath, ASSET_ROOT));
|
||||
} catch (IOException ignored) {}
|
||||
|
||||
// Impostor: Zeitstempel aus Dateiname extrahieren und passende Datei suchen
|
||||
String base = j3oPath.getFileName().toString().replace(".j3o", "");
|
||||
java.util.regex.Matcher m = java.util.regex.Pattern
|
||||
.compile(".*(\\d{8}_\\d{6})$").matcher(base);
|
||||
if (!m.matches()) return;
|
||||
String ts = m.group(1);
|
||||
Path impostorDir = ASSET_ROOT.resolve(
|
||||
de.blight.editor.state.ThumbnailRenderer.IMPOSTOR_DIR);
|
||||
if (!Files.isDirectory(impostorDir)) return;
|
||||
try (var stream = Files.list(impostorDir)) {
|
||||
stream.filter(f -> f.getFileName().toString().endsWith("_" + ts + ".png"))
|
||||
.forEach(f -> { try { Files.deleteIfExists(f); } catch (IOException ignored) {} });
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Befüllt den Asset-Baum vollständig aus dem Dateisystem.
|
||||
* Bekannte Verzeichnisse werden den Kategorie-Feldern zugewiesen;
|
||||
@@ -3851,6 +3878,11 @@ public class EditorApp extends Application {
|
||||
List<Path> topDirs;
|
||||
try (var s = Files.list(ASSET_ROOT)) {
|
||||
topDirs = s.filter(Files::isDirectory)
|
||||
.filter(p -> {
|
||||
String n = p.getFileName().toString();
|
||||
return !n.equals(de.blight.editor.state.ThumbnailRenderer.THUMB_DIR)
|
||||
&& !n.equals(de.blight.editor.state.ThumbnailRenderer.IMPOSTOR_DIR);
|
||||
})
|
||||
.sorted(Comparator.comparing(p -> p.getFileName().toString().toLowerCase()))
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
} catch (IOException e) { topDirs = List.of(); }
|
||||
|
||||
@@ -599,12 +599,12 @@ public class EzTreeState extends BaseAppState {
|
||||
img.setRGB(x, height - 1 - y, (a<<24)|(r<<16)|(g<<8)|b);
|
||||
}
|
||||
}
|
||||
Path texDir = ASSET_ROOT.resolve("Textures").resolve("impostor");
|
||||
Path texDir = ASSET_ROOT.resolve(ThumbnailRenderer.IMPOSTOR_DIR);
|
||||
Files.createDirectories(texDir);
|
||||
File pngFile = texDir.resolve(name + ".png").toFile();
|
||||
ImageIO.write(img, "PNG", pngFile);
|
||||
try {
|
||||
return (Texture2D) assets.loadTexture("Textures/impostor/" + name + ".png");
|
||||
return (Texture2D) assets.loadTexture(ThumbnailRenderer.IMPOSTOR_DIR + "/" + name + ".png");
|
||||
} catch (Exception ignored) {
|
||||
pixels.rewind();
|
||||
Image jmeImg = new Image(Image.Format.RGBA8, width, height, pixels, null,
|
||||
|
||||
@@ -28,6 +28,9 @@ import java.nio.file.Path;
|
||||
*/
|
||||
public class ModelEditorState extends BaseAppState {
|
||||
|
||||
private static final java.nio.file.Path ASSET_ROOT =
|
||||
de.blight.editor.ProjectRoot.resolve("blight-assets", "src", "main", "resources");
|
||||
|
||||
// ── Orbit-Kamera ─────────────────────────────────────────────────────────
|
||||
private static final float ORBIT_SENS = 0.4f; // Grad / Pixel Maus-Delta
|
||||
private static final float ZOOM_FACTOR = 0.1f;
|
||||
@@ -421,7 +424,7 @@ public class ModelEditorState extends BaseAppState {
|
||||
Spatial modelClone = modelWrapper.clone();
|
||||
byte[] thumb = ThumbnailRenderer.render(modelClone, app.getRenderManager(), app.getRenderer());
|
||||
if (thumb == null) return;
|
||||
ThumbnailRenderer.saveSidecar(thumb, j3oPath);
|
||||
ThumbnailRenderer.saveSidecar(thumb, j3oPath, ASSET_ROOT);
|
||||
embedThumbnail(thumb, j3oPath);
|
||||
} catch (Exception e) {
|
||||
System.err.println("[ModelEditor] Thumbnail-Fehler: " + e.getMessage());
|
||||
|
||||
@@ -1250,7 +1250,7 @@ public class SceneObjectState extends BaseAppState {
|
||||
ThumbnailRenderer.embed(model, thumb);
|
||||
Files.createDirectories(req.destJ3o().getParent());
|
||||
BinaryExporter.getInstance().save(model, req.destJ3o().toFile());
|
||||
ThumbnailRenderer.saveSidecar(thumb, req.destJ3o());
|
||||
ThumbnailRenderer.saveSidecar(thumb, req.destJ3o(), ASSET_ROOT);
|
||||
} else {
|
||||
Files.createDirectories(req.destJ3o().getParent());
|
||||
BinaryExporter.getInstance().save(model, req.destJ3o().toFile());
|
||||
|
||||
@@ -128,19 +128,28 @@ public final class ThumbnailRenderer {
|
||||
|
||||
public static String getUserDataKey() { return USERDATA_KEY; }
|
||||
|
||||
/** Speichert PNG-Bytes als {@code <j3oPath>.thumb.png}. */
|
||||
public static void saveSidecar(byte[] pngBytes, Path j3oPath) {
|
||||
/** Name des zentralen Thumbnail-Verzeichnisses (direkt unter assetRoot). */
|
||||
public static final String THUMB_DIR = ".thumbnails";
|
||||
|
||||
/** Name des zentralen Impostor-Textur-Verzeichnisses (direkt unter assetRoot). */
|
||||
public static final String IMPOSTOR_DIR = ".impostors";
|
||||
|
||||
/** Speichert PNG-Bytes ins zentrale Thumbnail-Verzeichnis ({@code assetRoot/.thumbnails/…}). */
|
||||
public static void saveSidecar(byte[] pngBytes, Path j3oPath, Path assetRoot) {
|
||||
if (pngBytes == null) return;
|
||||
try {
|
||||
Files.write(sidecarPath(j3oPath), pngBytes);
|
||||
Path dest = sidecarPath(j3oPath, assetRoot);
|
||||
Files.createDirectories(dest.getParent());
|
||||
Files.write(dest, pngBytes);
|
||||
} catch (IOException e) {
|
||||
System.err.println("[ThumbnailRenderer] Sidecar-Fehler: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** Pfad der Sidecar-Datei: {@code <j3oPath>.thumb.png}. */
|
||||
public static Path sidecarPath(Path j3oPath) {
|
||||
return j3oPath.resolveSibling(j3oPath.getFileName() + ".thumb.png");
|
||||
/** Pfad der Thumbnail-Datei: {@code assetRoot/.thumbnails/<relative-j3o-pfad>.thumb.png}. */
|
||||
public static Path sidecarPath(Path j3oPath, Path assetRoot) {
|
||||
Path rel = assetRoot.relativize(j3oPath);
|
||||
return assetRoot.resolve(THUMB_DIR).resolve(rel.toString() + ".thumb.png");
|
||||
}
|
||||
|
||||
// ── Intern ───────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -593,14 +593,14 @@ public class TreeGeneratorState extends BaseAppState {
|
||||
img.setRGB(x, height - 1 - y, (a<<24)|(r<<16)|(g<<8)|b);
|
||||
}
|
||||
}
|
||||
Path texDir = ASSET_ROOT.resolve("Textures").resolve("impostor");
|
||||
Path texDir = ASSET_ROOT.resolve(ThumbnailRenderer.IMPOSTOR_DIR);
|
||||
Files.createDirectories(texDir);
|
||||
File pngFile = texDir.resolve(name + ".png").toFile();
|
||||
ImageIO.write(img, "PNG", pngFile);
|
||||
log.info("[Blight-Baum] Impostor: {}", pngFile.getAbsolutePath());
|
||||
|
||||
try {
|
||||
return (Texture2D) assets.loadTexture("Textures/impostor/" + name + ".png");
|
||||
return (Texture2D) assets.loadTexture(ThumbnailRenderer.IMPOSTOR_DIR + "/" + name + ".png");
|
||||
} catch (Exception loadEx) {
|
||||
pixels.rewind();
|
||||
Image jmeImg = new Image(Image.Format.RGBA8, width, height,
|
||||
|
||||
@@ -8,7 +8,7 @@ import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.stage.Modality;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import de.blight.editor.state.ThumbnailRenderer;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.*;
|
||||
@@ -18,7 +18,7 @@ import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Dialog zum Auswählen eines .j3o-Modells.
|
||||
* Zeigt Karten mit 128×128-Thumbnail wenn eine {@code .j3o.thumb.png} Sidecar-Datei vorhanden ist.
|
||||
* Zeigt Karten mit 128×128-Thumbnail wenn eine Thumbnail-Datei im zentralen {@code .thumbnails}-Verzeichnis vorhanden ist.
|
||||
* Gibt den relativen Asset-Pfad (z.B. "Models/Items/sword.j3o") zurück oder {@code null} bei Abbruch.
|
||||
*/
|
||||
public class ModelChooser extends Dialog<String> {
|
||||
@@ -113,8 +113,7 @@ public class ModelChooser extends Dialog<String> {
|
||||
}
|
||||
|
||||
private Image loadThumb(Path j3o) {
|
||||
// Sidecar: <model.j3o>.thumb.png
|
||||
Path sidecar = j3o.resolveSibling(j3o.getFileName() + ".thumb.png");
|
||||
Path sidecar = ThumbnailRenderer.sidecarPath(j3o, assetRoot);
|
||||
if (Files.isRegularFile(sidecar)) {
|
||||
try (InputStream is = Files.newInputStream(sidecar)) {
|
||||
return new Image(is, THUMB_SIZE, THUMB_SIZE, true, true);
|
||||
|
||||
@@ -44,3 +44,4 @@ Models/plants/fern/fern_20260608_165628.j3o 162.27063 0.88450 24.03092 0.00000 1
|
||||
Models/plants/misc/heliconia+plant+3d+model.j3o 152.94803 0.96488 8.99865 0.00000 1.00000 0.00000 0.00000 false true true 30.00000 80.00000 120.00000
|
||||
Models/plants/misc/heliconia+plant+3d+model.j3o 155.57500 0.96457 10.04861 0.00000 1.00000 0.00000 0.00000 false true true 30.00000 80.00000 120.00000
|
||||
Models/plants/misc/kaktusfeige.j3o 153.89978 0.98474 38.66549 0.00000 2.50000 0.00000 0.00000 true true true 30.00000 80.00000 120.00000
|
||||
@plane 102.97000 1.06000 -172.24001 0.00000 1.00000 0.00000 0.00000 false Textures/ground/Rocks015_1K-JPG_Color.jpg Textures/ground/Rocks015_1K-JPG_NormalDX.jpg Common/MatDefs/Light/Lighting.j3md Models/custom_mesh_7.j3o true true 30.00000 80.00000 120.00000
|
||||
|
||||