package com.framsticks.model; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import com.framsticks.model.f0.Schema; import com.framsticks.params.ParamsUtil; import com.framsticks.params.annotations.AutoAppendAnnotation; import com.framsticks.params.annotations.FramsClassAnnotation; // import com.framsticks.params.annotations.ParamAnnotation; import com.framsticks.parsers.F0Parser; import com.framsticks.util.AutoBuilder; import com.framsticks.util.FramsticksException; import com.framsticks.util.ResourceBuilder; import com.framsticks.util.lang.Casting; import com.framsticks.util.lang.IterableIterator; import com.framsticks.util.math.Orientation; @FramsClassAnnotation public class ModelBuilder extends ResourceBuilder implements AutoBuilder { Schema schema; final List components = new ArrayList<>(); @Override public Model finish() { if (stream == null && components.isEmpty()) { throw new FramsticksException().msg("model builder instance not ready"); } if (stream != null) { if (schema == null) { schema = Schema.getDefaultSchema(); } F0Parser parser = new F0Parser(schema, stream); components.addAll(ParamsUtil.stripAccess(parser.parse(), ModelComponent.class)); } return build(); } /** * @return the schema */ public Schema getSchema() { return schema; } /** * @param schema the schema to set */ @AutoAppendAnnotation public ModelBuilder schema(Schema schema) { this.schema = schema; return this; } @AutoAppendAnnotation public ModelBuilder addComponent(ModelComponent component) { components.add(component); return this; } @AutoAppendAnnotation public ModelBuilder addComponents(List component) { this.components.addAll(component); return this; } public Model build() { Iterator i = components.iterator(); if (!i.hasNext()) { throw new FramsticksException().msg("empty components list"); } Model f0Genotype = Casting.tryCast(Model.class, i.next()); if (f0Genotype == null) { throw new FramsticksException().msg("first component is not a Model"); } for (ModelComponent component : new IterableIterator(i)) { if (component instanceof Joint) { f0Genotype.joints.add((Joint)component); continue; } if (component instanceof Part) { f0Genotype.parts.add((Part)component); continue; } if (component instanceof NeuroDefinition) { f0Genotype.neuroDefinitions.add((NeuroDefinition) component); continue; } if (component instanceof NeuroConnection) { f0Genotype.neuroConnections.add((NeuroConnection) component); continue; } throw new FramsticksException().msg("invalid class").arg("class", component.getClass().getCanonicalName()); } for (Part p : f0Genotype.getParts()) { p.setOrientation(new Orientation().rotate(p.getRotation())); } for (Joint j : f0Genotype.getJoints()) { /** based on c++ Joint::attachToParts*/ Part p1 = f0Genotype.parts.get(j.part1); Part p2 = f0Genotype.parts.get(j.part2); assert p1 != null && p2 != null; Orientation o = new Orientation().rotate(j.getRotation()); p2.setOrientation(p1.getOrientation().transform(o)); p2.setPosition(p2.getOrientation().transform(j.getDelta()).add(p1.getPosition())); } return f0Genotype; } @Override public List autoFinish() { Model model = finish(); assert schema != null; return Arrays.asList(schema.getRegistry(), model); } }