DynamicAtlasAllocator.java
net.minecraft.client.gui.render.DynamicAtlasAllocator
信息
- 全限定名:net.minecraft.client.gui.render.DynamicAtlasAllocator
- 类型:public class
- 包:net.minecraft.client.gui.render
- 源码路径:src/main/java/net/minecraft/client/gui/render/DynamicAtlasAllocator.java
- 起始行号:L19
- 职责:
TODO
字段/常量
-
width- 类型:
int - 修饰符:
private final - 源码定位:
L20 - 说明:
TODO
- 类型:
-
slots- 类型:
List<DynamicAtlasAllocator.Slot> - 修饰符:
private final - 源码定位:
L21 - 说明:
TODO
- 类型:
-
usedSlotByKey- 类型:
Map<K,DynamicAtlasAllocator.Slot> - 修饰符:
private final - 源码定位:
L22 - 说明:
TODO
- 类型:
-
freeSlots- 类型:
BitSet - 修饰符:
private final - 源码定位:
L23 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.client.gui.render.DynamicAtlasAllocator.Slot- 类型:
class - 修饰符:
public static - 源码定位:
L113 - 说明:
TODO
- 类型:
-
net.minecraft.client.gui.render.DynamicAtlasAllocator.SlotState- 类型:
enum - 修饰符:
public static - 源码定位:
L139 - 说明:
TODO
- 类型:
构造器
public DynamicAtlasAllocator(int width, int height) @ L25
- 构造器名:DynamicAtlasAllocator
- 源码定位:L25
- 修饰符:public
参数:
- width: int
- height: int
说明:
TODO
方法
下面的方法块按源码顺序生成。
public boolean reclaimSpaceFor(Set<K> keys) @ L40
- 方法名:reclaimSpaceFor
- 源码定位:L40
- 返回类型:boolean
- 修饰符:public
参数:
- keys: Set
说明:
TODO
public void endFrame() @ L58
- 方法名:endFrame
- 源码定位:L58
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
private void freeSlotIf(BiPredicate<K,DynamicAtlasAllocator.Slot> predicate) @ L62
- 方法名:freeSlotIf
- 源码定位:L62
- 返回类型:void
- 修饰符:private
参数:
- predicate: BiPredicate<K,DynamicAtlasAllocator.Slot>
说明:
TODO
public boolean hasSpaceForAll(Set<K> keys) @ L75
- 方法名:hasSpaceForAll
- 源码定位:L75
- 返回类型:boolean
- 修饰符:public
参数:
- keys: Set
说明:
TODO
public DynamicAtlasAllocator.Slot getOrAllocate(K key, boolean discardAfterFrame) @ L80
- 方法名:getOrAllocate
- 源码定位:L80
- 返回类型:DynamicAtlasAllocator.Slot
- 修饰符:public
参数:
- key: K
- discardAfterFrame: boolean
说明:
TODO
public int freeSlotCount() @ L102
- 方法名:freeSlotCount
- 源码定位:L102
- 返回类型:int
- 修饰符:public
参数:
- 无
说明:
TODO
public Set<K> usedSlotKeys() @ L107
- 方法名:usedSlotKeys
- 源码定位:L107
- 返回类型:Set
- 修饰符:public
参数:
- 无
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class DynamicAtlasAllocator<K> {
private final int width;
private final List<DynamicAtlasAllocator.Slot> slots;
private final Map<K, DynamicAtlasAllocator.Slot> usedSlotByKey = new HashMap<>();
private final BitSet freeSlots;
public DynamicAtlasAllocator(int width, int height) {
this.width = width;
int size = width * height;
this.slots = new ArrayList<>(size);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
this.slots.add(new DynamicAtlasAllocator.Slot(x, y));
}
}
this.freeSlots = new BitSet(size);
this.freeSlots.set(0, size);
}
public boolean reclaimSpaceFor(Set<K> keys) {
int preexistingKeyCount = Sets.intersection(this.usedSlotByKey.keySet(), keys).size();
if (preexistingKeyCount == keys.size()) {
return true;
} else {
MutableInt needSpaceFor = new MutableInt(keys.size() - preexistingKeyCount);
this.freeSlotIf((key, var3x) -> {
if (needSpaceFor.intValue() != 0 && !keys.contains(key)) {
needSpaceFor.decrement();
return true;
} else {
return false;
}
});
return needSpaceFor.intValue() == 0;
}
}
public void endFrame() {
this.freeSlotIf((var0, slot) -> slot.discardAfterFrame);
}
private void freeSlotIf(BiPredicate<K, DynamicAtlasAllocator.Slot> predicate) {
this.usedSlotByKey.entrySet().removeIf(entry -> {
if (!predicate.test(entry.getKey(), entry.getValue())) {
return false;
} else {
DynamicAtlasAllocator.Slot slot = entry.getValue();
this.freeSlots.set(slot.x + slot.y * this.width);
slot.discardAfterFrame = false;
return true;
}
});
}
public boolean hasSpaceForAll(Set<K> keys) {
Set<K> predictedUsedSlots = Sets.union(this.usedSlotByKey.keySet(), keys);
return predictedUsedSlots.size() <= this.slots.size();
}
public DynamicAtlasAllocator.@Nullable Slot getOrAllocate(K key, boolean discardAfterFrame) {
DynamicAtlasAllocator.Slot usedSlot = this.usedSlotByKey.get(key);
if (usedSlot != null) {
usedSlot.discardAfterFrame |= discardAfterFrame;
usedSlot.externalState = DynamicAtlasAllocator.SlotState.READY;
return usedSlot;
} else {
int freeSlotIndex = this.freeSlots.nextSetBit(0);
if (freeSlotIndex == -1) {
return null;
} else {
DynamicAtlasAllocator.Slot freeSlot = this.slots.get(freeSlotIndex);
freeSlot.externalState = freeSlot.fresh ? DynamicAtlasAllocator.SlotState.EMPTY : DynamicAtlasAllocator.SlotState.STALE;
freeSlot.fresh = false;
freeSlot.discardAfterFrame = discardAfterFrame;
this.usedSlotByKey.put(key, freeSlot);
this.freeSlots.clear(freeSlotIndex);
return freeSlot;
}
}
}
@VisibleForTesting
public int freeSlotCount() {
return this.slots.size() - this.usedSlotByKey.size();
}
@VisibleForTesting
public Set<K> usedSlotKeys() {
return Collections.unmodifiableSet(this.usedSlotByKey.keySet());
}
@OnlyIn(Dist.CLIENT)
public static class Slot {
private final int x;
private final int y;
private boolean fresh = true;
private boolean discardAfterFrame;
private DynamicAtlasAllocator.SlotState externalState = DynamicAtlasAllocator.SlotState.EMPTY;
private Slot(int x, int y) {
this.x = x;
this.y = y;
}
public int x() {
return this.x;
}
public int y() {
return this.y;
}
public DynamicAtlasAllocator.SlotState state() {
return this.externalState;
}
}
@OnlyIn(Dist.CLIENT)
public static enum SlotState {
EMPTY,
STALE,
READY;
}
}引用的其他类
- 无