public void OnEnable() { dnaRange = target as DNARangeAsset; if (dnaRange.dnaConverter != null) { dnaSource = dnaRange.dnaConverter.DNAType.GetConstructor(System.Type.EmptyTypes).Invoke(null) as UMADnaBase; if (dnaSource != null) entryCount = dnaSource.Count; } }
public IDNAConverter GetConverter(UMADnaBase DNA) { /*foreach (DnaConverterBehaviour dcb in _dnaConverterList) * { * if (dcb.DNATypeHash == DNA.DNATypeHash) * return dcb; * }*/ for (int i = 0; i < _dnaConverterList.Count; i++) { if (_dnaConverterList[i].DNATypeHash == DNA.DNATypeHash) { return(_dnaConverterList[i]); } } return(null); }
public float GetUmaDNAValue(string DNATypeName, UMADnaBase umaDnaIn) { if (umaDnaIn == null) { return(0.5f); } DynamicUMADnaBase umaDna = (DynamicUMADnaBase)umaDnaIn; float val = 0.5f; if (DNATypeName == "None" || umaDna == null) { return(val); } val = umaDna.GetValue(DNATypeName, true); //implimented a 'failSilently' option here because recipes may have dna in that the dna asset no longer has return(val); }
//TODO methods for screwing with the reducer dnas? Better if we can use fancy properties with indexers public void ApplyDNA(UMAData umaData, UMASkeleton skeleton, UMADnaBase activeDNA, float masterWeight = 1f) { _liveShapeWeight = _startingShapeWeight; //dna weight superceeds startingWeight if it exists if (_modifyingDNA.UsedDNANames.Count > 0) { _liveShapeWeight = _modifyingDNA.Evaluate(activeDNA); } _liveShapeWeight = _liveShapeWeight * masterWeight; //In Unity 2018.3+ blendshapes can have negative values too, so in that case allow the value to go to -1 #if !UNITY_2018_3_OR_NEWER _liveShapeWeight = Mathf.Clamp(_liveShapeWeight, 0f, 1f); #endif umaData.SetBlendShape(_blendshapeToApply, _liveShapeWeight); }
public void ApplyDNA(UMAData umaData, UMASkeleton skeleton, UMADnaBase activeDNA, float masterWeight = 1f) { if (_poseToApply == null) { if (Debug.isDebugBuild) { Debug.LogWarning(umaData.gameObject.name + " had an invalid or empty pose set in its BonePoseDNAConverters in its DNAConverterController"); } return; } _livePoseWeight = _startingPoseWeight; //dna weight superceeds startingWeight if it exists if (_modifyingDNA.UsedDNANames.Count > 0) { _livePoseWeight = _modifyingDNA.Evaluate(activeDNA); } _livePoseWeight = _livePoseWeight * masterWeight; _livePoseWeight = Mathf.Clamp(_livePoseWeight, 0f, 1f); _poseToApply.ApplyPose(skeleton, _livePoseWeight); }
/// <summary> /// Uniformly randomizes each value in the DNA. /// </summary> /// <param name="data">UMA data.</param> public void RandomizeDNA(UMAData data) { if (dnaConverter == null) { return; } UMADnaBase dna = data.GetDna(dnaConverter.DNATypeHash); if (dna == null) { return; } int entryCount = dna.Count; for (int i = 0; i < means.Length; i++) { dna.SetValue(i, means[i] + (Random.value - 0.5f) * spreads[i]); } }
/// <summary> /// Finds the set dna name in the supplied dna list and applies the evaluator and multiplier to it. /// Tip: if you are already looping through the dna to find the name/value just use Evaluate(float dnaValue) instead for efficiency /// </summary> /// <param name="dna">The dna to search</param> /// <returns>The evaluated value</returns> public float Evaluate(UMADnaBase dna) { //using lastIndex building dna takes apprx 00:00:00.0027695 //Using lastIndex modifying dna takes apprx 00:00:00.0004993 //notusing lastIndex building dna takes apprx 00:00:00.0035695 //notusing lastIndex modifying dna takes apprx 00:00:00.0008447 //using lastIndex is about 1/3 faster at the cost of being less robust because the dnaNames could in theory be changed at runtime and lastIndex would then fail //could make the difference between being able to use things like color dna for wrinkle maps etc? if (_lastIndex != -1) { return(Evaluate(dna.GetValue(_lastIndex))); } else { _lastIndex = System.Array.IndexOf(dna.Names, _dnaName); if (_lastIndex > -1) { return(Evaluate(dna.GetValue(_lastIndex))); } } return(defaultDNAValue); }
/// <summary> /// Uniformly randomizes each value in the DNA. /// </summary> /// <param name="data">UMA data.</param> public void RandomizeDNA(UMAData data) { if (dnaConverter == null) { return; } UMADnaBase dna = data.GetDna(dnaConverter.DNATypeHash); if (dna == null) { return; } int entryCount = dna.Count; if (means.Length != entryCount) { if (Debug.isDebugBuild) { Debug.LogWarning("Range settings out of sync with DNA, cannot apply!"); } return; } if ((values == null) || (values.Length != entryCount)) { values = new float[entryCount]; } for (int i = 0; i < entryCount; i++) { values[i] = means[i] + (Random.value - 0.5f) * spreads[i]; } dna.Values = values; }
/// <summary> /// Randomizes each value in the DNA using a Gaussian distribution. /// </summary> /// <param name="data">UMA data.</param> public void RandomizeDNAGaussian(UMAData data) { if (dnaConverter == null) { return; } UMADnaBase dna = data.GetDna(dnaConverter.DNATypeHash); if (dna == null) { return; } int entryCount = dna.Count; if (means.Length != entryCount) { if (Debug.isDebugBuild) { Debug.LogWarning("Range settings out of sync with DNA, cannot apply!"); } return; } if (values == null) { values = new float[entryCount]; } for (int i = 0; i < entryCount; i++) { values[i] = UMAUtils.GaussianRandom(means[i], deviations[i]); } dna.Values = values; }
//TODO check if this still screws up the incoming dnas values public UMADnaBase GetWeightedDNA(UMADnaBase incomingDna) { if (_masterWeightType == MasterWeightType.UseGlobalValue) { return(incomingDna); } var masterWeight = GetWeight(incomingDna); var weightedDNA = new DynamicUMADna(); if (masterWeight > 0) { weightedDNA._names = new string[incomingDna.Names.Length]; Array.Copy(incomingDna.Names, weightedDNA._names, incomingDna.Names.Length); weightedDNA._values = new float[incomingDna.Values.Length]; Array.Copy(incomingDna.Values, weightedDNA._values, incomingDna.Values.Length); for (int i = 0; i < incomingDna.Count; i++) { weightedDNA.SetValue(i, weightedDNA.GetValue(i) * masterWeight); } } return(weightedDNA); }
/// <summary> /// Calls ApplyDNA on all this convertersControllers plugins (aka converters) that apply dna during the pre-pass /// </summary> /// <param name="umaData">The umaData on the avatar</param> /// <param name="skeleton">The avatars skeleton</param> /// <param name="dnaTypeHash">The dnaTypeHash that this converters behaviour is using</param> public void ApplyDNAPrepass(UMAData umaData, UMASkeleton skeleton) { if (!_prepared) { Prepare(); } UMADnaBase umaDna = umaData.GetDna(DNATypeHash); //Make the DNAAssets match if they dont already, can happen when some parts are in bundles and others arent if (((DynamicUMADnaBase)umaDna).dnaAsset != DNAAsset && DNAAsset != null) { ((DynamicUMADnaBase)umaDna).dnaAsset = DNAAsset; } if (_applyDNAPrepassPlugins.Count > 0) { for (int i = 0; i < _applyDNAPrepassPlugins.Count; i++) { _applyDNAPrepassPlugins[i].ApplyDNA(umaData, skeleton, DNATypeHash); } } }
/// <summary> /// Convert a recipes UMADnaHumanoid values to DynamicUMADna values. This will need to be done if the user switches a races converter from a HumanoidDNAConverterBehaviour to a DynamicDNAConverterBehaviour /// </summary> /// <param name="umaDna"></param> public override int ImportUMADnaValues(UMADnaBase umaDna) { int dnaImported = 0; string[] dnaNames = umaDna.Names; for (int i = 0; i < umaDna.Count; i++) { var thisValueName = dnaNames[i]; for (int ii = 0; ii < Names.Length; ii++) { //if (Names[ii].Equals(thisValueName, StringComparison.OrdinalIgnoreCase)) //actually I think they should be exactly equal if (Names[ii] == thisValueName) { Values[ii] = umaDna.Values[i]; dnaImported++; } } } return(dnaImported); }
public void ApplyDNA(UMAData data, UMASkeleton skeleton) { UMADnaBase activeDNA = data.GetDna(this.dnaTypeHash); if (activeDNA == null) { Debug.LogError("Could not get DNA values for: " + this.name); return; } if (startingPose != null) { startingPose.ApplyPose(skeleton, 1f); } if (activeDNA.Count == dnaPoses.Length) { float[] dnaValues = activeDNA.Values; for (int i = 0; i < dnaValues.Length; i++) { float dnaValue = dnaValues[i]; if ((dnaValue > 0.5f) && (dnaPoses[i].poseOne != null)) { float poseWeight = (dnaValue - 0.5f) * 2f; dnaPoses[i].poseOne.ApplyPose(skeleton, poseWeight); } else if ((dnaValue < 0.5f) && (dnaPoses[i].poseZero != null)) { float poseWeight = (0.5f - dnaValue) * 2f; dnaPoses[i].poseOne.ApplyPose(skeleton, poseWeight); } } } else { Debug.LogWarning("DNA length mismatch, trying names. This is SLOW!"); string[] dnaNames = activeDNA.Names; for (int i = 0; i < dnaPoses.Length; i++) { if ((dnaPoses[i].dnaEntryName == null) || (dnaPoses[i].dnaEntryName.Length == 0)) { continue; } int dnaIndex = System.Array.IndexOf(dnaNames, dnaPoses[i].dnaEntryName); if (dnaIndex < 0) { continue; } float dnaValue = activeDNA.GetValue(dnaIndex); if ((dnaValue > 0.5f) && (dnaPoses[i].poseOne != null)) { float poseWeight = (dnaValue - 0.5f) * 2f; dnaPoses[i].poseOne.ApplyPose(skeleton, poseWeight); } else if ((dnaValue < 0.5f) && (dnaPoses[i].poseZero != null)) { float poseWeight = (0.5f - dnaValue) * 2f; dnaPoses[i].poseOne.ApplyPose(skeleton, poseWeight); } } } }
public abstract int ImportUMADnaValues(UMADnaBase umaDna);
public override void ApplyDNA(UMAData umaData, UMASkeleton skeleton, int dnaTypeHash) { //Add the reset listeners if we havent already //we need this because if 'fastGeneration' is false we may still get another loop //and we should not do this again if _dnaAppliedTo contains umaData.gameObject if (!_listenersAddedTo.Contains(umaData.gameObject)) { umaData.CharacterUpdated.AddListener(ResetOnCharaterUpdated); _listenersAddedTo.Add(umaData.gameObject); } if (_dnaAppliedTo.Contains(umaData.gameObject)) { return; } UMADnaBase activeDNA = umaData.GetDna(dnaTypeHash); if (activeDNA == null) { Debug.LogError("Could not get DNA values for: " + this.name); return; } var masterWeightCalc = masterWeight.GetWeight(activeDNA); if (masterWeightCalc == 0f) { return; } bool needsUpdate = false; for (int i = 0; i < _colorSets.Length; i++) { if (_colorSets[i].modifyingDNA.UsedDNANames.Count == 0 || string.IsNullOrEmpty(_colorSets[i].targetName)) { continue; } var targetOverlays = new List <OverlayData>(); for (int si = 0; si < umaData.umaRecipe.slotDataList.Length; si++) { var overlays = umaData.umaRecipe.slotDataList[si].GetOverlayList(); for (int oi = 0; oi < overlays.Count; oi++) { if (overlays[oi] != null) { //we can target specific Overlays or SharedColors now if ((overlays[oi].colorData.IsASharedColor && overlays[oi].colorData.name == _colorSets[i].targetName) || overlays[oi].overlayName == _colorSets[i].targetName) { if (!targetOverlays.Contains(overlays[oi])) { targetOverlays.Add(overlays[oi]); } } } } } if (targetOverlays.Count == 0) { continue; } if (_colorSets[i].EvaluateAndApplyAdjustments(activeDNA, masterWeightCalc, targetOverlays)) { needsUpdate = true; } } if (needsUpdate) { umaData.isTextureDirty = true; umaData.isAtlasDirty = true; } _dnaAppliedTo.Add(umaData.gameObject); }
public void ApplyDNA(UMAData data, UMASkeleton skeleton) { if (morphSet == null) { if (Debug.isDebugBuild) { Debug.LogError("Missing morph set asset for: " + this.name); } return; } UMADnaBase activeDNA = data.GetDna(this.dnaTypeHash); if (activeDNA == null) { if (Debug.isDebugBuild) { Debug.LogError("Could not get DNA values for: " + this.name); } return; } if (morphSet.startingPose != null) { morphSet.startingPose.ApplyPose(skeleton, 1f); } if (!String.IsNullOrEmpty(morphSet.startingBlendShape)) { data.SetBlendShape(morphSet.startingBlendShape, 1f); } if (activeDNA.Count == morphSet.dnaMorphs.Length) { float[] dnaValues = activeDNA.Values; for (int i = 0; i < dnaValues.Length; i++) { float dnaValue = dnaValues[i]; MorphSetDnaAsset.DNAMorphSet morph = morphSet.dnaMorphs[i]; ApplyMorph(dnaValue, data, skeleton, morph); } } else { if (Debug.isDebugBuild) { Debug.LogWarning("DNA length mismatch, trying names. This is SLOW!"); } string[] dnaNames = activeDNA.Names; for (int i = 0; i < morphSet.dnaMorphs.Length; i++) { if (String.IsNullOrEmpty(morphSet.dnaMorphs[i].dnaEntryName)) { continue; } int dnaIndex = System.Array.IndexOf(dnaNames, morphSet.dnaMorphs[i].dnaEntryName); if (dnaIndex < 0) { continue; } float dnaValue = activeDNA.GetValue(dnaIndex); MorphSetDnaAsset.DNAMorphSet morph = morphSet.dnaMorphs[i]; ApplyMorph(dnaValue, data, skeleton, morph); } } }
public float CalculateValue(UMADnaBase umaDNA) { float thisVal = value; float modifierVal = 0; float tempModifierVal = 0; string dnaCombineMethod = ""; bool inModifierPair = false; if (modifiers.Count > 0) { for (int i = 0; i < modifiers.Count; i++) { if (modifiers[i].DNATypeName != "None" && (modifiers[i].modifier == spValModifier.spValModifierType.AddDNA || modifiers[i].modifier == spValModifier.spValModifierType.DivideDNA || modifiers[i].modifier == spValModifier.spValModifierType.MultiplyDNA || modifiers[i].modifier == spValModifier.spValModifierType.SubtractDNA)) { tempModifierVal = GetUmaDNAValue(modifiers[i].DNATypeName, umaDNA); tempModifierVal -= 0.5f; inModifierPair = true; if (modifiers[i].modifier == spValModifier.spValModifierType.AddDNA) { dnaCombineMethod = "Add"; } else if (modifiers[i].modifier == spValModifier.spValModifierType.DivideDNA) { dnaCombineMethod = "Divide"; } else if (modifiers[i].modifier == spValModifier.spValModifierType.MultiplyDNA) { dnaCombineMethod = "Multiply"; } else if (modifiers[i].modifier == spValModifier.spValModifierType.SubtractDNA) { dnaCombineMethod = "Subtract"; } } else { if (modifiers[i].modifier == spValModifier.spValModifierType.Add) { modifierVal += (tempModifierVal + modifiers[i].modifierValue); tempModifierVal = 0; inModifierPair = false; } else if (modifiers[i].modifier == spValModifier.spValModifierType.Divide) { modifierVal += (tempModifierVal / modifiers[i].modifierValue); tempModifierVal = 0; inModifierPair = false; } else if (modifiers[i].modifier == spValModifier.spValModifierType.Multiply) { modifierVal += (tempModifierVal * modifiers[i].modifierValue); tempModifierVal = 0; inModifierPair = false; } else if (modifiers[i].modifier == spValModifier.spValModifierType.Subtract) { modifierVal += (tempModifierVal - modifiers[i].modifierValue); tempModifierVal = 0; inModifierPair = false; } } if (modifierVal != 0 && inModifierPair == false) { if (dnaCombineMethod == "Add") { thisVal += modifierVal; } if (dnaCombineMethod == "Subtract") { thisVal -= modifierVal; } if (dnaCombineMethod == "Multiply") { thisVal *= modifierVal; } if (dnaCombineMethod == "Divide") { thisVal /= modifierVal; } modifierVal = 0; dnaCombineMethod = ""; } } //in the case of left/Right(Up)LegAdjust the umadna is subtracted from the result without being multiplied by anything //this accounts for the scenario where umaDna is left trailing with no correcponding add/subtract/multiply/divide multiplier if (tempModifierVal != 0 && inModifierPair != false) { if (dnaCombineMethod == "Add") { thisVal += tempModifierVal; } if (dnaCombineMethod == "Subtract") { thisVal -= tempModifierVal; } if (dnaCombineMethod == "Multiply") { thisVal *= tempModifierVal; } if (dnaCombineMethod == "Divide") { thisVal /= tempModifierVal; } dnaCombineMethod = ""; modifierVal = 0; tempModifierVal = 0; inModifierPair = false; } } return(thisVal); }
public void AddDna(UMADnaBase dna) { umaDna.Add(dna.GetType(), dna); }
public override void OnInspectorGUI() { bool dirty = false; DnaConverterBehaviour newSource = EditorGUILayout.ObjectField("DNA Converter", dnaRange.dnaConverter, typeof(DnaConverterBehaviour), true) as DnaConverterBehaviour; if (newSource != dnaRange.dnaConverter) { dnaRange.dnaConverter = newSource; dnaSource = null; if (dnaRange.dnaConverter != null) { dnaSource = dnaRange.dnaConverter.DNAType.GetConstructor(System.Type.EmptyTypes).Invoke(null) as UMADnaBase; } if (dnaSource == null) { entryCount = 0; } else { entryCount = dnaSource.Count; } dnaRange.means = new float[entryCount]; dnaRange.deviations = new float[entryCount]; dnaRange.spreads = new float[entryCount]; for (int i = 0; i < entryCount; i++) { dnaRange.means[i] = 0.5f; dnaRange.deviations[i] = 0.16f; dnaRange.spreads[i] = 0.5f; } dirty = true; } GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); if (dnaRange.dnaConverter != null) { GUILayout.Space(2f); GUIStyle headerStyle = new GUIStyle(); headerStyle.alignment = TextAnchor.MiddleCenter; headerStyle.normal.textColor = Color.white; headerStyle.fontSize = 12; EditorGUILayout.LabelField(dnaRange.dnaConverter.DNAType.Name, headerStyle); string[] dnaNames = dnaSource.Names; for (int i = 0; i < entryCount; i++) { float currentMin = dnaRange.means[i] - dnaRange.spreads[i]; float currentMax = dnaRange.means[i] + dnaRange.spreads[i]; float min = currentMin; float max = currentMax; EditorGUILayout.PrefixLabel(dnaNames[i]); EditorGUILayout.MinMaxSlider(ref min, ref max, 0f, 1f); if ((min != currentMin) || (max != currentMax)) { dnaRange.means[i] = (min + max) / 2f; dnaRange.spreads[i] = (max - min) / 2f; dnaRange.deviations[i] = dnaRange.spreads[i] / 3f; dirty = true; } } } if (dirty) { EditorUtility.SetDirty(dnaRange); AssetDatabase.SaveAssets(); } }
public bool EvaluateAndApplyAdjustments(UMADnaBase activeDNA, float masterWeight, List <OverlayData> targetOverlays) { var dnaVal = modifyingDNA.Evaluate(activeDNA); float rAdj = 0f; float gAdj = 0f; float bAdj = 0f; float aAdj = 0f; float rCurr = 0f; float gCurr = 0f; float bCurr = 0f; float aCurr = 0f; OverlayColorData ocd; for (int oi = 0; oi < targetOverlays.Count; oi++) { ocd = targetOverlays[oi].colorData; if (colorModifier.R.enable) { rCurr = colorModifier.R.Additive ? ocd.channelAdditiveMask[textureChannel].r : ocd.channelMask[textureChannel].r; rAdj = colorModifier.R.EvaluateAdjustment(dnaVal, rCurr); if (colorModifier.R.Absolute) { rAdj = Mathf.Lerp(rCurr, rAdj, masterWeight); } else { rAdj = rAdj * masterWeight; } if ((colorModifier.R.Absolute && rAdj != 0) || (!colorModifier.R.Absolute && rAdj != rCurr)) { targetOverlays[oi].colorComponentAdjusters.Add(new OverlayData.ColorComponentAdjuster(textureChannel, 0, rAdj, colorModifier.R.adjustmentType)); } } if (colorModifier.G.enable) { gCurr = colorModifier.G.Additive ? ocd.channelAdditiveMask[textureChannel].g : ocd.channelMask[textureChannel].g; gAdj = colorModifier.G.EvaluateAdjustment(dnaVal, gCurr); if (colorModifier.G.Absolute) { gAdj = Mathf.Lerp(gCurr, gAdj, masterWeight); } else { gAdj = gAdj * masterWeight; } if ((colorModifier.G.Absolute && gAdj != 0) || (!colorModifier.G.Absolute && gAdj != gCurr)) { targetOverlays[oi].colorComponentAdjusters.Add(new OverlayData.ColorComponentAdjuster(textureChannel, 1, gAdj, colorModifier.G.adjustmentType)); } } if (colorModifier.B.enable) { bCurr = colorModifier.B.Additive ? ocd.channelAdditiveMask[textureChannel].b : ocd.channelMask[textureChannel].b; bAdj = colorModifier.B.EvaluateAdjustment(dnaVal, bCurr); if (colorModifier.B.Absolute) { bAdj = Mathf.Lerp(bCurr, bAdj, masterWeight); } else { bAdj = bAdj * masterWeight; } if ((colorModifier.B.Absolute && bAdj != 0) || (!colorModifier.B.Absolute && bAdj != bCurr)) { targetOverlays[oi].colorComponentAdjusters.Add(new OverlayData.ColorComponentAdjuster(textureChannel, 2, bAdj, colorModifier.B.adjustmentType)); } } if (colorModifier.A.enable) { aCurr = colorModifier.A.Additive ? ocd.channelAdditiveMask[textureChannel].a : ocd.channelMask[textureChannel].a; aAdj = colorModifier.A.EvaluateAdjustment(dnaVal, aCurr); if (colorModifier.A.Absolute) { aAdj = Mathf.Lerp(aCurr, aAdj, masterWeight); } else if (colorModifier.A.adjustmentType == AdjustmentType.BlendFactor) //BlendFactor is different and only used on the alpha channel { aAdj = Mathf.Lerp(aCurr, aAdj * masterWeight, masterWeight); } else { aAdj = aAdj * masterWeight; } if ((colorModifier.A.Absolute && aAdj != 0) || (!colorModifier.A.Absolute && aAdj != aCurr)) { targetOverlays[oi].colorComponentAdjusters.Add(new OverlayData.ColorComponentAdjuster(textureChannel, 3, aAdj, colorModifier.A.adjustmentType)); } } } return(true); }
private float GetAggregateValueNew(UMADnaBase dna, float result = 0f) { float tempResult = 0f; if (_aggregationMethod == AggregationMethodOpts.Average) { var aveCount = result != 0f ? 1 : 0; for (int i = 0; i < _dnaEvaluators.Count; i++) { if (!string.IsNullOrEmpty(_dnaEvaluators[i].dnaName)) { aveCount++; result += _dnaEvaluators[i].Evaluate(dna); } } if (aveCount > 0) { result = result / aveCount; } } else if (_aggregationMethod == AggregationMethodOpts.Maximum) { for (int i = 0; i < _dnaEvaluators.Count; i++) { tempResult = 0f; if (!string.IsNullOrEmpty(_dnaEvaluators[i].dnaName)) { tempResult = _dnaEvaluators[i].Evaluate(dna); if (tempResult > result) { result = tempResult; } } } } else if (_aggregationMethod == AggregationMethodOpts.Minimum) { for (int i = 0; i < _dnaEvaluators.Count; i++) { tempResult = 0f; if (!string.IsNullOrEmpty(_dnaEvaluators[i].dnaName)) { tempResult = _dnaEvaluators[i].Evaluate(dna); if (tempResult < result) { result = tempResult; } } } } else if (aggregationMethod == AggregationMethodOpts.Cumulative) { for (int i = 0; i < _dnaEvaluators.Count; i++) { tempResult = 0f; if (!string.IsNullOrEmpty(_dnaEvaluators[i].dnaName)) { tempResult = _dnaEvaluators[i].Evaluate(dna); if (_dnaEvaluators[i].calcOption == DNAEvaluator.CalcOption.Add) { result += tempResult; } else if (_dnaEvaluators[i].calcOption == DNAEvaluator.CalcOption.Subtract) { result -= tempResult; } else if (_dnaEvaluators[i].calcOption == DNAEvaluator.CalcOption.Multiply) { result *= tempResult; } else if (_dnaEvaluators[i].calcOption == DNAEvaluator.CalcOption.Divide && tempResult != 0) { result /= tempResult; } } } } return(result); }