package de.lessvoid.nifty.render; import de.lessvoid.nifty.render.batch.BatchRenderDevice; import de.lessvoid.nifty.render.batch.BatchRenderImage; import de.lessvoid.nifty.render.NiftyImageManager.ReferencedCountedImage; import de.lessvoid.nifty.screen.Screen; import de.lessvoid.nifty.spi.render.RenderDevice; import de.lessvoid.nifty.spi.render.RenderImage; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; public class NiftyImageManagerExtBatch implements NiftyImageManagerExt<ReferencedCountedImage> { @Nonnull private static final Logger log = Logger.getLogger(NiftyImageManagerExtBatch.class.getName()); @Nonnull private final Map<String, Set<ReferencedCountedImageBatch>> screenRef = new HashMap<String, Set<ReferencedCountedImageBatch>>(); @Nullable private Screen currentScreen; @Override public void registerImage(@Nonnull final Screen screen, @Nonnull final ReferencedCountedImage image) { Set<ReferencedCountedImageBatch> screenList = screenRef.get(screen.getScreenId()); if (screenList == null) { screenList = new HashSet<ReferencedCountedImageBatch>(); screenRef.put(screen.getScreenId(), screenList); } final ReferencedCountedImageBatch batchImage = cast(image); if (screenList.add(batchImage)) { if (log.isLoggable(Level.FINER)) { log.finer("[" + screen.getScreenId() + "] now with [" + screenList.size() + "] entries (" + image.getName() + ")"); } } if (currentScreen != null && currentScreen.getScreenId().equals(screen.getScreenId())) { if (!batchImage.isUploaded()) { batchImage.upload(); } } } @Override public void unregisterImage(@Nonnull final ReferencedCountedImage reference) { final ReferencedCountedImageBatch image = cast(reference); image.unload(); Set<ReferencedCountedImageBatch> screenList = screenRef.get(reference.getScreen().getScreenId()); if (screenList != null) { screenList.remove(image); } } @Override public void uploadScreenImages(@Nonnull final Screen screen) { currentScreen = screen; // find all ReferencedCountedImage and upload them into the texture atlas (for this screen). Set<ReferencedCountedImageBatch> imageList = screenRef.get(screen.getScreenId()); if (imageList == null) { return; } for (ReferencedCountedImageBatch image : imageList) { image.upload(); } } @Override public void unloadScreenImages( @Nonnull final Screen screen, @Nonnull final RenderDevice renderDevice, @Nonnull final Collection<ReferencedCountedImage> imageSet) { ((BatchRenderDevice) renderDevice).resetTextureAtlases(); // we need to mark all images as unloaded for (ReferencedCountedImage i : imageSet) { cast(i).markAsUnloaded(); } currentScreen = null; } @Nonnull private static ReferencedCountedImageBatch cast(@Nonnull final ReferencedCountedImage image) { if (image instanceof ReferencedCountedImageBatch) { return (ReferencedCountedImageBatch) image; } throw new IllegalArgumentException("Illegal image type supplied: " + image.getClass().getName() + "expected " + ReferencedCountedImageBatch.class.getName()); } @Override public void screenAdded(@Nonnull final Screen screen) { } @Override public void screenRemoved(@Nonnull final Screen screen) { screenRef.remove(screen.getScreenId()); } @Override public void addScreenInfo(@Nonnull final StringBuffer result) { if (screenRef.entrySet().isEmpty()) { return; } result.append("\n"); for (Map.Entry<String, Set<ReferencedCountedImageBatch>> entry : screenRef.entrySet()) { result.append("\n[").append(entry.getKey()).append("]\n"); for (ReferencedCountedImageBatch image : entry.getValue()) { result.append(image.toString()); } } } @Nonnull @Override public ReferencedCountedImageBatch createReferencedCountedImage( @Nonnull final RenderDevice renderDevice, @Nonnull final Screen screen, @Nonnull final String filename, final boolean filterLinear, @Nonnull final RenderImage renderImage, @Nonnull final String key) { return new ReferencedCountedImageBatch(renderDevice, screen, filename, filterLinear, renderImage, key); } /** * A standard implementation of a ReferencedCountedImage without Batch support. * * @author void */ public static class ReferencedCountedImageBatch implements ReferencedCountedImage { @Nonnull private final RenderDevice renderDevice; @Nonnull private final Screen screen; @Nonnull private final String filename; private final boolean filterLinear; @Nonnull private final String key; @Nonnull private RenderImage renderImage; private int references; public ReferencedCountedImageBatch( @Nonnull final RenderDevice renderDevice, @Nonnull final Screen screen, @Nonnull final String filename, final boolean filterLinear, @Nonnull final RenderImage renderImage, @Nonnull final String key) { this.renderDevice = renderDevice; this.screen = screen; this.filename = filename; this.filterLinear = filterLinear; this.key = key; this.renderImage = renderImage; this.references = 1; } public void upload() { BatchRenderImage batchRenderImage = (BatchRenderImage) renderImage; batchRenderImage.upload(); } public void unload() { BatchRenderImage batchRenderImage = (BatchRenderImage) renderImage; batchRenderImage.unload(); } public void markAsUnloaded() { BatchRenderImage batchRenderImage = (BatchRenderImage) renderImage; batchRenderImage.markAsUnloaded(); } @Nonnull @Override public RenderImage reload() { final RenderImage newImage = renderDevice.createImage(filename, filterLinear); if (newImage == null) { log.severe("Failed to reload image, reloading canceled."); } else { renderImage.dispose(); renderImage = newImage; } return renderImage; } @Nonnull @Override public RenderImage addReference() { references++; return renderImage; } @Override public boolean removeReference() { references--; if (references == 0) { renderImage.dispose(); return true; } return false; } @Override public int getReferences() { return references; } @Nonnull @Override public RenderImage getRenderImage() { return renderImage; } @Nonnull @Override public String getName() { return key; } @Nonnull @Override public Screen getScreen() { return screen; } public boolean isUploaded() { if (renderImage instanceof BatchRenderImage) { return ((BatchRenderImage) renderImage).isUploaded(); } return false; } @Nonnull @Override public String toString() { return " - [" + getName() + "] reference count [" + getReferences() + "] uploaded [" + isUploaded() + "]\n"; } } }