SpriteLoader.java

net.minecraft.client.renderer.texture.SpriteLoader

信息

  • 全限定名:net.minecraft.client.renderer.texture.SpriteLoader
  • 类型:public class
  • 包:net.minecraft.client.renderer.texture
  • 源码路径:src/main/java/net/minecraft/client/renderer/texture/SpriteLoader.java
  • 起始行号:L35
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L36
    • 说明:

      TODO

  • location

    • 类型: Identifier
    • 修饰符: private final
    • 源码定位: L37
    • 说明:

      TODO

  • maxSupportedTextureSize

    • 类型: int
    • 修饰符: private final
    • 源码定位: L38
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.client.renderer.texture.SpriteLoader.Preparations
    • 类型: record
    • 修饰符: public
    • 源码定位: L146
    • 说明:

      TODO

构造器

public SpriteLoader(Identifier location, int maxSupportedTextureSize) @ L40

  • 构造器名:SpriteLoader
  • 源码定位:L40
  • 修饰符:public

参数:

  • location: Identifier
  • maxSupportedTextureSize: int

说明:

TODO

方法

下面的方法块按源码顺序生成。

public static SpriteLoader create(TextureAtlas atlas) @ L45

  • 方法名:create
  • 源码定位:L45
  • 返回类型:SpriteLoader
  • 修饰符:public static

参数:

  • atlas: TextureAtlas

说明:

TODO

private SpriteLoader.Preparations stitch(List<SpriteContents> sprites, int maxMipmapLevels, Executor executor) @ L49

  • 方法名:stitch
  • 源码定位:L49
  • 返回类型:SpriteLoader.Preparations
  • 修饰符:private

参数:

  • sprites: List
  • maxMipmapLevels: int
  • executor: Executor

说明:

TODO

private static CompletableFuture<List<SpriteContents>> runSpriteSuppliers(SpriteResourceLoader resourceLoader, List<SpriteSource.Loader> sprites, Executor executor) @ L119

  • 方法名:runSpriteSuppliers
  • 源码定位:L119
  • 返回类型:CompletableFuture<List>
  • 修饰符:private static

参数:

  • resourceLoader: SpriteResourceLoader
  • sprites: List<SpriteSource.Loader>
  • executor: Executor

说明:

TODO

public CompletableFuture<SpriteLoader.Preparations> loadAndStitch(ResourceManager manager, Identifier atlasInfoLocation, int maxMipmapLevels, Executor taskExecutor, Set<MetadataSectionType<?>> additionalMetadata) @ L128

  • 方法名:loadAndStitch
  • 源码定位:L128
  • 返回类型:CompletableFuture<SpriteLoader.Preparations>
  • 修饰符:public

参数:

  • manager: ResourceManager
  • atlasInfoLocation: Identifier
  • maxMipmapLevels: int
  • taskExecutor: Executor
  • additionalMetadata: Set<MetadataSectionType<?>>

说明:

TODO

private Map<Identifier,TextureAtlasSprite> getStitchedSprites(Stitcher<SpriteContents> stitcher, int atlasWidth, int atlasHeight) @ L137

  • 方法名:getStitchedSprites
  • 源码定位:L137
  • 返回类型:Map<Identifier,TextureAtlasSprite>
  • 修饰符:private

