-
-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Add ModelTree - Add LoweringVisitor to traverse a MeshTree and emit ModelTree nodes and Models - Provide some default visitor creation methods - Abstract ModelCache -> ResourceReloadCache - Abstract ModelHolder -> ResourceReloadHolder - Add ModelTreeCache to hide lookup cost if it gets extreme
- Loading branch information
Showing
13 changed files
with
361 additions
and
141 deletions.
There are no files selected for viewing
33 changes: 2 additions & 31 deletions
33
common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,11 @@ | ||
package dev.engine_room.flywheel.lib.model; | ||
|
||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.function.Function; | ||
|
||
import org.jetbrains.annotations.ApiStatus; | ||
|
||
import dev.engine_room.flywheel.api.model.Model; | ||
import dev.engine_room.flywheel.lib.util.FlwUtil; | ||
|
||
public final class ModelCache<T> { | ||
private static final Set<ModelCache<?>> ALL = FlwUtil.createWeakHashSet(); | ||
private final Function<T, Model> factory; | ||
private final Map<T, Model> map = new ConcurrentHashMap<>(); | ||
|
||
public final class ModelCache<T> extends ResourceReloadCache<T, Model> { | ||
public ModelCache(Function<T, Model> factory) { | ||
this.factory = factory; | ||
|
||
synchronized (ALL) { | ||
ALL.add(this); | ||
} | ||
} | ||
|
||
public Model get(T key) { | ||
return map.computeIfAbsent(key, factory); | ||
} | ||
|
||
public void clear() { | ||
map.clear(); | ||
} | ||
|
||
@ApiStatus.Internal | ||
public static void onEndClientResourceReload() { | ||
for (ModelCache<?> cache : ALL) { | ||
cache.clear(); | ||
} | ||
super(factory); | ||
} | ||
} |
53 changes: 2 additions & 51 deletions
53
common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelHolder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,11 @@ | ||
package dev.engine_room.flywheel.lib.model; | ||
|
||
import java.util.Set; | ||
import java.util.function.Supplier; | ||
|
||
import org.jetbrains.annotations.ApiStatus; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import dev.engine_room.flywheel.api.model.Model; | ||
import dev.engine_room.flywheel.lib.util.FlwUtil; | ||
|
||
public final class ModelHolder { | ||
private static final Set<ModelHolder> ALL = FlwUtil.createWeakHashSet(); | ||
private final Supplier<Model> factory; | ||
@Nullable | ||
private volatile Model model; | ||
|
||
public final class ModelHolder extends ResourceReloadHolder<Model> { | ||
public ModelHolder(Supplier<Model> factory) { | ||
this.factory = factory; | ||
|
||
synchronized (ALL) { | ||
ALL.add(this); | ||
} | ||
} | ||
|
||
public Model get() { | ||
Model model = this.model; | ||
|
||
if (model == null) { | ||
synchronized (this) { | ||
model = this.model; | ||
if (model == null) { | ||
this.model = model = factory.get(); | ||
} | ||
} | ||
} | ||
|
||
return model; | ||
} | ||
|
||
public void clear() { | ||
Model model = this.model; | ||
|
||
if (model != null) { | ||
synchronized (this) { | ||
model = this.model; | ||
if (model != null) { | ||
this.model = null; | ||
} | ||
} | ||
} | ||
} | ||
|
||
@ApiStatus.Internal | ||
public static void onEndClientResourceReload() { | ||
for (ModelHolder holder : ALL) { | ||
holder.clear(); | ||
} | ||
super(factory); | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
common/src/lib/java/dev/engine_room/flywheel/lib/model/ResourceReloadCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package dev.engine_room.flywheel.lib.model; | ||
|
||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.function.Function; | ||
|
||
import org.jetbrains.annotations.ApiStatus; | ||
|
||
import dev.engine_room.flywheel.lib.util.FlwUtil; | ||
|
||
public class ResourceReloadCache<T, U> implements Function<T, U> { | ||
private static final Set<ResourceReloadCache<?, ?>> ALL = FlwUtil.createWeakHashSet(); | ||
private final Function<T, U> factory; | ||
private final Map<T, U> map = new ConcurrentHashMap<>(); | ||
|
||
public ResourceReloadCache(Function<T, U> factory) { | ||
this.factory = factory; | ||
|
||
synchronized (ALL) { | ||
ALL.add(this); | ||
} | ||
} | ||
|
||
public final U get(T key) { | ||
return map.computeIfAbsent(key, factory); | ||
} | ||
|
||
@Override | ||
public final U apply(T t) { | ||
return get(t); | ||
} | ||
|
||
public final void clear() { | ||
map.clear(); | ||
} | ||
|
||
@ApiStatus.Internal | ||
public static void onEndClientResourceReload() { | ||
for (ResourceReloadCache<?, ?> cache : ALL) { | ||
cache.clear(); | ||
} | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
common/src/lib/java/dev/engine_room/flywheel/lib/model/ResourceReloadHolder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package dev.engine_room.flywheel.lib.model; | ||
|
||
import java.util.Set; | ||
import java.util.function.Supplier; | ||
|
||
import org.jetbrains.annotations.ApiStatus; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import dev.engine_room.flywheel.lib.util.FlwUtil; | ||
|
||
public class ResourceReloadHolder<T> implements Supplier<T> { | ||
private static final Set<ResourceReloadHolder<?>> ALL = FlwUtil.createWeakHashSet(); | ||
private final Supplier<T> factory; | ||
@Nullable | ||
private volatile T obj; | ||
|
||
public ResourceReloadHolder(Supplier<T> factory) { | ||
this.factory = factory; | ||
|
||
synchronized (ALL) { | ||
ALL.add(this); | ||
} | ||
} | ||
|
||
@Override | ||
public final T get() { | ||
T obj = this.obj; | ||
|
||
if (obj == null) { | ||
synchronized (this) { | ||
obj = this.obj; | ||
if (obj == null) { | ||
this.obj = obj = factory.get(); | ||
} | ||
} | ||
} | ||
|
||
return obj; | ||
} | ||
|
||
public final void clear() { | ||
T obj = this.obj; | ||
|
||
if (obj != null) { | ||
synchronized (this) { | ||
obj = this.obj; | ||
if (obj != null) { | ||
this.obj = null; | ||
} | ||
} | ||
} | ||
} | ||
|
||
@ApiStatus.Internal | ||
public static void onEndClientResourceReload() { | ||
for (ResourceReloadHolder<?> holder : ALL) { | ||
holder.clear(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
common/src/lib/java/dev/engine_room/flywheel/lib/model/part/LoweringVisitor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package dev.engine_room.flywheel.lib.model.part; | ||
|
||
import java.util.ArrayList; | ||
|
||
import org.jetbrains.annotations.Nullable; | ||
|
||
import dev.engine_room.flywheel.api.material.Material; | ||
import dev.engine_room.flywheel.api.model.Mesh; | ||
import dev.engine_room.flywheel.api.model.Model; | ||
import dev.engine_room.flywheel.lib.model.RetexturedMesh; | ||
import dev.engine_room.flywheel.lib.model.SingleMeshModel; | ||
import net.minecraft.client.model.geom.PartPose; | ||
import net.minecraft.client.renderer.texture.TextureAtlasSprite; | ||
|
||
/** | ||
* A tree walking visitor that lowers a MeshTree to a ModelTree. | ||
*/ | ||
public interface LoweringVisitor { | ||
static ModelTree leaf(Model model) { | ||
return leaf(model, PartPose.ZERO); | ||
} | ||
|
||
static ModelTree leaf(Model model, PartPose initialPose) { | ||
return ModelTree.create(model, initialPose, new ModelTree[0], new String[0]); | ||
} | ||
|
||
static LoweringVisitor materialApplyingVisitor(Material material) { | ||
return (path, mesh) -> new SingleMeshModel(mesh, material); | ||
} | ||
|
||
static LoweringVisitor retexturingVisitor(Material material, TextureAtlasSprite sprite) { | ||
return (path, mesh) -> new SingleMeshModel(new RetexturedMesh(mesh, sprite), material); | ||
} | ||
|
||
static String append(String path, String child) { | ||
if (path.isEmpty()) { | ||
return child; | ||
} | ||
|
||
return path + "/" + child; | ||
} | ||
|
||
/** | ||
* Walk the given MeshTree, lowering its Mesh to a Model, and lowering all children using the given visitor. | ||
* | ||
* @param path The absolute path to the MeshTree node. | ||
* @param meshTree The MeshTree to walk. | ||
* @param loweringVisitor The visitor to use to lower the Mesh and MeshTree nodes. | ||
* @return The lowered ModelTree. | ||
*/ | ||
static ModelTree walk(String path, MeshTree meshTree, LoweringVisitor loweringVisitor) { | ||
Model out = null; | ||
|
||
if (meshTree.mesh() != null) { | ||
out = loweringVisitor.visit(path, meshTree.mesh()); | ||
} | ||
|
||
ArrayList<ModelTree> children = new ArrayList<>(); | ||
ArrayList<String> childNames = new ArrayList<>(); | ||
|
||
for (int i = 0; i < meshTree.childCount(); i++) { | ||
var child = loweringVisitor.visit(append(path, meshTree.childName(i)), meshTree.child(i)); | ||
|
||
if (child != null) { | ||
children.add(child); | ||
childNames.add(meshTree.childName(i)); | ||
} | ||
} | ||
|
||
return ModelTree.create(out, meshTree.initialPose(), children.toArray(new ModelTree[0]), childNames.toArray(new String[0])); | ||
} | ||
|
||
/** | ||
* Visit the given Mesh, converting it to a Model. | ||
* | ||
* @param path The absolute path to the MeshTree node containing the Mesh. | ||
* @param mesh The Mesh to lower. | ||
* @return The lowered Model, or null if the Model should be omitted. | ||
*/ | ||
@Nullable Model visit(String path, Mesh mesh); | ||
|
||
/** | ||
* Visit the given MeshTree, converting it to a ModelTree. | ||
* | ||
* @param path The absolute path to the MeshTree node. | ||
* @param meshTree The MeshTree to lower. | ||
* @return The lowered ModelTree, or null if the ModelTree should be omitted. | ||
*/ | ||
@Nullable | ||
default ModelTree visit(String path, MeshTree meshTree) { | ||
return walk(path, meshTree, this); | ||
} | ||
} |
Oops, something went wrong.