/* Function: HashPath * Returns the hash path for the class. */ static public string HashPath(SymbolString databaseSymbol) { SymbolString qualifier = databaseSymbol.WithoutLastSegment; string endingSymbol = databaseSymbol.LastSegment; return(QualifierHashPath(qualifier) + Utilities.Sanitize(endingSymbol)); }
public SymbolString(SymbolString symString) { for (int i = 0; i < symString.Length(); i++) { this.symList.Add(new Symbol(symString.GetAt(i))); } }
/* Function: HashPath * Returns the hash path for the class. */ static public string HashPath(string simpleLanguageID, SymbolString classSymbol) { SymbolString qualifier = classSymbol.WithoutLastSegment; string endingSymbol = classSymbol.LastSegment; return(QualifierHashPath(simpleLanguageID, qualifier) + Utilities.Sanitize(endingSymbol)); }
public void Operate( ref TurtleState state, int indexInString, SymbolString <float> sourceString) { var paramIndex = sourceString.parameters[indexInString]; if (paramIndex.length == 0) { state.transformation *= Matrix4x4.Scale(defaultScaleFactor * nonUniformScale); } else if (paramIndex.length == 1) { state.transformation *= Matrix4x4.Scale(sourceString.parameters[paramIndex, 0] * nonUniformScale); } else if (paramIndex.length == 3) { state.transformation *= Matrix4x4.Scale( new Vector3( sourceString.parameters[paramIndex, 0], sourceString.parameters[paramIndex, 1], sourceString.parameters[paramIndex, 2] )); } else { Debug.LogError($"Invalid scale parameter length: {paramIndex.length}"); } }
public void WriteReplacement( NativeArray <float> matchedParameters, JaggedIndexing parameterSpace, NativeArray <OperatorDefinition> operatorData, SymbolString <float> target, NativeArray <ReplacementSymbolGenerator.Blittable> replacementSymbolSpace, NativeArray <StructExpression> structExpressionSpace, int firstIndexInSymbols, int firstIndexInParamters) { var writeIndexInParams = firstIndexInParamters; for (int symbolIndex = 0; symbolIndex < replacementSymbols.length; symbolIndex++) { var replacementExpression = replacementSymbolSpace[symbolIndex + replacementSymbols.index]; target[symbolIndex + firstIndexInSymbols] = replacementExpression.replacementSymbol; replacementExpression.WriteNewParameters( matchedParameters, parameterSpace, operatorData, target.parameters, structExpressionSpace, ref writeIndexInParams, symbolIndex + firstIndexInSymbols ); } }
public LSystemStructureTreeElement( LinkedFileSet sourceFileSet, SymbolString <float> symbols, int indexInSymbols, int branchSymbolIndex = -1) { symbol = symbols[indexInSymbols]; parameters = symbols.parameters.AsArray(indexInSymbols); var symbolDefinition = sourceFileSet.GetLeafMostSymbolDefinition(symbol); var builder = new StringBuilder(); builder.Append(symbolDefinition.characterInSourceFile); if (!"[]".Contains(symbolDefinition.characterInSourceFile)) { symbols.WriteParamString(indexInSymbols, builder); builder.Append(" : "); builder.Append(Path.GetFileName(symbolDefinition.sourceFileDefinition)); } displayName = builder.ToString(); if (branchSymbolIndex != -1) { id = -branchSymbolIndex - 1; } else { id = indexInSymbols; } }
/// <summary> /// partial, semi-ordered tree matching algorithm. /// /// iterate over target string, no backtracking /// maintain data about matches in series match: /// indexes which are valid branched matches for the current index in target /// record of which leaves in the matcher have been matched /// </summary> /// <param name="indexInSymbolTarget"></param> /// <param name="seriesMatch"></param> /// <returns>a mapping from all symbols in seriesMatch back into the target string</returns> public bool MatchesForward( NativeMultipleHashSets.HashSetSlice includeSymbolsSet, int indexInSymbolTarget, SymbolSeriesSuffixMatcher seriesMatch, SymbolString <float> symbolString, int firstParameterCopyIndex, NativeArray <float> parameterCopyMemory, out byte paramsCopiedToMem, TmpNativeStack <BranchEventData> helperStack ) { if (!seriesMatch.HasGraphIndexes) { // this should be done in the parsing/compiling phase. should only have to happen once for the whole system, per matching rule. throw new System.Exception("graph indexes should be precomputed"); //seriesMatch.ComputeGraphIndexes(branchOpenSymbol, branchCloseSymbol); } // keep count of how many more matches are required at each level of the tree. // starts out as a copy of the child count array. each leaf will be at 0, and will go negative when matched. //var remainingMatchesAtIndexes = seriesMatch.childrenCounts.Clone() as int[]; return(MatchesForwardsAtIndexOrderingInvariant( includeSymbolsSet, indexInSymbolTarget, seriesMatch, symbolString, firstParameterCopyIndex, parameterCopyMemory, out paramsCopiedToMem, helperStack)); }
/// <summary> /// Checks to see if <paramref name="currentSymbolInTarget"/> matches the symbol at <paramref name="currentIndexInMatch"/> in the <paramref name="seriesMatch"/> string. /// And also if the parent at <paramref name="currentParentIndexInTarget"/> maps to the parent of <paramref name="currentIndexInMatch"/> /// </summary> /// <param name="seriesMatch"></param> /// <param name="targetIndexesToMatchIndexes"></param> /// <param name="currentParentIndexInTarget"></param> /// <param name="currentSymbolInTarget"></param> /// <param name="currentIndexInMatch"></param> /// <returns></returns> private bool TargetSymbolMatchesAndParentMatches( SymbolSeriesSuffixMatcher seriesMatch, NativeHashMap <int, int> targetIndexesToMatchIndexes, int currentParentIndexInTarget, int currentIndexInTarget, int currentIndexInMatch, SymbolString <float> symbolString ) { var symbolInMatch = nativeRuleData.suffixMatcherGraphNodeData[currentIndexInMatch + seriesMatch.graphNodeMemSpace.index].mySymbol; if ( symbolInMatch.targetSymbol == symbolString[currentIndexInTarget] && symbolInMatch.parameterLength == symbolString.ParameterSize(currentIndexInTarget)) { var parentIndexInMatch = nativeRuleData.suffixMatcherGraphNodeData[currentIndexInMatch + seriesMatch.graphNodeMemSpace.index].parentIndex; if (parentIndexInMatch == -1) { // if the parent is the origin, always match. return(true); } var parentIndexInTarget = currentParentIndexInTarget; var indexInMatchOfTargetParentMapped = targetIndexesToMatchIndexes[parentIndexInTarget]; // check to ensure the parent of this node in the target graph // is already mapped to the parent of the node in the if (parentIndexInMatch == indexInMatchOfTargetParentMapped) { return(true); } } return(false); }
/* Function: ScoreInterpretation * A function used by <Score()> to determine the C and S fields of the score for the passed interpretation. Only * those fields and the trailing 1 will be set in the returned score. If the interpretation doesn't match, it will return * zero. */ private long ScoreInterpretation(Topic topic, Link link, SymbolString interpretation) { // --C----- -------- -------- -SSSSSSS SSS----- -------- -------- -------1 // C - Whether the topic and link's capitalization match if it matters to the language. // S - How high on the scope list the symbol match is. long scopeScore = ScoreScopeInterpretation(topic, link, interpretation); // S is always going to be higher for scopes than for using statements, so if there's a match and C is set we can // quit early because there's no way a using statement is going to top it. if (scopeScore > 0x3000000000000000) { return(scopeScore); } long usingScore = ScoreUsingInterpretation(topic, link, interpretation); if (scopeScore > usingScore) { return(scopeScore); } else { return(usingScore); } }
public void Operate( ref TurtleState state, int indexInString, SymbolString <float> sourceString) { var paramIndex = sourceString.parameters[indexInString]; float bendFactor = defaultBendFactor; if (paramIndex.length == 1) { bendFactor = sourceString.parameters[paramIndex, 0]; } var localBendDirection = state.transformation.inverse.MultiplyVector(defaultBendDirection); var adjustment = (bendFactor) * (Vector3.Cross(localBendDirection, Vector3.right)); state.transformation *= Matrix4x4.Rotate( Quaternion.Slerp( Quaternion.identity, Quaternion.FromToRotation( Vector3.right, localBendDirection), adjustment.magnitude ) ); }
public void Operate( ref TurtleState state, int indexInString, SymbolString <float> sourceString, TurtleVolumetricHandles volumetricHandles) { var paramIndex = sourceString.parameters[indexInString]; if (paramIndex.length != 1) { return; } var pointInLocalSpace = state.transformation.MultiplyPoint(Vector3.zero); var voxelIndex = volumetricHandles.universalWriter.GetVoxelIndexFromLocalSpace(pointInLocalSpace); if (!voxelIndex.IsValid) { return; } var amountInSymbol = sourceString.parameters[paramIndex, 0]; if (diffusionDirection == OrganDiffusionDirection.PUMP_OUT) { volumetricHandles.universalWriter.AppendAmountChangeToOtherLayer(voxelIndex, amountInSymbol, resourceLayerId); return; } var amountInVoxel = volumetricHandles.volumetricData[voxelIndex, resourceLayerId]; var diffusionToLSystem = (amountInVoxel - amountInSymbol) * diffusionConstant; switch (diffusionDirection) { case OrganDiffusionDirection.DIFFUSE_IN_ONLY: diffusionToLSystem = math.max(diffusionToLSystem, 0); break; case OrganDiffusionDirection.DIFFUSE_OUT_ONLY: diffusionToLSystem = math.min(diffusionToLSystem, 0); break; default: break; } if (diffusionCap > 0) { var maxAllowableDiffuseIn = math.max(diffusionCap - amountInSymbol, 0); diffusionToLSystem = math.min(diffusionToLSystem, maxAllowableDiffuseIn); var maxAllowableDiffuseOut = math.max(diffusionCap - amountInVoxel, 0); diffusionToLSystem = -math.min(-diffusionToLSystem, maxAllowableDiffuseOut); } if (diffusionToLSystem == 0) { return; } sourceString.parameters[paramIndex, 0] = amountInSymbol + diffusionToLSystem; volumetricHandles.universalWriter.AppendAmountChangeToOtherLayer(voxelIndex, -diffusionToLSystem, resourceLayerId); }
private void AssertRuleDoesNotMatchCondtitional( string ruleText, int[] sourceSymbols = null, float[][] sourceParameters = null, string axiom = null, int ruleParamMemoryStartIndex = 0, int matchIndex = 0, int paramTempMemorySize = 0, float[] globalParams = null, string[] globalParamNames = null, string includedSymbols = "[]ABCDE" ) { var totalIncluded = new HashSet <int>(includedSymbols.Select(x => (int)x)); globalParamNames = globalParamNames ?? new string[0]; using var symbols = new DependencyTracker <SymbolString <float> >( axiom == null ? new SymbolString <float>(sourceSymbols, sourceParameters) : SymbolString <float> .FromString(axiom, Allocator.Persistent) ); var ruleFromString = new BasicRule( RuleParser.ParseToRule(ruleText, x => x, globalParameters: globalParamNames), '[', ']'); using var ruleNativeData = new SystemLevelRuleNativeData(new[] { ruleFromString }); var nativeWriter = new SymbolSeriesMatcherNativeDataWriter(); ruleFromString.WriteDataIntoMemory(ruleNativeData, nativeWriter); globalParams = globalParams ?? new float[0]; using var globalNative = new NativeArray <float>(globalParams, Allocator.Persistent); using var paramMemory = new NativeArray <float>(paramTempMemorySize, Allocator.Persistent); using var branchCache = new SymbolStringBranchingCache('[', ']', new[] { totalIncluded }, ruleNativeData); branchCache.BuildJumpIndexesFromSymbols(symbols); var random = new Unity.Mathematics.Random(); var matchSingleData = new LSystemSingleSymbolMatchData { isTrivial = false, tmpParameterMemorySpace = JaggedIndexing.GetWithNoLength(ruleParamMemoryStartIndex) }; var potentialMatch = ruleFromString.AsBlittable().PreMatchCapturedParametersWithoutConditional( branchCache, symbols.Data, matchIndex, paramMemory, matchSingleData.tmpParameterMemorySpace.index, ref matchSingleData, new TmpNativeStack <SymbolStringBranchingCache.BranchEventData>(5), globalNative, ruleNativeData.dynamicOperatorMemory, ref random, ruleNativeData.ruleOutcomeMemorySpace ); Assert.IsFalse(potentialMatch); }
public void FindsBranchForwardLinksCorrectlyWhenBranchingAtSameIndexAsCharacterCodeForBranchingSymbol() { using var targetString = new DependencyTracker <SymbolString <float> >(SymbolString <float> .FromString("[&E][&&E]&EEEE[&[EE]E][&&[EE]E]&EEEE[&[EEEE]EE][&&[EEEE]EE]&EEEA[&[EEEEEE]E[E]E[E]][&&[EEEEEE]E[E]E[E]]")); using var branchingCache = new SymbolStringBranchingCache('[', ']', new SystemLevelRuleNativeData()); branchingCache.BuildJumpIndexesFromSymbols(targetString); Assert.AreEqual(64, branchingCache.FindOpeningBranchIndexReadonly(82)); Assert.AreEqual(86, branchingCache.FindOpeningBranchIndexReadonly(93)); }
/* Function: OutputFile * Returns the output file for a class. */ static public Path OutputFile(Path targetOutputFolder, SymbolString databaseSymbol) { SymbolString qualifier = databaseSymbol.WithoutLastSegment; string endingSymbol = databaseSymbol.LastSegment; return(OutputFolder(targetOutputFolder, qualifier) + '/' + Utilities.Sanitize(endingSymbol, replaceDots: true) + ".html"); }
/* Function: OutputFile * Returns the output file for a class. */ static public Path OutputFile(Path targetOutputFolder, string simpleLanguageID, SymbolString classSymbol) { SymbolString qualifier = classSymbol.WithoutLastSegment; string endingSymbol = classSymbol.LastSegment; return(OutputFolder(targetOutputFolder, simpleLanguageID, qualifier) + '/' + Utilities.Sanitize(endingSymbol, replaceDots: true) + ".html"); }
/// <summary> /// /// </summary> /// <param name="indexInSymbolTarget"></param> /// <param name="seriesMatch"></param> /// <returns>whether the match succeeded or not</returns> public bool MatchesBackwards( NativeMultipleHashSets.HashSetSlice includedSymbolSet, int indexInSymbolTarget, SymbolSeriesPrefixMatcher seriesMatch, SymbolString <float> symbolString, int firstParameterCopyIndex, NativeArray <float> parameterCopyMemory, out byte paramsCopiedToMem) { indexInSymbolTarget--; int matchingIndex = seriesMatch.graphNodeMemSpace.length - 1; paramsCopiedToMem = 0; for (; matchingIndex >= 0 && indexInSymbolTarget >= 0;) { var symbolToMatch = nativeRuleData.prefixMatcherSymbols[matchingIndex + seriesMatch.graphNodeMemSpace.index]; while (indexInSymbolTarget >= 0) { var currentSymbol = symbolString.symbols[indexInSymbolTarget]; if (!includedSymbolSet.Contains(currentSymbol) || currentSymbol == branchOpenSymbol) { indexInSymbolTarget--; } else if (currentSymbol == branchCloseSymbol) { indexInSymbolTarget = FindOpeningBranchIndexReadonly(indexInSymbolTarget) - 1; } else if (currentSymbol == symbolToMatch.targetSymbol && symbolToMatch.parameterLength == symbolString.parameters[indexInSymbolTarget].length) { // copy the parameters in reverse order, so they can be reversed in-place at end // on success var paramIndexing = symbolString.parameters[indexInSymbolTarget]; for (int i = paramIndexing.length - 1; i >= 0; i--) { parameterCopyMemory[paramsCopiedToMem + firstParameterCopyIndex] = symbolString.parameters[paramIndexing, i]; paramsCopiedToMem++; } indexInSymbolTarget--; matchingIndex--; break; } else { return(false); } } } if (matchingIndex == -1) { ReverseRange(parameterCopyMemory, firstParameterCopyIndex, paramsCopiedToMem); return(true); } return(false); }
public void FindsClosingBranchLinks() { using var targetString = new DependencyTracker <SymbolString <float> >(SymbolString <float> .FromString("A[AA]AAA[A[AAA[A]]]A")); using var branchingCache = new SymbolStringBranchingCache('[', ']', new SystemLevelRuleNativeData()); branchingCache.BuildJumpIndexesFromSymbols(targetString); Assert.AreEqual(4, branchingCache.FindClosingBranchIndexReadonly(1)); Assert.AreEqual(17, branchingCache.FindClosingBranchIndexReadonly(10)); Assert.AreEqual(18, branchingCache.FindClosingBranchIndexReadonly(8)); }
static void Main() { CapitalString capitals = new CapitalString("BMW Bape Add".ToCharArray()); Console.WriteLine(capitals.FindChar()); Console.WriteLine(capitals.GetLength()); SymbolString symbols = new SymbolString("paloAlto**_123)u*".ToCharArray()); Console.WriteLine(symbols.FindChar()); }
public SymbolString <float> GetAxiom(Allocator allocator = Allocator.Persistent) { if (!fileIndexesByFullIdentifier.ContainsKey(originFile)) { throw new LinkException(LinkExceptionType.BAD_ORIGIN_FILE, $"could not find origin file '{originFile}'"); } var originFileData = allFiles.data[fileIndexesByFullIdentifier[originFile]]; return(SymbolString <float> .FromString(originFileData.axiom, allocator, chr => originFileData.GetSymbolInFile(chr))); }
public void PerformDiffusionOnDataAndApply(SymbolString <float> targetSymbols) { var latestDataInA = true; for (int i = 0; i < customSymbols.diffusionStepsPerStep; i++) { DiffuseBetween(latestDataInA); latestDataInA = !latestDataInA; } ApplyDiffusionResults(latestDataInA, targetSymbols); }
/* Function: ExtractTypeLinks * Goes through the prototype of the passed <Topic> and adds any type links it finds to <LinkSet>. */ protected void ExtractTypeLinks(Topic topic, LinkSet linkSet) { if (topic.Prototype == null) { return; } Language language = EngineInstance.Languages.FromID(topic.LanguageID); TokenIterator symbolStart = topic.ParsedPrototype.Tokenizer.FirstToken; TokenIterator symbolEnd; while (symbolStart.IsInBounds) { if (symbolStart.PrototypeParsingType == PrototypeParsingType.Type || symbolStart.PrototypeParsingType == PrototypeParsingType.TypeQualifier) { symbolEnd = symbolStart; do { symbolEnd.Next(); }while (symbolEnd.PrototypeParsingType == PrototypeParsingType.Type || symbolEnd.PrototypeParsingType == PrototypeParsingType.TypeQualifier); if (language.IsBuiltInType(symbolStart, symbolEnd) == false) { Link link = new Link(); // ignore LinkID link.Type = LinkType.Type; link.Symbol = SymbolString.FromPlainText_NoParameters(symbolStart.Tokenizer.TextBetween(symbolStart, symbolEnd)); link.Context = topic.PrototypeContext; // ignore contextID link.FileID = topic.FileID; link.ClassString = topic.ClassString; // ignore classID link.LanguageID = topic.LanguageID; // ignore EndingSymbol // ignore TargetTopicID // ignore TargetScore linkSet.Add(link); } symbolStart = symbolEnd; } else { symbolStart.Next(); } } }
public void SymbolStringConstructorConvertsToInts() { var symbolFromString = SymbolString <float> .FromString("AABA"); var convertedSymbols = symbolFromString.symbols; Assert.AreEqual(convertedSymbols[0], 65); Assert.AreEqual(convertedSymbols[1], 65); Assert.AreEqual(convertedSymbols[2], 66); Assert.AreEqual(convertedSymbols[3], 65); symbolFromString.Dispose(); }
// Calculates the resultant string after n applications of the rules public SymbolString CalculateResult(int n) { SymbolString result = results[results.Count - 1]; // the last string that has been calculated so far for (int j = results.Count - 1; j < n; j++) { result = ApplyRules(result); results.Add(result); } return result; }
private void AssertBackwardsMatch( string target, string matcher, bool shouldMatch, string includeSymbols = "[]ABCDEFJ", int parameterMemorySize = 10, float[] expectedCapturedParameters = null, int indexInTarget = -1) { var includedSymbolSet = includeSymbols.Select(x => (int)x); var prefixBuilder = SymbolSeriesPrefixBuilder.Parse(matcher); using var nativeData = new SystemLevelRuleNativeData(new RuleDataRequirements { prefixNodes = prefixBuilder.RequiredNodeMemorySpace }); var writer = new SymbolSeriesMatcherNativeDataWriter(); var seriesMatcher = prefixBuilder.BuildIntoManagedMemory(nativeData, writer); using var targetString = new DependencyTracker <SymbolString <float> >(SymbolString <float> .FromString(target)); using var branchingCache = new SymbolStringBranchingCache( '[', ']', includedSymbolSet == null ? new HashSet <int> [0] : new[] { new HashSet <int>(includedSymbolSet) }, nativeData); branchingCache.BuildJumpIndexesFromSymbols(targetString); using var parameterMemory = new NativeArray <float>(parameterMemorySize, Allocator.Persistent); var realIndex = indexInTarget < 0 ? indexInTarget + targetString.Data.Length : indexInTarget; var hasMatched = branchingCache.MatchesBackwards( branchingCache.includeSymbols[0], realIndex, seriesMatcher, targetString.Data, 0, parameterMemory, out var copiedParams); if (shouldMatch != hasMatched) { Assert.Fail($"Expected '{matcher}' to {(shouldMatch ? "" : "not ")}match backwards from {indexInTarget} in '{target}'"); } if (shouldMatch && expectedCapturedParameters != null) { Assert.AreEqual(expectedCapturedParameters.Length, copiedParams); for (int i = 0; i < expectedCapturedParameters.Length; i++) { Assert.AreEqual(expectedCapturedParameters[i], parameterMemory[i]); } } }
public void Operate( ref TurtleState state, int indexInString, SymbolString <float> sourceString) { var paramIndex = sourceString.parameters[indexInString]; float theta = defaultTheta; if (paramIndex.length >= 1) { theta = sourceString.parameters[paramIndex, 0]; } state.transformation *= Matrix4x4.Rotate(Quaternion.Euler(theta * unitEulerRotation)); }
// Adds a rule to the set. public void AddRule(Symbol input, float probability, SymbolString output) { if (ruleset.ContainsKey((string)input)) { ruleset[(string)input].Add(new Rule(probability, output)); } else { ruleset.Add((string)input, new List <Rule>() { new Rule(probability, output) }); } }
/* Function: OutputFolder * * Returns the output folder for database files, optionally for the passed qualifier within it. * * - If the qualifier isn't specified, it returns the root output folder for all database files. * - If the qualifier is specified, it returns the output folder for that qualifier. * * Examples: * * targetOutputFolder - C:\Project\Documentation\database * targetOutputFolder + qualifier - C:\Project\Documentation\database\Qualifier1\Qualifier2 */ static public Path OutputFolder(Path targetOutputFolder, SymbolString qualifier = default(SymbolString)) { StringBuilder result = new StringBuilder(targetOutputFolder); result.Append("/database"); if (qualifier != null) { result.Append('/'); string pathString = qualifier.FormatWithSeparator('/'); result.Append(Utilities.Sanitize(pathString)); } return(result.ToString()); }
/* Function: Database_OutputFolder * * Returns the output folder for database files, optionally for the partial symbol within it. * * - If the partial symbol isn't specified, it returns the output folder for all database files. * - If partial symbol is specified, it returns the output folder for that symbol. */ public Path Database_OutputFolder(SymbolString partialSymbol = default(SymbolString)) { StringBuilder result = new StringBuilder(OutputFolder); result.Append("/database"); if (partialSymbol != null) { result.Append('/'); string pathString = partialSymbol.FormatWithSeparator('/'); result.Append(SanitizePath(pathString)); } return(result.ToString()); }
/* Function: QualifierHashPath * * Returns the qualifier part of the hash path for classes. If the qualifier symbol is specified it will include a * trailing member operator so that the last segment can simply be concatenated. * * - If language ID is specified but the qualifier is not, it returns the prefix for all class paths of that language. * - If language ID and qualifier are specified, it returns the prefix plus the hash path for that qualifier6, including * a trailing separator. * * Examples: * * simpleLanguageID - CSharpClass: * simpleLanguageID + qualifier - CSharpClass:Namespace1.Namespace2. */ static public string QualifierHashPath(string simpleLanguageID, SymbolString qualifier = default(SymbolString)) { StringBuilder result = new StringBuilder(); result.Append(simpleLanguageID); result.Append("Class:"); if (qualifier != null) { string pathString = qualifier.FormatWithSeparator('.'); result.Append(Utilities.Sanitize(pathString)); result.Append('.'); } return(result.ToString()); }
public void Operate( ref TurtleState state, int indexInString, SymbolString <float> sourceString, EntityCommandBuffer spawningCommandBuffer, Matrix4x4 localToWorldTransform) { var paramIndex = sourceString.parameters[indexInString]; var spawned = spawningCommandBuffer.Instantiate(instantiableEntity); var newbuffer = spawningCommandBuffer.SetBuffer <TurtleSpawnedParameters>(spawned); var parameterSlice = sourceString.parameters.data.Slice(paramIndex.index, paramIndex.length); newbuffer.CopyFrom(parameterSlice.SliceConvert <TurtleSpawnedParameters>()); var totalLocalToWorld = localToWorldTransform * state.transformation * prefabTransform; var rot = totalLocalToWorld.rotation; Vector3 pos = totalLocalToWorld.GetColumn(3); // Extract new local scale Vector3 scale = new Vector3( totalLocalToWorld.GetColumn(0).magnitude, totalLocalToWorld.GetColumn(1).magnitude, totalLocalToWorld.GetColumn(2).magnitude ); spawningCommandBuffer.SetComponent(spawned, new Rotation { Value = rot }); spawningCommandBuffer.SetComponent(spawned, new Translation { Value = pos }); // scale is done a bit differently for everything. if scale changes are needed, read from the TurtleSpawnedParameters //spawningCommandBuffer.SetComponent(instantiableEntity, new NonUniformScale //{ // Value = scale //}); //spawningCommandBuffer.SetComponent(instantiableEntity, new LocalToWorld //{ // Value = localToWorldTransform * state.transformation //}); }