145 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
package iron.data;
 | 
						|
 | 
						|
import haxe.ds.Vector;
 | 
						|
import iron.data.SceneFormat;
 | 
						|
import iron.data.ShaderData;
 | 
						|
import iron.object.MeshObject;
 | 
						|
 | 
						|
class MaterialData {
 | 
						|
 | 
						|
	static var uidCounter = 0;
 | 
						|
	public var uid: Float;
 | 
						|
	public var name: String;
 | 
						|
	public var raw: TMaterialData;
 | 
						|
	public var shader: ShaderData;
 | 
						|
 | 
						|
	public var contexts: Array<MaterialContext> = null;
 | 
						|
 | 
						|
	public function new(raw: TMaterialData, done: MaterialData->Void, file = "") {
 | 
						|
		uid = ++uidCounter; // Start from 1
 | 
						|
		this.raw = raw;
 | 
						|
		this.name = raw.name;
 | 
						|
 | 
						|
		var ref = raw.shader.split("/");
 | 
						|
		var object_file = "";
 | 
						|
		var data_ref = "";
 | 
						|
		if (ref.length == 2) { // File reference
 | 
						|
			object_file = ref[0];
 | 
						|
			data_ref = ref[1];
 | 
						|
		}
 | 
						|
		else { // Local data
 | 
						|
			object_file = file;
 | 
						|
			data_ref = raw.shader;
 | 
						|
		}
 | 
						|
 | 
						|
		Data.getShader(object_file, data_ref, function(b: ShaderData) {
 | 
						|
			shader = b;
 | 
						|
 | 
						|
			// Contexts have to be in the same order as in raw data for now
 | 
						|
			contexts = [];
 | 
						|
			while (contexts.length < raw.contexts.length) contexts.push(null);
 | 
						|
			var contextsLoaded = 0;
 | 
						|
 | 
						|
			for (i in 0...raw.contexts.length) {
 | 
						|
				var c = raw.contexts[i];
 | 
						|
				new MaterialContext(c, function(self: MaterialContext) {
 | 
						|
					contexts[i] = self;
 | 
						|
					contextsLoaded++;
 | 
						|
					if (contextsLoaded == raw.contexts.length) done(this);
 | 
						|
				});
 | 
						|
			}
 | 
						|
		}, raw.override_context);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function parse(file: String, name: String, done: MaterialData->Void) {
 | 
						|
		Data.getSceneRaw(file, function(format: TSceneFormat) {
 | 
						|
			var raw: TMaterialData = Data.getMaterialRawByName(format.material_datas, name);
 | 
						|
			if (raw == null) {
 | 
						|
				trace('Material data "$name" not found!');
 | 
						|
				done(null);
 | 
						|
			}
 | 
						|
			new MaterialData(raw, done, file);
 | 
						|
		});
 | 
						|
	}
 | 
						|
 | 
						|
	public function getContext(name: String): MaterialContext {
 | 
						|
		for (c in contexts) {
 | 
						|
			// 'mesh' will fetch both 'mesh' and 'meshheight' contexts
 | 
						|
			if (c.raw.name.substr(0, name.length) == name) return c;
 | 
						|
		}
 | 
						|
		return null;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
class MaterialContext {
 | 
						|
	public var raw: TMaterialContext;
 | 
						|
	public var textures: Vector<kha.Image> = null;
 | 
						|
	public var id = 0;
 | 
						|
	static var num = 0;
 | 
						|
 | 
						|
	public function new(raw: TMaterialContext, done: MaterialContext->Void) {
 | 
						|
		this.raw = raw;
 | 
						|
		id = num++;
 | 
						|
 | 
						|
		if (raw.bind_textures != null && raw.bind_textures.length > 0) {
 | 
						|
 | 
						|
			textures = new Vector(raw.bind_textures.length);
 | 
						|
			var texturesLoaded = 0;
 | 
						|
 | 
						|
			for (i in 0...raw.bind_textures.length) {
 | 
						|
				var tex = raw.bind_textures[i];
 | 
						|
 | 
						|
				if (tex.file == "" || tex.source == "movie") { // Empty texture
 | 
						|
					texturesLoaded++;
 | 
						|
					if (texturesLoaded == raw.bind_textures.length) done(this);
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
 | 
						|
				Data.getImage(tex.file, function(image: kha.Image) {
 | 
						|
					textures[i] = image;
 | 
						|
					texturesLoaded++;
 | 
						|
 | 
						|
					// Set mipmaps
 | 
						|
					if (tex.mipmaps != null) {
 | 
						|
						var mipmaps: Array<kha.Image> = [];
 | 
						|
						while (mipmaps.length < tex.mipmaps.length) mipmaps.push(null);
 | 
						|
						var mipmapsLoaded = 0;
 | 
						|
 | 
						|
						for (j in 0...tex.mipmaps.length) {
 | 
						|
							var name = tex.mipmaps[j];
 | 
						|
 | 
						|
							Data.getImage(name, function(mipimg: kha.Image) {
 | 
						|
								mipmaps[j] = mipimg;
 | 
						|
								mipmapsLoaded++;
 | 
						|
 | 
						|
								if (mipmapsLoaded == tex.mipmaps.length) {
 | 
						|
									image.setMipmaps(mipmaps);
 | 
						|
									tex.mipmaps = null;
 | 
						|
									tex.generate_mipmaps = false;
 | 
						|
 | 
						|
									if (texturesLoaded == raw.bind_textures.length) done(this);
 | 
						|
								}
 | 
						|
							});
 | 
						|
						}
 | 
						|
					}
 | 
						|
					else if (tex.generate_mipmaps == true && image != null) {
 | 
						|
						image.generateMipmaps(1000);
 | 
						|
						tex.mipmaps = null;
 | 
						|
						tex.generate_mipmaps = false;
 | 
						|
 | 
						|
						if (texturesLoaded == raw.bind_textures.length) done(this);
 | 
						|
					}
 | 
						|
					else if (texturesLoaded == raw.bind_textures.length) done(this);
 | 
						|
 | 
						|
				}, false, tex.format != null ? tex.format : "RGBA32");
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else done(this);
 | 
						|
	}
 | 
						|
 | 
						|
	public function setTextureParameters(g: kha.graphics4.Graphics, textureIndex: Int, context: ShaderContext, unitIndex: Int) {
 | 
						|
		// This function is called by MeshObject for samplers set using material context
 | 
						|
		context.setTextureParameters(g, unitIndex, raw.bind_textures[textureIndex]);
 | 
						|
	}
 | 
						|
}
 |