package loon.opengl.d3d.materials;
import java.util.Comparator;
import java.util.Iterator;
import loon.utils.InsertionSorter;
import loon.utils.TArray;
public class Material implements Iterable<Material.Attribute>,
Comparator<Material.Attribute> {
private final static InsertionSorter<Material.Attribute> sorter = new InsertionSorter<Material.Attribute>();
public static abstract class Attribute {
protected static long register(final String type) {
return Material.register(type);
}
public final long type;
protected Attribute(final long type) {
this.type = type;
}
public abstract Attribute cpy();
protected abstract boolean equals(Attribute other);
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (!(obj instanceof Attribute))
return false;
final Attribute other = (Attribute) obj;
if (other.type != other.type)
return false;
return equals(other);
}
@Override
public String toString() {
return Material.getAttributeAlias(type);
}
}
private final static TArray<String> types = new TArray<String>();
private static int counter = 0;
protected final static long getAttributeType(final String alias) {
for (int i = 0; i < types.size; i++) {
if (types.get(i).compareTo(alias) == 0) {
return 1L << i;
}
}
return 0;
}
protected final static String getAttributeAlias(final long type) {
int idx = -1;
while (type != 0 && ++idx < 63 && (((type >> idx) & 1) == 0))
;
return (idx >= 0 && idx < types.size) ? types.get(idx) : null;
}
protected final static long register(final String alias) {
long result = getAttributeType(alias);
if (result > 0) {
return result;
}
types.add(alias);
return 1L << (types.size - 1);
}
public String id;
protected long mask;
protected final TArray<Attribute> attributes = new TArray<Attribute>();
protected boolean sorted = true;
public Material() {
this("mater" + (++counter));
}
public Material(final String id) {
this.id = id;
}
public Material(final Attribute... attributes) {
this();
set(attributes);
}
public Material(final String id, final Attribute... attributes) {
this(id);
set(attributes);
}
public Material(final TArray<Attribute> attributes) {
this();
set(attributes);
}
public Material(final String id, final TArray<Attribute> attributes) {
this(id);
set(attributes);
}
public Material(final Material copyFrom) {
this(copyFrom.id, copyFrom);
}
public Material(final String id, final Material copyFrom) {
this(id);
for (Attribute attr : copyFrom)
set(attr.cpy());
}
private final void enable(final long mask) {
this.mask |= mask;
}
private final void disable(final long mask) {
this.mask &= -1L ^ mask;
}
public final long getMask() {
return mask;
}
public final boolean has(final long type) {
return type > 0 && (this.mask & type) == type;
}
protected int indexOf(final long type) {
if (has(type)) {
for (int i = 0; i < attributes.size; i++) {
if (attributes.get(i).type == type) {
return i;
}
}
}
return -1;
}
public final void set(final Attribute attribute) {
final int idx = indexOf(attribute.type);
if (idx < 0) {
enable(attribute.type);
attributes.add(attribute);
sorted = false;
} else {
attributes.set(idx, attribute);
}
}
public final void set(final Attribute... attributes) {
for (final Attribute attr : attributes) {
set(attr);
}
}
public final void set(final TArray<Attribute> attributes) {
for (final Attribute attr : attributes)
set(attr);
}
public final void remove(final long mask) {
for (int i = 0; i < attributes.size; i++) {
final long type = attributes.get(i).type;
if ((mask & type) == type) {
attributes.removeIndex(i);
disable(type);
sorted = false;
}
}
}
public final Attribute get(final long type) {
if (has(type)) {
for (int i = 0; i < attributes.size; i++) {
if (attributes.get(i).type == type) {
return attributes.get(i);
}
}
}
return null;
}
public final TArray<Attribute> get(final TArray<Attribute> out,
final long type) {
for (int i = 0; i < attributes.size; i++) {
if ((attributes.get(i).type & type) != 0) {
out.add(attributes.get(i));
}
}
return out;
}
public final void clear() {
mask = 0;
attributes.clear();
}
public int size() {
return attributes.size;
}
public final Material cpy() {
return new Material(this);
}
@Override
public final int compare(final Attribute arg0, final Attribute arg1) {
return (int) (arg0.type - arg1.type);
}
public final void sort() {
if (!sorted) {
sorter.sort(attributes, this);
sorted = true;
}
}
public final boolean same(final Material other) {
return mask == other.mask;
}
public final boolean equals(final Material other) {
if (other == null){
return false;
}
if (other == this){
return true;
}
if (!same(other)){
return false;
}
sort();
other.sort();
for (int i = 0; i < attributes.size; i++) {
if (!attributes.get(i).equals(other.attributes.get(i))) {
return false;
}
}
return true;
}
@Override
public final boolean equals(final Object obj) {
return obj instanceof Material ? equals((Material) obj) : false;
}
@Override
public final Iterator<Attribute> iterator() {
return attributes.iterator();
}
}