package speiger.src.coreengine.math.misc; import java.util.EnumSet; import java.util.Iterator; import java.util.Set; import java.util.StringJoiner; import java.util.function.Predicate; import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectList; import speiger.src.coreengine.math.MathUtils; import speiger.src.coreengine.math.misc.Facing.Axis; import speiger.src.coreengine.math.vector.ints.Vec2i; public final class FacingList implements Iterable, Predicate { static final FacingList[] FACINGS = createArray(); public static final FacingList EMPTY = ofNumber(0); public static final FacingList NORTH = ofFacings(Facing.NORTH); public static final FacingList EAST = ofFacings(Facing.EAST); public static final FacingList SOUTH = ofFacings(Facing.SOUTH); public static final FacingList WEST = ofFacings(Facing.WEST); public static final FacingList NORTH_EAST = ofFacings(Facing.NORTH, Facing.EAST); public static final FacingList SOUTH_EAST = ofFacings(Facing.EAST, Facing.SOUTH); public static final FacingList SOUTH_WEST = ofFacings(Facing.SOUTH, Facing.WEST); public static final FacingList NORTH_WEST = ofFacings(Facing.WEST, Facing.NORTH); public static final FacingList VERTICAL = ofFacings(Facing.NORTH, Facing.SOUTH); public static final FacingList HORIZONTAL = ofFacings(Facing.EAST, Facing.WEST); public static final FacingList ALL = ofFacings(Facing.NORTH, Facing.SOUTH, Facing.EAST, Facing.WEST); final byte code; final byte next; final byte opposite; final byte prev; final byte count; final Vec2i offset; final Facing[] array; private FacingList(int initCode) { code = (byte)MathUtils.clamp(0, 15, initCode); Vec2i pos = Vec2i.newMutable(); ObjectList facings = new ObjectArrayList(); for(int i = 0;i<4;i++) { if((code & 1 << i) != 0) { pos.add(Facing.byIndex(i).getOffset()); facings.add(Facing.byIndex(i)); } } int[] data = new int[3]; for(int i = 0,m=facings.size();i toFacings() { return isEmpty() ? EnumSet.noneOf(Facing.class) : EnumSet.copyOf(ObjectArrayList.wrap(array)); } public boolean[] toFlags() { return toFlags(array); } public int getRotation() { switch(count) { case 1: return array[0].getRotation(); case 2: return array[0].getRotation(array[1]); default: return 0; } } public FacingList rotate(int amount) { switch(amount & 3) { case 1: return FACINGS[next]; case 2: return FACINGS[opposite]; case 3: return FACINGS[prev]; default: return this; } } public FacingList invert() { return FACINGS[15 - code]; } public FacingList opposite() { return FACINGS[opposite]; } public FacingList add(Facing facing) { return FACINGS[code | (1 << facing.getIndex())]; } public FacingList add(FacingList facings) { return FACINGS[code | facings.code]; } public FacingList remove(Facing facing) { return FACINGS[code & ~(1 << facing.getIndex())]; } public FacingList remove(FacingList facings) { return FACINGS[code & ~facings.code]; } public boolean contains(Facing direction) { return (code & 1 << direction.getIndex()) != 0; } public boolean contains(FacingList facings) { return (code & facings.code) == facings.code; } public boolean containsAny(FacingList facings) { return (code & facings.code) != 0; } public boolean notContains(Facing direction) { return (code & 1 << direction.getIndex()) == 0; } public boolean notContains(FacingList facings) { return (code & facings.code) != facings.code; } public FacingList flipFacing(Facing facing) { return contains(facing) ? remove(facing).add(facing.opposite()) : this; } public FacingList flipAxis(Axis axis) { FacingList result = this; for(int i = 0,m=array.length;i iterator() { return new Iterator(){ int index = 0; @Override public boolean hasNext() { return index < size(); } @Override public Facing next() { return array[index++]; } }; } public static int toNumber(Facing...facings) { int value = 0; for(int i = 0,m=facings.length;i