/* * Copyright 2013 MovingBlocks * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.terasology.rendering.assets.material; import com.google.common.base.Charsets; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import org.terasology.assets.ResourceUrn; import org.terasology.assets.format.AbstractAssetFileFormat; import org.terasology.assets.format.AssetDataFile; import org.terasology.assets.management.AssetManager; import org.terasology.assets.module.annotations.RegisterAssetFileFormat; import org.terasology.rendering.assets.shader.Shader; import org.terasology.rendering.assets.texture.Texture; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import java.util.Optional; /** */ @RegisterAssetFileFormat public class MaterialFormat extends AbstractAssetFileFormat<MaterialData> { private final Gson gson; private final AssetManager assetManager; public MaterialFormat(AssetManager assetManager) { super("mat"); this.gson = new GsonBuilder().registerTypeAdapter(MaterialMetadata.class, new MaterialMetadataHandler()).create(); this.assetManager = assetManager; } @Override public MaterialData load(ResourceUrn urn, List<AssetDataFile> inputs) throws IOException { MaterialMetadata metadata = gson.fromJson(new InputStreamReader(inputs.get(0).openStream(), Charsets.UTF_8), MaterialMetadata.class); Optional<? extends Shader> shader = assetManager.getAsset(metadata.shader, Shader.class); if (shader.isPresent()) { MaterialData data = new MaterialData(shader.get()); data.setTextureParams(metadata.textures); data.setFloatParams(metadata.floatParams); data.setFloatArrayParams(metadata.floatArrayParams); data.setIntParams(metadata.intParams); return data; } else { throw new IOException("Unable to resolve shader '" + metadata.shader + "'"); } } private static class MaterialMetadata { String shader; Map<String, Texture> textures = Maps.newHashMap(); Map<String, Float> floatParams = Maps.newHashMap(); Map<String, float[]> floatArrayParams = Maps.newHashMap(); Map<String, Integer> intParams = Maps.newHashMap(); } private class MaterialMetadataHandler implements JsonDeserializer<MaterialMetadata> { @Override public MaterialMetadata deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { MaterialMetadata metadata = new MaterialMetadata(); JsonObject obj = json.getAsJsonObject(); if (obj.has("shader")) { metadata.shader = obj.getAsJsonPrimitive("shader").getAsString(); } if (obj.has("params") && obj.get("params").isJsonObject()) { JsonObject params = obj.get("params").getAsJsonObject(); for (Map.Entry<String, JsonElement> prop : params.entrySet()) { if (prop.getValue().isJsonPrimitive()) { if (prop.getValue().getAsJsonPrimitive().isString()) { Optional<? extends Texture> texture = assetManager.getAsset(prop.getValue().getAsString(), Texture.class); if (texture.isPresent()) { metadata.textures.put(prop.getKey(), texture.get()); } } else if (prop.getValue().getAsJsonPrimitive().isNumber()) { metadata.floatParams.put(prop.getKey(), prop.getValue().getAsFloat()); } else if (prop.getValue().getAsJsonPrimitive().isBoolean()) { metadata.intParams.put(prop.getKey(), (prop.getValue().getAsBoolean()) ? 1 : 0); } } else if (prop.getValue().isJsonArray()) { JsonArray array = prop.getValue().getAsJsonArray(); float[] result = new float[array.size()]; boolean valid = true; for (int i = 0; i < array.size(); ++i) { if (!array.get(i).isJsonPrimitive() || !array.get(i).getAsJsonPrimitive().isNumber()) { valid = false; break; } result[i] = array.get(i).getAsFloat(); } if (valid) { metadata.floatArrayParams.put(prop.getKey(), result); } } } } return metadata; } } }