参数:

  • stitcher: Stitcher
  • atlasWidth: int
  • atlasHeight: int

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class SpriteLoader {
    private static final Logger LOGGER = LogUtils.getLogger();
    private final Identifier location;
    private final int maxSupportedTextureSize;
 
    public SpriteLoader(Identifier location, int maxSupportedTextureSize) {
        this.location = location;
        this.maxSupportedTextureSize = maxSupportedTextureSize;
    }
 
    public static SpriteLoader create(TextureAtlas atlas) {
        return new SpriteLoader(atlas.location(), atlas.maxSupportedTextureSize());
    }
 
    private SpriteLoader.Preparations stitch(List<SpriteContents> sprites, int maxMipmapLevels, Executor executor) {
        SpriteLoader.Preparations var19;
        try (Zone ignored = Profiler.get().zone(() -> "stitch " + this.location)) {
            int maxTextureSize = this.maxSupportedTextureSize;
            int minTexelSize = Integer.MAX_VALUE;
            int lowestOneBit = 1 << maxMipmapLevels;
 
            for (SpriteContents spriteInfo : sprites) {
                minTexelSize = Math.min(minTexelSize, Math.min(spriteInfo.width(), spriteInfo.height()));
                int lowestTextureBit = Math.min(Integer.lowestOneBit(spriteInfo.width()), Integer.lowestOneBit(spriteInfo.height()));
                if (lowestTextureBit < lowestOneBit) {
                    LOGGER.warn(
                        "Texture {} with size {}x{} limits mip level from {} to {}",
                        spriteInfo.name(),
                        spriteInfo.width(),
                        spriteInfo.height(),
                        Mth.log2(lowestOneBit),
                        Mth.log2(lowestTextureBit)
                    );
                    lowestOneBit = lowestTextureBit;
                }
            }
 
            int minSize = Math.min(minTexelSize, lowestOneBit);
            int minPowerOfTwo = Mth.log2(minSize);
            int mipLevel;
            if (minPowerOfTwo < maxMipmapLevels) {
                LOGGER.warn("{}: dropping miplevel from {} to {}, because of minimum power of two: {}", this.location, maxMipmapLevels, minPowerOfTwo, minSize);
                mipLevel = minPowerOfTwo;
            } else {
                mipLevel = maxMipmapLevels;
            }
 
            Options options = Minecraft.getInstance().options;
            int anisotropyBit = options.textureFiltering().get() != TextureFilteringMethod.ANISOTROPIC ? 0 : options.maxAnisotropyBit().get();
            Stitcher<SpriteContents> stitcher = new Stitcher<>(maxTextureSize, maxTextureSize, mipLevel, anisotropyBit);
 
            for (SpriteContents spriteInfox : sprites) {
                stitcher.registerSprite(spriteInfox);
            }
 
            try {
                stitcher.stitch();
            } catch (StitcherException var21) {
                CrashReport report = CrashReport.forThrowable(var21, "Stitching");
                CrashReportCategory category = report.addCategory("Stitcher");
                category.setDetail(
                    "Sprites",
                    var21.getAllSprites()
                        .stream()
                        .map(s -> String.format(Locale.ROOT, "%s[%dx%d]", s.name(), s.width(), s.height()))
                        .collect(Collectors.joining(","))
                );
                category.setDetail("Max Texture Size", maxTextureSize);
                throw new ReportedException(report);
            }
 
            int width = stitcher.getWidth();
            int height = stitcher.getHeight();
            Map<Identifier, TextureAtlasSprite> result = this.getStitchedSprites(stitcher, width, height);
            TextureAtlasSprite missingSprite = result.get(MissingTextureAtlasSprite.getLocation());
            CompletableFuture<Void> readyForUpload = CompletableFuture.runAsync(
                () -> result.values().forEach(s -> s.contents().increaseMipLevel(mipLevel)), executor
            );
            var19 = new SpriteLoader.Preparations(width, height, mipLevel, missingSprite, result, readyForUpload);
        }
 
        return var19;
    }
 
    private static CompletableFuture<List<SpriteContents>> runSpriteSuppliers(
        SpriteResourceLoader resourceLoader, List<SpriteSource.Loader> sprites, Executor executor
    ) {
        List<CompletableFuture<SpriteContents>> spriteFutures = sprites.stream()
            .map(supplier -> CompletableFuture.supplyAsync(() -> supplier.get(resourceLoader), executor))
            .toList();
        return Util.sequence(spriteFutures).thenApply(l -> l.stream().filter(Objects::nonNull).toList());
    }
 
    public CompletableFuture<SpriteLoader.Preparations> loadAndStitch(
        ResourceManager manager, Identifier atlasInfoLocation, int maxMipmapLevels, Executor taskExecutor, Set<MetadataSectionType<?>> additionalMetadata
    ) {
        SpriteResourceLoader spriteResourceLoader = SpriteResourceLoader.create(additionalMetadata);
        return CompletableFuture.<List<SpriteSource.Loader>>supplyAsync(() -> SpriteSourceList.load(manager, atlasInfoLocation).list(manager), taskExecutor)
            .thenCompose(sprites -> runSpriteSuppliers(spriteResourceLoader, (List<SpriteSource.Loader>)sprites, taskExecutor))
            .thenApply(resources -> this.stitch((List<SpriteContents>)resources, maxMipmapLevels, taskExecutor));
    }
 
    private Map<Identifier, TextureAtlasSprite> getStitchedSprites(Stitcher<SpriteContents> stitcher, int atlasWidth, int atlasHeight) {
        Map<Identifier, TextureAtlasSprite> result = new HashMap<>();
        stitcher.gatherSprites(
            (contents, x, y, padding) -> result.put(contents.name(), new TextureAtlasSprite(this.location, contents, atlasWidth, atlasHeight, x, y, padding))
        );
        return result;
    }
 
    @OnlyIn(Dist.CLIENT)
    public record Preparations(
        int width, int height, int mipLevel, TextureAtlasSprite missing, Map<Identifier, TextureAtlasSprite> regions, CompletableFuture<Void> readyForUpload
    ) {
        public @Nullable TextureAtlasSprite getSprite(Identifier id) {
            return this.regions.get(id);
        }
    }
}

引用的其他类