first code commit
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package mods.betterfoliage.client.resource;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public interface ILeafTextureRecognizer {
|
||||
|
||||
public boolean isLeafTexture(TextureAtlasSprite icon);
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package mods.betterfoliage.client.resource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import mods.betterfoliage.BetterFoliage;
|
||||
import mods.betterfoliage.client.BetterFoliageClient;
|
||||
import mods.betterfoliage.common.util.DeobfNames;
|
||||
import mods.betterfoliage.common.util.ReflectionUtil;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.client.resources.IResource;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
/** Generates rounded crossleaf textures for all registered normal leaf textures at stitch time.
|
||||
* @author octarine-noise
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class LeafTextureGenerator implements IIconRegister, IResourceManager {
|
||||
|
||||
/** Resource domain name of autogenerated crossleaf textures */
|
||||
public String domainName = "bf_leaves_autogen";
|
||||
|
||||
/** Resource location for fallback texture (if the generation process fails) */
|
||||
public ResourceLocation missing_resource = new ResourceLocation("betterfoliage", "textures/blocks/missingleaf.png");
|
||||
|
||||
/** Texture atlas for block textures used in the current run */
|
||||
public TextureMap blockTextures;
|
||||
|
||||
/** List of helpers which can identify leaf textures loaded by alternate means */
|
||||
public List<ILeafTextureRecognizer> recognizers = Lists.newLinkedList();
|
||||
|
||||
/** Number of textures generated in the current run */
|
||||
int counter = 0;
|
||||
|
||||
/** Map leaf types to alpha masks */
|
||||
public Map<String, String> maskMappings = Maps.newHashMap();
|
||||
|
||||
public Set<String> getResourceDomains() {
|
||||
return ImmutableSet.<String>of(domainName);
|
||||
}
|
||||
|
||||
public IResource getResource(ResourceLocation resourceLocation) throws IOException {
|
||||
// remove "/blocks/textures/" from beginning
|
||||
String origResPath = resourceLocation.getResourcePath().substring(16);
|
||||
LeafTextureResource result = new LeafTextureResource(new ResourceLocation(origResPath), maskMappings);
|
||||
if (result.data == null) {
|
||||
return Minecraft.getMinecraft().getResourceManager().getResource(missing_resource);
|
||||
} else {
|
||||
counter++;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public List<IResource> getAllResources(ResourceLocation resource) throws IOException {
|
||||
return ImmutableList.<IResource>of();
|
||||
}
|
||||
|
||||
/** Leaf blocks register their textures here. An extra texture will be registered in the atlas
|
||||
* for each, with the resource domain of this generator.
|
||||
* @return the originally registered {@link IIcon} already in the atlas
|
||||
*/
|
||||
public IIcon registerIcon(String resourceLocation) {
|
||||
IIcon original = blockTextures.getTextureExtry(resourceLocation);
|
||||
blockTextures.registerIcon(new ResourceLocation(domainName, resourceLocation).toString());
|
||||
BetterFoliage.log.debug(String.format("Found leaf texture: %s", resourceLocation));
|
||||
return original;
|
||||
}
|
||||
|
||||
/** Iterates through all leaf blocks in the registry and makes them register
|
||||
* their textures to "sniff out" all leaf textures.
|
||||
* @param event
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@SubscribeEvent
|
||||
public void handleTextureReload(TextureStitchEvent.Pre event) {
|
||||
if (event.map.getTextureType() != 0) return;
|
||||
|
||||
blockTextures = event.map;
|
||||
counter = 0;
|
||||
BetterFoliage.log.info("Reloading leaf textures");
|
||||
|
||||
Map<String, IResourceManager> domainManagers = ReflectionUtil.getDomainResourceManagers();
|
||||
if (domainManagers == null) {
|
||||
BetterFoliage.log.warn("Failed to inject leaf texture generator");
|
||||
return;
|
||||
}
|
||||
domainManagers.put(domainName, this);
|
||||
|
||||
// register simple block textures
|
||||
Iterator<Block> iter = Block.blockRegistry.iterator();
|
||||
while(iter.hasNext()) {
|
||||
Block block = iter.next();
|
||||
for (Class<?> clazz : BetterFoliageClient.blockLeavesClasses) if (clazz.isAssignableFrom(block.getClass())) {
|
||||
BetterFoliage.log.debug(String.format("Inspecting leaf block: %s", block.getClass().getName()));
|
||||
block.registerBlockIcons(this);
|
||||
}
|
||||
}
|
||||
|
||||
// enumerate all registered textures, find leaf textures among them
|
||||
Map<String, TextureAtlasSprite> mapAtlas = null;
|
||||
mapAtlas = ReflectionUtil.getField(blockTextures, DeobfNames.TM_MRS_SRG, Map.class);
|
||||
if (mapAtlas == null) mapAtlas = ReflectionUtil.getField(blockTextures, DeobfNames.TM_MRS_MCP, Map.class);
|
||||
if (mapAtlas == null) {
|
||||
BetterFoliage.log.warn("Failed to reflect texture atlas, textures may be missing");
|
||||
} else {
|
||||
Set<String> foundLeafTextures = Sets.newHashSet();
|
||||
for (TextureAtlasSprite icon : mapAtlas.values())
|
||||
for (ILeafTextureRecognizer recognizer : recognizers)
|
||||
if (recognizer.isLeafTexture(icon))
|
||||
foundLeafTextures.add(icon.getIconName());
|
||||
for (String resourceLocation : foundLeafTextures) {
|
||||
BetterFoliage.log.debug(String.format("Found non-block-registered leaf texture: %s", resourceLocation));
|
||||
blockTextures.registerIcon(new ResourceLocation(domainName, resourceLocation).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void endTextureReload(TextureStitchEvent.Post event) {
|
||||
blockTextures = null;
|
||||
if (event.map.getTextureType() == 0) BetterFoliage.log.info(String.format("Generated %d leaf textures", counter));
|
||||
}
|
||||
|
||||
public void loadLeafMappings(File leafMaskFile) {
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(leafMaskFile);
|
||||
props.load(fis);
|
||||
} catch (Exception e) {
|
||||
maskMappings.put("spruce", "fine");
|
||||
maskMappings.put("fir", "fine");
|
||||
maskMappings.put("bamboo", "fine");
|
||||
saveLeafMappings(leafMaskFile);
|
||||
return;
|
||||
}
|
||||
|
||||
for (Map.Entry<Object, Object> entry : props.entrySet()) {
|
||||
maskMappings.put(entry.getKey().toString(), entry.getValue().toString());
|
||||
}
|
||||
BetterFoliage.log.info(String.format("Loaded %d leaf mask mappings", maskMappings.size()));
|
||||
}
|
||||
|
||||
protected void saveLeafMappings(File leafMaskFile) {
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(leafMaskFile);
|
||||
Properties props = new Properties();
|
||||
props.putAll(maskMappings);
|
||||
props.store(fos, "");
|
||||
} catch (Exception e) {
|
||||
BetterFoliage.log.info("Failed to save default leaf mask mappings");
|
||||
return;
|
||||
}
|
||||
BetterFoliage.log.info("Created default leaf mask mappings");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package mods.betterfoliage.client.resource;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import mods.betterfoliage.BetterFoliage;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.IResource;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import net.minecraft.client.resources.data.IMetadataSection;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
/** {@link IResource} containing an autogenerated round crossleaf texture
|
||||
* @author octarine-noise
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class LeafTextureResource implements IResource {
|
||||
|
||||
/** Raw PNG data*/
|
||||
protected byte[] data = null;
|
||||
|
||||
/** Name of the default alpha mask to use */
|
||||
public static String defaultMask = "rough";
|
||||
|
||||
public LeafTextureResource(ResourceLocation resLeaf, Map<String, String> maskMappings) {
|
||||
IResourceManager resourceManager = Minecraft.getMinecraft().getResourceManager();
|
||||
try {
|
||||
// load normal leaf texture
|
||||
ResourceLocation origResource = new ResourceLocation(resLeaf.getResourceDomain(), "textures/blocks/" + resLeaf.getResourcePath());
|
||||
BufferedImage origImage = ImageIO.read(resourceManager.getResource(origResource).getInputStream());
|
||||
if (origImage.getWidth() != origImage.getHeight()) return;
|
||||
int size = origImage.getWidth();
|
||||
|
||||
// load alpha mask of appropriate size
|
||||
String maskType = defaultMask;
|
||||
for(Map.Entry<String, String> entry : maskMappings.entrySet()) if (resLeaf.getResourcePath().contains(entry.getKey())) {
|
||||
maskType = entry.getValue();
|
||||
break;
|
||||
}
|
||||
BufferedImage maskImage = loadLeafMaskImage(maskType, size * 2);
|
||||
int scale = size * 2 / maskImage.getWidth();
|
||||
|
||||
// tile leaf texture 2x2
|
||||
BufferedImage overlayIcon = new BufferedImage(size * 2, size * 2, BufferedImage.TYPE_4BYTE_ABGR);
|
||||
Graphics2D graphics = overlayIcon.createGraphics();
|
||||
graphics.drawImage(origImage, 0, 0, null);
|
||||
graphics.drawImage(origImage, 0, size, null);
|
||||
graphics.drawImage(origImage, size, 0, null);
|
||||
graphics.drawImage(origImage, size, size, null);
|
||||
|
||||
// overlay mask alpha on texture
|
||||
for (int x = 0; x < overlayIcon.getWidth(); x++) {
|
||||
for (int y = 0; y < overlayIcon.getHeight(); y++) {
|
||||
long origPixel = overlayIcon.getRGB(x, y) & 0xFFFFFFFFl;
|
||||
long maskPixel = maskImage.getRGB(x / scale, y / scale) & 0xFF000000l | 0x00FFFFFF;
|
||||
overlayIcon.setRGB(x, y, (int) (origPixel & maskPixel));
|
||||
}
|
||||
}
|
||||
|
||||
// create PNG image
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(overlayIcon, "PNG", baos);
|
||||
data = baos.toByteArray();
|
||||
} catch (Exception e) {
|
||||
BetterFoliage.log.info(String.format("Could not create leaf texture: %s, exception: %s", resLeaf.toString(), e.getClass().getSimpleName()));
|
||||
}
|
||||
}
|
||||
|
||||
/** Loads the alpha mask of the given type and size. If a mask of the exact size can not be found,
|
||||
* will try to load progressively smaller masks down to 16x16
|
||||
* @param type mask type
|
||||
* @param size texture size
|
||||
* @return alpha mask
|
||||
*/
|
||||
protected BufferedImage loadLeafMaskImage(String type, int size) {
|
||||
IResourceManager resourceManager = Minecraft.getMinecraft().getResourceManager();
|
||||
IResource maskResource = null;
|
||||
|
||||
while (maskResource == null && size >= 16) {
|
||||
try {
|
||||
maskResource = resourceManager.getResource(new ResourceLocation(String.format("betterfoliage:textures/blocks/leafmask_%d_%s.png", size, type)));
|
||||
} catch (Exception e) {}
|
||||
size /= 2;
|
||||
}
|
||||
|
||||
try {
|
||||
return maskResource == null ? null : ImageIO.read(maskResource.getInputStream());
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return data != null ? new ByteArrayInputStream(data) : null;
|
||||
}
|
||||
|
||||
public boolean hasMetadata() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public IMetadataSection getMetadata(String var1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user