private void ImportOperation(SplineOperationBuilder splineOperationBuilder, List <OperationRecipe> operations, DsonTypes.DsonDocument doc, DsonTypes.Operation operation) { if (operation.op == DsonTypes.Operator.Push) { if (operation.url != null) { splineOperationBuilder.ConfirmInactive(); string channelRef = ConvertChannelUri(doc, operation.url); operations.Add(OperationRecipe.MakePushChannel(channelRef)); } else { Object val = operation.val; switch (val) { case JArray arrayValue: float[] values = arrayValue.ToObject <float[]>(); splineOperationBuilder.AddValueArray(values); break; default: if (splineOperationBuilder.Active) { splineOperationBuilder.AddSize(Convert.ToInt32(operation.val)); } else { float value = Convert.ToSingle(operation.val); operations.Add(OperationRecipe.MakePushConstant(value)); } break; } } } else if (operation.op == DsonTypes.Operator.Add) { splineOperationBuilder.ConfirmInactive(); operations.Add(OperationRecipe.Make(OperationRecipe.OperationKind.Add)); } else if (operation.op == DsonTypes.Operator.Sub) { splineOperationBuilder.ConfirmInactive(); operations.Add(OperationRecipe.Make(OperationRecipe.OperationKind.Sub)); } else if (operation.op == DsonTypes.Operator.Mult) { splineOperationBuilder.ConfirmInactive(); operations.Add(OperationRecipe.Make(OperationRecipe.OperationKind.Mul)); } else if (operation.op == DsonTypes.Operator.Div) { splineOperationBuilder.ConfirmInactive(); operations.Add(OperationRecipe.Make(OperationRecipe.OperationKind.Div)); } else if (operation.op == DsonTypes.Operator.SplineTcb) { operations.Add(splineOperationBuilder.Build()); } }
public OperationRecipe Build() { if (this.size < 0) { throw new InvalidOperationException("missing size"); } Spline spline = new Spline(knots.ToArray()); OperationRecipe operation = OperationRecipe.MakeEvalSpline(spline); Reset(); return(operation); }
public FormulaRecipe SynthesizeFormula() { var rootBoneScaleChannelName = bones[0].Name + "?scale/general"; return(new FormulaRecipe { Output = rootBoneScaleChannelName, Stage = FormulaRecipe.FormulaStage.Multiply, Operations = new List <OperationRecipe> { OperationRecipe.MakePushChannel(ChannelName), OperationRecipe.MakePushConstant(1), OperationRecipe.Make(OperationRecipe.OperationKind.Add) } }); }
private List <MorphRecipe> MergeMorphs(List <FormulaRecipe> mergedFormulas) { var parentMorphsByName = parent.Morphs.ToDictionary(morph => morph.Channel, morph => morph); var childMorphsByName = children.Select(child => child.Morphs.ToDictionary(morph => morph.Channel, morph => morph)).ToList(); var allMorphNames = parentMorphsByName.Keys.Concat(childMorphsByName.SelectMany(dict => dict.Keys)).Distinct().ToList(); var childAutomorphers = children.Select(child => child.Automorpher).ToArray(); List <MorphRecipe> mergedMorphs = new List <MorphRecipe>(); foreach (string morphName in allMorphNames) { parentMorphsByName.TryGetValue(morphName, out var parentMorph); var childMorphs = new MorphRecipe[childMorphsByName.Count]; for (int childIdx = 0; childIdx < childMorphsByName.Count; ++childIdx) { childMorphsByName[childIdx].TryGetValue(morphName, out childMorphs[childIdx]); } var mergedMorph = MorphRecipe.Merge(morphName, reindexer, parentMorph, childMorphs, childAutomorphers); mergedMorphs.Add(mergedMorph); } for (int childIdx = 0; childIdx < children.Length; ++childIdx) { var child = children[childIdx]; int childVertexOffset = reindexer.ChildOffsets[childIdx].Vertex; string childControlChannel = childControlChannels[childIdx].Name; //Add a morph that moves each child vertex from the parent surface to its active position mergedMorphs.Add(child.Automorpher.GenerateGraftControlMorph(childControlChannel, childVertexOffset, child.Geometry)); //Add a formula that disables each child morph when when the child control channel is 0 foreach (var childMorph in child.Morphs) { if (parentMorphsByName.ContainsKey(childMorph.Channel)) { /* * Skip child morphs that are following a parent morph. * * In principle, I should disable these to and replace them with automorpher-generated * morphs. But in practice, these morphs are already very similar to the automorphs so it's * OK to leave them as is. */ continue; } mergedFormulas.Add(new FormulaRecipe { Output = childMorph.Channel, Stage = FormulaRecipe.FormulaStage.Multiply, Operations = new List <OperationRecipe> { OperationRecipe.MakePushChannel(childControlChannel) } }); } } return(mergedMorphs); }