[Test] // TODO: fix jobs public void OnEnterWorks([Values(CodeGenMode.NoJobs)] CodeGenMode mode) { SetupTestGraphMultipleFrames(mode, graphModel => { var group = graphModel.CreateComponentQuery("g"); var positionType = typeof(Translation).GenerateTypeHandle(Stencil); group.AddComponent(graphModel.Stencil, positionType, ComponentDefinitionFlags.None); group.AddComponent(graphModel.Stencil, typeof(Rotation).GenerateTypeHandle(Stencil), ComponentDefinitionFlags.None); var groupInstance = graphModel.CreateVariableNode(group, Vector2.zero); var update = graphModel.CreateNode <OnStartEntitiesNodeModel>("update", Vector2.zero); graphModel.CreateEdge(update.InstancePort, groupInstance.OutputPort); var set = update.CreateStackedNode <SetPositionNodeModel>("set", 0, SpawnFlags.Default, n => n.Mode = SetPositionNodeModel.TranslationMode.Float3); set.Add = true; // increment so we can detect multiple runs if they happen ((Float3ConstantModel)set.InputConstantsById["Value"]).value = new Vector3(1f, 0.0f, 0.0f); IVariableModel posComponent = GraphModel.CreateVariableNode(update.FunctionParameterModels.Single(p => p.DataType == positionType), Vector2.zero); GraphModel.CreateEdge(set.InstancePort, posComponent.OutputPort); }, EachEntity((manager, i, e) => manager.AddComponent(e, typeof(Rotation))), EachEntity((manager, i, e) => { manager.AddComponent(e, typeof(Translation)); // will make the entity enter the query Assert.That(manager.GetComponentData <Translation>(e).Value.x, Is.EqualTo(0)); }), EachEntity((manager, i, e) => Assert.That(manager.GetComponentData <Translation>(e).Value.x, Is.EqualTo(1))), // translate ran once EachEntity((manager, i, e) => Assert.That(manager.GetComponentData <Translation>(e).Value.x, Is.EqualTo(1))) // not twice ); }
public void TestFunctionCall([Values(CodeGenMode.NoJobs)] CodeGenMode mode) { var originalScale = Time.timeScale; try { SetupTestGraph(mode, graph => { var query = graph.CreateComponentQuery("m_Query"); var translationType = typeof(Translation).GenerateTypeHandle(Stencil); query.AddComponent(Stencil, translationType, ComponentDefinitionFlags.None); var queryInstance = graph.CreateVariableNode(query, Vector2.zero); var onUpdate = graph.CreateNode <OnUpdateEntitiesNodeModel>("On Update", Vector2.zero); graph.CreateEdge(onUpdate.InstancePort, queryInstance.OutputPort); var propertyInfo = typeof(Time).GetProperty("timeScale", BindingFlags.Static | BindingFlags.Public); var setProperty = onUpdate.CreateFunctionCallNode(propertyInfo?.SetMethod); var floatConst = graph.CreateConstantNode("floatConst", TypeHandle.Float, Vector2.zero); ((FloatConstantModel)floatConst).value = 0.42f; graph.CreateEdge(setProperty.GetPortForParameter("value"), floatConst.OutputPort); }, (manager, entityIndex, entity) => manager.AddComponentData(entity, new Translation()), (manager, entityIndex, entity) => Assert.That(Time.timeScale, Is.EqualTo(0.42f))); } finally { Time.timeScale = originalScale; } }
[Test] // TODO: fix jobs public void OnExitWorks([Values(CodeGenMode.NoJobs)] CodeGenMode mode) { SetupTestGraphMultipleFrames(mode, graphModel => { var group = graphModel.CreateComponentQuery("g"); var positionType = typeof(Translation).GenerateTypeHandle(Stencil); group.AddComponent(graphModel.Stencil, positionType, ComponentDefinitionFlags.None); group.AddComponent(graphModel.Stencil, typeof(Rotation).GenerateTypeHandle(Stencil), ComponentDefinitionFlags.None); var groupInstance = graphModel.CreateVariableNode(group, Vector2.zero); var update = graphModel.CreateNode <OnEndEntitiesNodeModel>("update", Vector2.zero); graphModel.CreateEdge(update.InstancePort, groupInstance.OutputPort); var log = update.CreateFunctionCallNode(typeof(Debug).GetMethod("Log", new[] { typeof(object) }), 0); IVariableModel entityVariable = GraphModel.CreateVariableNode(update.FunctionParameterModels.Single(p => p.DataType == typeof(Entity).GenerateTypeHandle(Stencil)), Vector2.zero); GraphModel.CreateEdge(log.GetParameterPorts().First(), entityVariable.OutputPort); }, EachEntity((manager, i, e) => manager.AddComponent(e, typeof(Rotation))), EachEntity((manager, i, e) => manager.AddComponent(e, typeof(Translation))), EachEntity((manager, i, e) => { LogAssert.NoUnexpectedReceived(); LogAssert.Expect(LogType.Log, $"Entity({i}:1)"); manager.RemoveComponent <Rotation>(e); }), EachEntity((manager, i, e) => {}) ); }
public void TestStackInstantiateEntityAndAddComponent([Values] CodeGenMode mode) { int entitiesWithTranslationComponent = 0; int entitiesWithoutTranslationComponent = 0; SetupTestGraph(mode, graphModel => { PrepareGraph(graphModel); var translationType = typeof(Translation).GenerateTypeHandle(Stencil); // Create instantiate node m_InstantiateModel.SetComponentOperation(translationType, ComponentOperation.ComponentOperationType.AddComponent); m_InstantiateModel.DefineNode(); var translateComponentPort = m_InstantiateModel.GetPortsForComponent(translationType).First(); graphModel.CreateEdge(translateComponentPort, m_FloatConstantNode.OutputPort); }, (manager, entityIndex, e) => manager.AddComponent(e, typeof(Scale)), (manager, entityIndex, e) => { if (manager.GetComponentTypes(e).Any(ct => ct.GetManagedType() == typeof(Translation))) { Translation t = manager.GetComponentData <Translation>(e); Assert.That(t.Value.x, Is.EqualTo(m_FloatConstantNode.value)); entitiesWithTranslationComponent++; } else { entitiesWithoutTranslationComponent++; } }); Assert.That(entitiesWithoutTranslationComponent, Is.EqualTo(k_EntityCount)); Assert.That(entitiesWithTranslationComponent, Is.EqualTo(k_EntityCount)); }
protected void SetupTestGraphMultipleFrames(CodeGenMode mode, Action <VSGraphModel> setupGraph, params StepDelegate[] setup) { m_SystemType = null; setupGraph(GraphModel); try { m_SystemType = CompileGraph(mode); } finally { GC.Collect(); } if (setup.Length > 0) { Entity[] entities = new Entity[k_EntityCount]; for (var index = 0; index < entities.Length; index++) { entities[index] = m_EntityManager.CreateEntity(); } setup[0](m_EntityManager, entities); } for (int i = 1; i < setup.Length; i++) { TestSystem(m_SystemType); setup[i](m_EntityManager, m_EntityManager.GetAllEntities().ToArray()); } }
public void OneGroupIterationSystem([Values] CodeGenMode mode) { SetupTestGraph(mode, g => { ComponentQueryDeclarationModel query = GraphModel.CreateComponentQuery("g1"); TypeHandle positionType = typeof(Translation).GenerateTypeHandle(Stencil); query.AddComponent(Stencil, positionType, ComponentDefinitionFlags.None); IVariableModel queryInstance = GraphModel.CreateVariableNode(query, Vector2.zero); OnUpdateEntitiesNodeModel onUpdateModel = GraphModel.CreateNode <OnUpdateEntitiesNodeModel>("update", Vector2.zero); GraphModel.CreateEdge(onUpdateModel.InstancePort, queryInstance.OutputPort); SetPropertyGroupNodeModel set = onUpdateModel.CreateStackedNode <SetPropertyGroupNodeModel>("set"); var member = new TypeMember(TypeHandle.Float, new List <string> { nameof(Translation.Value), nameof(Translation.Value.x) }); set.AddMember(member); IVariableModel posComponent = GraphModel.CreateVariableNode(onUpdateModel.FunctionParameterModels.Single(p => p.DataType == positionType), Vector2.zero); GraphModel.CreateEdge(set.InstancePort, posComponent.OutputPort); ((FloatConstantModel)set.InputConstantsById[member.GetId()]).value = 2f; }, (manager, entityIndex, e) => manager.AddComponentData(e, new Translation { Value = { x = entityIndex } }), (manager, entityIndex, e) => Assert.That(manager.GetComponentData <Translation>(e).Value.x, Is.EqualTo(2f))); }
public void OneGroupIterationSystem_SharedAndRegularComponents([Values(CodeGenMode.NoJobs)] CodeGenMode mode) { SetupTestGraph(mode, g => { var query = GraphModel.CreateComponentQuery("query"); var positionType = typeof(Translation).GenerateTypeHandle(Stencil); query.AddComponent(Stencil, positionType, ComponentDefinitionFlags.None); var renderType = typeof(RenderMesh).GenerateTypeHandle(Stencil); query.AddComponent(Stencil, renderType, ComponentDefinitionFlags.Shared); var queryInstance = GraphModel.CreateVariableNode(query, Vector2.zero); var onUpdateModel = GraphModel.CreateNode <OnUpdateEntitiesNodeModel>("update", Vector2.zero); GraphModel.CreateEdge(onUpdateModel.InstancePort, queryInstance.OutputPort); var posComponent = GraphModel.CreateVariableNode(onUpdateModel.FunctionParameterModels.Single(p => p.DataType == positionType), Vector2.zero); var renderComponent = GraphModel.CreateVariableNode(onUpdateModel.FunctionParameterModels.Single(p => p.DataType == renderType), Vector2.zero); var logTranslation = onUpdateModel.CreateFunctionCallNode(typeof(Debug).GetMethod("Log", new[] { typeof(object) }), 0); var logRenderMesh = onUpdateModel.CreateFunctionCallNode(typeof(Debug).GetMethod("Log", new[] { typeof(object) }), 1); GraphModel.CreateEdge(logTranslation.GetParameterPorts().First(), posComponent.OutputPort); GraphModel.CreateEdge(logRenderMesh.GetParameterPorts().First(), renderComponent.OutputPort); }, (manager, entityIndex, e) => { manager.AddComponentData(e, new Translation { Value = { x = entityIndex } }); manager.AddSharedComponentData(e, new RenderMesh()); }, (manager, entityIndex, e) => Assert.Pass()); }
Type CompileGraph(CodeGenMode mode, out CompilationResult results) { results = default; RoslynEcsTranslator translator = (RoslynEcsTranslator)GraphModel.CreateTranslator(); translator.AllowNoJobsFallback = false; // because of the hack in the translator constructor, override right after ((EcsStencil)Stencil).UseJobSystem = mode == CodeGenMode.Jobs || mode == CodeGenMode.JobsTracing; var compilationOptions = CompilationOptions.LiveEditing; if (mode == CodeGenMode.JobsTracing || mode == CodeGenMode.NoJobsTracing) { compilationOptions |= CompilationOptions.Tracing; } results = GraphModel.Compile(AssemblyType.Memory, translator, compilationOptions); var results2 = results; Assert.That(results?.status, Is.EqualTo(CompilationStatus.Succeeded), () => $"Compilation failed, errors: {String.Join("\n", results2?.errors)}\r\n{FormatCode(results2)}"); return(EcsStencil.LiveCompileGraph(GraphModel, results, includeVscriptingAssemblies: true)); }
public void TestStackInstantiateEntityAndRemoveComponent([Values] CodeGenMode mode) { int entitiesWithScaleComponent = 0; int entitiesWithoutScaleComponent = 0; SetupTestGraph(mode, graphModel => { PrepareGraph(graphModel); var scaleType = typeof(Scale).GenerateTypeHandle(Stencil); // Create instantiate node m_InstantiateModel.SetComponentOperation(scaleType, ComponentOperation.ComponentOperationType.RemoveComponent); m_InstantiateModel.DefineNode(); }, (manager, entityIndex, e) => manager.AddComponent(e, typeof(Scale)), (manager, entityIndex, e) => { if (manager.GetComponentTypes(e).Any(ct => ct.GetManagedType() == typeof(Scale))) { entitiesWithScaleComponent++; } else { entitiesWithoutScaleComponent++; } }); Assert.That(entitiesWithoutScaleComponent, Is.EqualTo(k_EntityCount)); Assert.That(entitiesWithScaleComponent, Is.EqualTo(k_EntityCount)); }
public void SendEventNestedTest([Values] CodeGenMode mode) { SetupTestGraphMultipleFrames(mode, graphModel => { // group1 - Position var group1 = graphModel.CreateComponentQuery("g1"); group1.AddComponent(graphModel.Stencil, typeof(Translation).GenerateTypeHandle(Stencil), ComponentDefinitionFlags.None); var group1Instance = graphModel.CreateVariableNode(group1, Vector2.zero); // group2 - Scale (will add RenderMesh) var group2 = graphModel.CreateComponentQuery("g2"); group2.AddComponent(graphModel.Stencil, typeof(Scale).GenerateTypeHandle(Stencil), ComponentDefinitionFlags.None); var group2Instance = graphModel.CreateVariableNode(group2, Vector2.zero); // update group 1 var onUpdateEntities = graphModel.CreateNode <OnUpdateEntitiesNodeModel>("update", Vector2.zero); graphModel.CreateEdge(onUpdateEntities.InstancePort, group1Instance.OutputPort); // nested update group 2 var forAllStack = GraphModel.CreateLoopStack <ForAllEntitiesStackModel>(Vector2.zero); var forAllNode = forAllStack.CreateLoopNode(onUpdateEntities, 0) as ForAllEntitiesNodeModel; graphModel.CreateEdge(forAllNode.InputPort, group2Instance.OutputPort); graphModel.CreateEdge(forAllStack.InputPort, forAllNode.OutputPort); TypeHandle eventTypeHandle = typeof(UnitTestEvent).GenerateTypeHandle(Stencil); SendEventNodeModel set = forAllStack.CreateStackedNode <SendEventNodeModel>("set", 0, SpawnFlags.Default, n => n.EventType = eventTypeHandle); TypeHandle entityType = typeof(Entity).GenerateTypeHandle(Stencil); IVariableModel entityVar = GraphModel.CreateVariableNode(forAllStack.FunctionParameterModels.Single(p => p.DataType == entityType), Vector2.zero); var firstFieldInput = set.EntityPort; GraphModel.CreateEdge(firstFieldInput, entityVar.OutputPort); } ); }
public void TestDestroyEntity([Values] CodeGenMode mode) { SetupTestGraph(mode, graphModel => { // Component creation var dummyF3Type = typeof(Translation).GenerateTypeHandle(Stencil); var query = graphModel.CreateComponentQuery("g"); query.AddComponent(graphModel.Stencil, dummyF3Type, ComponentDefinitionFlags.None); // On update var queryInstance = graphModel.CreateVariableNode(query, Vector2.zero); var onUpdateEntities = graphModel.CreateNode <OnUpdateEntitiesNodeModel>("update", Vector2.zero); graphModel.CreateEdge(onUpdateEntities.InstancePort, queryInstance.OutputPort); // Destroy Entity var entityInstance = graphModel.CreateVariableNode( onUpdateEntities.FunctionParameterModels.Single( p => p.DataType == typeof(Entity).GenerateTypeHandle(graphModel.Stencil) ), Vector2.zero); var destroy = onUpdateEntities.CreateStackedNode <DestroyEntityNodeModel>("destroy"); graphModel.CreateEdge(destroy.EntityPort, entityInstance.OutputPort); }, (manager, entityIndex, e) => manager.AddComponent(e, typeof(Translation)), (manager, entityIndex, e) => Assert.IsFalse(manager.Exists(e))); }
public void TestCoroutineAccessingLocalVariable([Values] CodeGenMode mode) { SetupTestGraphMultipleFrames(mode, graph => { var query = SetupQuery(graph, "query", new[] { typeof(Translation) }); var onUpdate = SetupOnUpdate(graph, query); onUpdate.CreateStackedNode <CoroutineNodeModel>("Wait", setup: n => { n.CoroutineType = typeof(Wait).GenerateTypeHandle(Stencil); }); var localVar = onUpdate.CreateFunctionVariableDeclaration("localVar", TypeHandle.Float); var localVarInstance = graph.CreateVariableNode(localVar, Vector2.zero); var log = onUpdate.CreateStackedNode <LogNodeModel>("Log"); graph.CreateEdge(log.InputPort, localVarInstance.OutputPort); }, EachEntity((manager, i, e) => { manager.AddComponentData(e, new Translation()); var coroutineType = m_SystemType.GetNestedTypes().First(t => t.Name.Contains("Coroutine")); Assert.That(coroutineType, Is.Not.Null); Assert.That(manager.HasComponent(e, coroutineType), Is.Not.True); }), EachEntity((manager, i, e) => Assert.Pass()) ); }
public void TestCoroutineExecutionStack([Values] CodeGenMode mode) { SetupTestGraphMultipleFrames(mode, graph => { var query = SetupQuery(graph, "query", new[] { typeof(Translation) }); var onUpdate = SetupOnUpdate(graph, query); var loopNode = onUpdate.CreateStackedNode <CoroutineNodeModel>("UnitTest", setup: n => { n.CoroutineType = typeof(UnitTestCoroutine).GenerateTypeHandle(Stencil); }); var loopStack = graph.CreateLoopStack <CoroutineStackModel>(Vector2.down); graph.CreateEdge(loopStack.InputPort, loopNode.OutputPort); var setProperty = loopStack.CreateSetPropertyGroupNode(0); var member = new TypeMember(TypeHandle.Float, new List <string> { nameof(Translation.Value), nameof(Translation.Value.x) }); setProperty.AddMember(member); ((FloatConstantModel)setProperty.InputConstantsById[member.GetId()]).value = 10f; var translation = graph.CreateVariableNode(onUpdate.FunctionParameterModels.Single(p => p.DataType == typeof(Translation).GenerateTypeHandle(Stencil)), Vector2.zero); graph.CreateEdge(setProperty.InstancePort, translation.OutputPort); }, EachEntity((manager, i, e) => manager.AddComponentData(e, new Translation())), EachEntity((manager, i, e) => {}), // Init State EachEntity((manager, i, e) => {}), // MoveNext -> Execute loop stack EachEntity((manager, i, e) => Assert.That(manager.GetComponentData <Translation>(e).Value.x, Is.EqualTo(10f))) ); }
public void TestGenerateUniqueCoroutineComponentsAndQueries([Values] CodeGenMode mode) { SetupTestGraph(mode, graph => { var query = SetupQuery(graph, "query", new[] { typeof(Translation) }); var onUpdate = SetupOnUpdate(graph, query); onUpdate.CreateStackedNode <CoroutineNodeModel>("Wait", setup: n => { n.CoroutineType = typeof(Wait).GenerateTypeHandle(Stencil); }); var onUpdate2 = SetupOnUpdate(graph, query); onUpdate2.CreateStackedNode <CoroutineNodeModel>("Wait 2", setup: n => { n.CoroutineType = typeof(Wait).GenerateTypeHandle(Stencil); }); }, (manager, entityIndex, entity) => { manager.AddComponentData(entity, new Translation()); }, (manager, entityIndex, entity) => { var coroutines = m_SystemType.GetNestedTypes() .Where(t => t.Name.Contains("Coroutine")) .ToList(); Assert.That(coroutines.Count, Is.EqualTo(2)); Assert.That(coroutines.Distinct().Count(), Is.EqualTo(coroutines.Count)); var queries = m_SystemType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic) .Where(f => f.FieldType == typeof(EntityQuery)) .ToList(); Assert.That(queries.Count, Is.EqualTo(4)); // 2 queries + 2 queries for coroutine initialization Assert.That(queries.Distinct().Count(), Is.EqualTo(queries.Count)); }); }
public void TestStackInstantiateEntity([Values] CodeGenMode mode) { SetupTestGraph(mode, PrepareGraph, (manager, entityIndex, e) => manager.AddComponent(e, typeof(Scale)), (manager, entityIndex, e) => {}); Assert.That(m_EntityManager.GetAllEntities().Length, Is.EqualTo(k_EntityCount * 2)); }
public void TestSendEventInCoroutine([Values] CodeGenMode mode) { SetupTestGraphMultipleFrames(mode, graph => { var query = SetupQuery(graph, "query", new[] { typeof(Translation) }); var onUpdate = SetupOnUpdate(graph, query); onUpdate.CreateStackedNode <CoroutineNodeModel>("Wait", 0, setup: n => { n.CoroutineType = typeof(Wait).GenerateTypeHandle(Stencil); }); var eventTypeHandle = typeof(UnitTestEvent).GenerateTypeHandle(Stencil); var sendEvent = onUpdate.CreateStackedNode <SendEventNodeModel>("Send", 1, setup: n => { n.EventType = eventTypeHandle; }); var entityType = typeof(Entity).GenerateTypeHandle(Stencil); var entityVar = graph.CreateVariableNode(onUpdate.FunctionParameterModels.Single(p => p.DataType == entityType), Vector2.zero); graph.CreateEdge(sendEvent.EntityPort, entityVar.OutputPort); var onEvent = graph.CreateNode <OnEventNodeModel>("On Event", preDefineSetup: n => { n.EventTypeHandle = eventTypeHandle; }); graph.CreateEdge(onEvent.InstancePort, query.OutputPort); var setProperty = onEvent.CreateSetPropertyGroupNode(0); var member = new TypeMember(TypeHandle.Float, new List <string> { nameof(Translation.Value), nameof(Translation.Value.x) }); setProperty.AddMember(member); ((FloatConstantModel)setProperty.InputConstantsById[member.GetId()]).value = 10f; var translation = graph.CreateVariableNode(onEvent.FunctionParameterModels.Single(p => p.DataType == typeof(Translation).GenerateTypeHandle(Stencil)), Vector2.zero); graph.CreateEdge(setProperty.InstancePort, translation.OutputPort); }, EachEntity((manager, i, e) => { manager.World.CreateSystem <InitializationSystemGroup>(); manager.AddComponentData(e, new Translation()); }), // Init State EachEntity((manager, i, e) => {}), // Wait MoveNext EachEntity((manager, i, e) => {}), // Send event; EachEntity((manager, i, e) => { Assert.That(manager.GetComponentData <Translation>(e).Value.x, Is.EqualTo(10f)); })); }
public void TestRemoveComponent_RootContext([Values] CodeGenMode mode) { SetupTestGraph(mode, graphModel => { CreateRemoveComponentInGraph(graphModel, typeof(Translation)); }, (manager, entityIndex, e) => manager.AddComponent(e, typeof(Translation)), (manager, entityIndex, e) => Assert.That(!manager.HasComponent <Translation>(e))); }
public void TestWaitUntilCoroutine([Values] CodeGenMode mode) { float yBeforeWait = 0f; float yAfterWait = 10f; SetupTestGraphMultipleFrames(mode, graph => { var query = SetupQuery(graph, "query", new[] { typeof(Translation) }); var onUpdate = SetupOnUpdate(graph, query); var waitUntil = onUpdate.CreateStackedNode <CoroutineNodeModel>("Wait Until", setup: n => { n.CoroutineType = typeof(WaitUntil).GenerateTypeHandle(Stencil); }); var translation = graph.CreateVariableNode(onUpdate.FunctionParameterModels.Single(p => p.DataType == typeof(Translation).GenerateTypeHandle(Stencil)), Vector2.zero); var getProperty = GraphModel.CreateGetPropertyGroupNode(Vector2.zero); var translationXMember = new TypeMember(TypeHandle.Float, new List <string> { nameof(Translation.Value), nameof(Translation.Value.x) }); getProperty.AddMember(translationXMember); GraphModel.CreateEdge(getProperty.InstancePort, translation.OutputPort); var equalNode = GraphModel.CreateBinaryOperatorNode(BinaryOperatorKind.GreaterThan, Vector2.zero); GraphModel.CreateEdge(equalNode.InputPortA, getProperty.GetPortsForMembers().Single()); ((FloatConstantModel)equalNode.InputConstantsById[equalNode.InputPortB.UniqueId]).value = 0f; var moveNextParam = typeof(WaitUntil).GetMethod(nameof(WaitUntil.MoveNext))?.GetParameters().Single(); Assert.That(moveNextParam, Is.Not.Null); GraphModel.CreateEdge(waitUntil.GetParameterPort(moveNextParam), equalNode.OutputPort); var setProperty = onUpdate.CreateSetPropertyGroupNode(-1); var translationYMember = new TypeMember(TypeHandle.Float, new List <string> { nameof(Translation.Value), nameof(Translation.Value.y) }); setProperty.AddMember(translationYMember); GraphModel.CreateEdge(setProperty.InstancePort, translation.OutputPort); ((FloatConstantModel)setProperty.InputConstantsById[translationYMember.GetId()]).value = yAfterWait; }, EachEntity((manager, i, e) => { manager.AddComponentData(e, new Translation()); }), EachEntity((manager, i, e) => { Assert.That(manager.GetComponentData <Translation>(e).Value.y, Is.EqualTo(yBeforeWait)); manager.SetComponentData(e, new Translation { Value = { x = 10f } }); // any x > 0 should stop this WaitUntil }), (manager, entities) => {}, // Skip Frame where WaitUntil is done and component gets set EachEntity((manager, i, e) => { Assert.That(manager.GetComponentData <Translation>(e).Value.y, Is.EqualTo(yAfterWait)); }) ); }
public void TestMultipleCriteriaModel([Values] CodeGenMode mode) { SetupTestGraph(mode, graphModel => { var group = CreateComponentQuery(graphModel, typeof(DummyFloat3Component), typeof(DummyBoolComponent)); var onUpdateEntities = CreateOnUpdateAndConnectGroup(graphModel, group); // Add criteria var f3Criterion = GetDummyFloat3ValueCriterion(); var cFloat3 = ScriptableObject.CreateInstance <CriteriaModel>(); cFloat3.UniqueNameProvider = onUpdateEntities; cFloat3.GraphModel = graphModel; cFloat3.Name = "cFloat3"; cFloat3.AddCriterionNoUndo(graphModel, f3Criterion); onUpdateEntities.AddCriteriaModelNoUndo(cFloat3); var boolCriterion = GetDummyBoolCriterion(); var cBool = ScriptableObject.CreateInstance <CriteriaModel>(); cBool.UniqueNameProvider = onUpdateEntities; cBool.Name = "cBool"; cBool.GraphModel = graphModel; cBool.AddCriterionNoUndo(graphModel, boolCriterion); onUpdateEntities.AddCriteriaModelNoUndo(cBool); AddSharedComponentIfCriteriaMatch(graphModel, onUpdateEntities); }, (manager, entityIndex, e) => { var x = entityIndex % 2 == 0 ? 0f : 25f; manager.AddComponentData(e, new DummyFloat3Component { Value = new float3 { x = x } }); var b = entityIndex % 3 == 0; manager.AddComponentData(e, new DummyBoolComponent { Value = b }); }, (manager, entityIndex, e) => { var x = manager.GetComponentData <DummyFloat3Component>(e).Value.x; var b = manager.GetComponentData <DummyBoolComponent>(e).Value; if (x < 10f || b) { Assert.That(manager.HasComponent <DummySharedComponent>(e)); } else { Assert.That(!manager.HasComponent <DummySharedComponent>(e)); } }); }
public void RandomFloatCall([Values] CodeGenMode mode) { SetupTestGraphMultipleFrames(mode, graph => { var query = SetupQuery(graph, "query", new[] { typeof(Translation) }); var onUpdate = SetupOnUpdate(graph, query); var log = onUpdate.CreateStackedNode <LogNodeModel>(); var rnd = graph.CreateNode <RandomNodeModel>(); graph.CreateEdge(log.InputPort, rnd.OutputPort); }); }
public void TestCoroutineWithForEachContext([Values] CodeGenMode mode) { SetupTestGraphMultipleFrames(mode, graph => { var translationQuery = SetupQuery(graph, "translationQuery", new[] { typeof(Translation) }); var scaleQuery = SetupQuery(graph, "scaleQuery", new[] { typeof(Scale) }); var onUpdate = SetupOnUpdate(graph, translationQuery); onUpdate.CreateStackedNode <CoroutineNodeModel>("Wait", setup: n => { n.CoroutineType = typeof(Wait).GenerateTypeHandle(Stencil); }); var forAllStack = graph.CreateLoopStack <ForAllEntitiesStackModel>(Vector2.zero); var forAllNode = forAllStack.CreateLoopNode(onUpdate, 1) as ForAllEntitiesNodeModel; Assert.That(forAllNode, Is.Not.Null); graph.CreateEdge(forAllNode.InputPort, scaleQuery.OutputPort); graph.CreateEdge(forAllStack.InputPort, forAllNode.OutputPort); var setProperty = forAllStack.CreateSetPropertyGroupNode(0); var member = new TypeMember(TypeHandle.Float, new List <string> { nameof(Scale.Value) }); setProperty.AddMember(member); ((FloatConstantModel)setProperty.InputConstantsById[member.GetId()]).value = 10f; var scale = graph.CreateVariableNode(forAllStack.FunctionParameterModels.Single(p => p.DataType == typeof(Scale).GenerateTypeHandle(Stencil)), Vector2.zero); graph.CreateEdge(setProperty.InstancePort, scale.OutputPort); }, EachEntity((manager, i, e) => { if (i % 2 == 0) { manager.AddComponentData(e, new Translation()); } else { manager.AddComponentData(e, new Scale()); } }), EachEntity((manager, i, e) => {}), // Init State EachEntity((manager, i, e) => {}), // Wait MoveNext EachEntity((manager, i, e) => // ForEach set Scale { if (manager.HasComponent <Scale>(e)) { Assert.That(manager.GetComponentData <Scale>(e).Value, Is.EqualTo(10f)); } }) ); }
public void TestRetrievingConcurrentCommandBuffer([Values(CodeGenMode.Jobs)] CodeGenMode mode) { SetupTestGraph(mode, graphModel => { // We instantiate 2 nodes that need a command buffer // Only 1 command buffer should be declared // Create componentQuery var dummyF3Type = typeof(Translation).GenerateTypeHandle(Stencil); var query = graphModel.CreateComponentQuery("g"); query.AddComponent(graphModel.Stencil, dummyF3Type, ComponentDefinitionFlags.None); // On update var queryInstance = graphModel.CreateVariableNode(query, Vector2.zero); var onUpdateEntities = graphModel.CreateNode <OnUpdateEntitiesNodeModel>("update", Vector2.zero); graphModel.CreateEdge(onUpdateEntities.InstancePort, queryInstance.OutputPort); // Create entity instance var entityInstance = graphModel.CreateVariableNode( onUpdateEntities.FunctionParameterModels.Single( p => p.DataType == typeof(Entity).GenerateTypeHandle(graphModel.Stencil) ), Vector2.zero); // Add Component var addComponent = onUpdateEntities.CreateStackedNode <AddComponentNodeModel>("add"); addComponent.ComponentType = typeof(Scale).GenerateTypeHandle(graphModel.Stencil); graphModel.CreateEdge(addComponent.EntityPort, entityInstance.OutputPort); // Destroy Entity var destroy = onUpdateEntities.CreateStackedNode <DestroyEntityNodeModel>("destroy"); graphModel.CreateEdge(destroy.EntityPort, entityInstance.OutputPort); }, (manager, entityIndex, e) => manager.AddComponent(e, typeof(Translation)), (manager, entityIndex, e) => { // Assert only 1 EndFrameBarrier field has been created var efbFields = m_SystemType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic) .Where(f => f.FieldType == typeof(EndSimulationEntityCommandBufferSystem)); Assert.AreEqual(1, efbFields.Count()); // Assert only 1 ConcurrentCommandBuffer has been created in job var nestedTypes = m_SystemType.GetNestedTypes(BindingFlags.NonPublic) .Where(t => t.IsValueType); var jobType = nestedTypes.First(); Assert.IsNotNull(jobType); var cbTypes = jobType.GetFields(BindingFlags.Instance | BindingFlags.Public) .Where(f => f.FieldType == typeof(EntityCommandBuffer.Concurrent)); Assert.AreEqual(1, cbTypes.Count()); }); }
public void TestExcludedComponentQuery_RootContext([Values] CodeGenMode mode) { var defaultValue = new quaternion(0, 0, 0, 0); var modifiedValue = new quaternion(1, 1, 1, 1); SetupTestGraph(mode, CreateGraphNodes, AddComponentsToEntities, ValidateSubtractive); void CreateGraphNodes(VSGraphModel graphModel) { var scaleType = typeof(Scale).GenerateTypeHandle(Stencil); var rotationType = typeof(Rotation).GenerateTypeHandle(Stencil); var group = graphModel.CreateComponentQuery("g"); group.AddComponent(graphModel.Stencil, scaleType, ComponentDefinitionFlags.Subtract); group.AddComponent(graphModel.Stencil, rotationType, ComponentDefinitionFlags.None); IVariableModel groupInstance = graphModel.CreateVariableNode(group, Vector2.zero); OnUpdateEntitiesNodeModel onOnEntitiesNodeModel = graphModel.CreateNode <OnUpdateEntitiesNodeModel>("loop", Vector2.zero); graphModel.CreateEdge(onOnEntitiesNodeModel.InstancePort, groupInstance.OutputPort); SetComponentNodeModel setRotationNode = graphModel.CreateNode <SetComponentNodeModel>("SetComponent", Vector2.zero); setRotationNode.ComponentType = typeof(Rotation).GenerateTypeHandle(Stencil); onOnEntitiesNodeModel.AddStackedNode(setRotationNode, -1); setRotationNode.DefineNode(); var entityVarDeclaration = onOnEntitiesNodeModel.FunctionParameterModels.Single(p => p.DataType == typeof(Entity).GenerateTypeHandle(graphModel.Stencil)); var entityInstance = graphModel.CreateVariableNode(entityVarDeclaration, Vector2.zero); var float4ConstantNode = (Float4ConstantModel)graphModel.CreateConstantNode("float4", typeof(float4).GenerateTypeHandle(graphModel.Stencil), Vector2.zero); float4ConstantNode.value = modifiedValue.value; graphModel.CreateEdge(setRotationNode.EntityPort, entityInstance.OutputPort); graphModel.CreateEdge(setRotationNode.InputsById[nameof(Rotation.Value)], float4ConstantNode.OutputPort); } void AddComponentsToEntities(EntityManager manager, int entityIndex, Entity e) { manager.AddComponent(e, typeof(Rotation)); if (entityIndex % 2 == 1) { manager.AddComponent(e, typeof(Scale)); } } void ValidateSubtractive(EntityManager manager, int entityIndex, Entity e) { var expectedValue = manager.HasComponent <Scale>(e) ? defaultValue : modifiedValue; Assert.That(manager.GetComponentData <Rotation>(e).Value, Is.EqualTo(expectedValue)); } }
protected void SetupTestGraphMultipleFrames(CodeGenMode mode, Action <VSGraphModel> setupGraph, params StepDelegate[] setup) { m_SystemType = null; setupGraph(GraphModel); CompilationResult results; try { m_SystemType = CompileGraph(mode, out results); } finally { GC.Collect(); } // Something fishy is going on here, the TypeManager is throwing a fit when adding new ComponentData through // live compilation. Shutting down the TypeManager and re-initializing seems like the way to circumvent the // issue, but it does not seem like it's enough. // Tearing the world down (along with the TypeManager), and recreating it, works. TearDownWorld(); bool hasTracing = mode == CodeGenMode.JobsTracing; SetUpWorld(hasTracing); if (setup.Length > 0) { Entity[] entities = new Entity[k_EntityCount]; for (var index = 0; index < entities.Length; index++) { entities[index] = m_EntityManager.CreateEntity(); } setup[0](m_EntityManager, entities); } try { for (int i = 1; i < setup.Length; i++) { TestSystem(m_SystemType); setup[i](m_EntityManager, m_EntityManager.GetAllEntities().ToArray()); } } catch { Debug.Log(FormatCode(results)); throw; } }
public void NestedIterationSystem_DifferentGroups_DifferentComponents([Values] CodeGenMode mode) { SetupTestGraph(mode, g => { TypeHandle translationType = typeof(Translation).GenerateTypeHandle(Stencil); TypeHandle rotationType = typeof(Rotation).GenerateTypeHandle(Stencil); // query1 - Position ComponentQueryDeclarationModel query1 = GraphModel.CreateComponentQuery("g1"); query1.AddComponent(Stencil, translationType, ComponentDefinitionFlags.None); IVariableModel query1Instance = GraphModel.CreateVariableNode(query1, Vector2.zero); // query2 - Rotation too ComponentQueryDeclarationModel query2 = GraphModel.CreateComponentQuery("g2"); query2.AddComponent(Stencil, rotationType, ComponentDefinitionFlags.None); IVariableModel query2Instance = GraphModel.CreateVariableNode(query2, Vector2.zero); // update query 1 OnUpdateEntitiesNodeModel onUpdateModel = GraphModel.CreateNode <OnUpdateEntitiesNodeModel>("update", Vector2.zero); GraphModel.CreateEdge(onUpdateModel.InstancePort, query1Instance.OutputPort); // nested update query 2 var forAllStack = GraphModel.CreateLoopStack <ForAllEntitiesStackModel>(Vector2.zero); var forAllNode = forAllStack.CreateLoopNode(onUpdateModel, 0) as ForAllEntitiesNodeModel; Assert.That(forAllNode, Is.Not.Null); GraphModel.CreateEdge(forAllNode.InputPort, query2Instance.OutputPort); GraphModel.CreateEdge(forAllStack.InputPort, forAllNode.OutputPort); // set query1.translation = ... SetPropertyGroupNodeModel set = forAllStack.CreateStackedNode <SetPropertyGroupNodeModel>("set"); var member = new TypeMember(TypeHandle.Float, new List <string> { nameof(Translation.Value), nameof(Translation.Value.x) }); set.AddMember(member); IVariableModel posComponent = GraphModel.CreateVariableNode(onUpdateModel.FunctionParameterModels.Single(p => p.DataType == translationType), Vector2.zero); GraphModel.CreateEdge(set.InstancePort, posComponent.OutputPort); ((FloatConstantModel)set.InputConstantsById[member.GetId()]).value = 2f; }, (manager, entityIndex, e) => { manager.AddComponentData(e, new Translation { Value = { x = entityIndex } }); manager.AddComponentData(e, new Rotation()); }, (manager, entityIndex, e) => Assert.That(manager.GetComponentData <Translation>(e).Value.x, Is.EqualTo(2f))); }
public void TestSingleCriteriaModel_ManyCriterion([Values] CodeGenMode mode) { SetupTestGraph(mode, graphModel => { var query = CreateComponentQuery(graphModel, typeof(DummyFloat3Component), typeof(DummyBoolComponent)); var onUpdateEntities = CreateOnUpdateAndConnectQuery(graphModel, query); // Add criteria var f3Criterion = GetDummyFloat3ValueCriterion(); var boolCriterion = GetDummyBoolCriterion(); var criteria = new CriteriaModel(); criteria.UniqueNameProvider = onUpdateEntities; criteria.GraphModel = graphModel; criteria.Name = "criteria"; criteria.AddCriterionNoUndo(graphModel, f3Criterion); criteria.AddCriterionNoUndo(graphModel, boolCriterion); onUpdateEntities.AddCriteriaModelNoUndo(criteria); AddSharedComponentIfCriteriaMatch(graphModel, onUpdateEntities); }, (manager, entityIndex, e) => { var x = entityIndex % 2 == 0 ? 0f : 25f; manager.AddComponentData(e, new DummyFloat3Component { Value = new float3 { x = x } }); var b = entityIndex % 4 == 0; manager.AddComponentData(e, new DummyBoolComponent { Value = b }); }, (manager, entityIndex, e) => { var x = manager.GetComponentData <DummyFloat3Component>(e).Value.x; var b = manager.GetComponentData <DummyBoolComponent>(e).Value; if (x < 10f && b) { Assert.That(manager.HasComponent <DummySharedComponent>(e)); } else { Assert.That(!manager.HasComponent <DummySharedComponent>(e)); } }); }
public void TestAddComponent_ForEachContext([Values] CodeGenMode mode) { SetupTestGraph(mode, graphModel => { // group1 - Position var group1 = graphModel.CreateComponentQuery("g1"); group1.AddComponent(graphModel.Stencil, typeof(Translation).GenerateTypeHandle(Stencil), ComponentDefinitionFlags.None); var group1Instance = graphModel.CreateVariableNode(group1, Vector2.zero); // group2 - Scale (will add DummySharedComponent) var group2 = graphModel.CreateComponentQuery("g2"); group2.AddComponent(graphModel.Stencil, typeof(Scale).GenerateTypeHandle(Stencil), ComponentDefinitionFlags.None); var group2Instance = graphModel.CreateVariableNode(group2, Vector2.zero); // update group 1 var onUpdateEntities = graphModel.CreateNode <OnUpdateEntitiesNodeModel>("update", Vector2.zero); graphModel.CreateEdge(onUpdateEntities.InstancePort, group1Instance.OutputPort); // nested update group 2 var forAllStack = graphModel.CreateLoopStack <ForAllEntitiesStackModel>(Vector2.zero); var forAllNode = forAllStack.CreateLoopNode(onUpdateEntities, 0) as ForAllEntitiesNodeModel; Assert.That(forAllNode, Is.Not.Null); graphModel.CreateEdge(forAllNode.InputPort, group2Instance.OutputPort); graphModel.CreateEdge(forAllStack.InputPort, forAllNode.OutputPort); // add DummySharedComponent component var addComponent = forAllStack.CreateStackedNode <AddComponentNodeModel>("add"); addComponent.ComponentType = typeof(DummySharedComponent).GenerateTypeHandle(graphModel.Stencil); var entityInstance = graphModel.CreateVariableNode( forAllStack.FunctionParameterModels.Single( p => p.DataType == typeof(Entity).GenerateTypeHandle(graphModel.Stencil) ), Vector2.zero); graphModel.CreateEdge(addComponent.EntityPort, entityInstance.OutputPort); }, (manager, entityIndex, e) => { // HACK as there is no Single update method as entry point (just the on UpdateEntities right now) var toAdd = entityIndex == 0 ? typeof(Translation) : typeof(Scale); manager.AddComponent(e, toAdd); }, (manager, entityIndex, e) => { Assert.That(manager.HasComponent <Scale>(e) ? manager.HasComponent <DummySharedComponent>(e) : !manager.HasComponent <DummySharedComponent>(e)); }); }
public void SendEventTest([Values] CodeGenMode mode) { SetupTestGraphMultipleFrames(mode, g => { ComponentQueryDeclarationModel query = GraphModel.CreateComponentQuery("g1"); TypeHandle positionType = typeof(Translation).GenerateTypeHandle(Stencil); query.AddComponent(Stencil, positionType, ComponentDefinitionFlags.None); IVariableModel queryInstance = GraphModel.CreateVariableNode(query, Vector2.zero); OnUpdateEntitiesNodeModel onUpdateModel = GraphModel.CreateNode <OnUpdateEntitiesNodeModel>("update", Vector2.zero); GraphModel.CreateEdge(onUpdateModel.InstancePort, queryInstance.OutputPort); TypeHandle eventTypeHandle = typeof(UnitTestEvent).GenerateTypeHandle(Stencil); SendEventNodeModel set = onUpdateModel.CreateStackedNode <SendEventNodeModel>("set", 0, SpawnFlags.Default, n => n.EventType = eventTypeHandle); TypeHandle entityType = typeof(Entity).GenerateTypeHandle(Stencil); IVariableModel entityVar = GraphModel.CreateVariableNode(onUpdateModel.FunctionParameterModels.Single(p => p.DataType == entityType), Vector2.zero); GraphModel.CreateEdge(set.EntityPort, entityVar.OutputPort); var firstFieldInput = set.FieldInputs.First(); ((FloatConstantModel)set.InputConstantsById[firstFieldInput.UniqueId]).value = 2f; }, // Add translation to even entities EachEntity((manager, i, e) => { manager.AddComponent(e, typeof(Translation)); manager.World.CreateSystem <InitializationSystemGroup>(); }), (manager, entities) => { EventSystem <UnitTestEvent> eventSystem = manager.World.GetExistingSystem <EventSystem <UnitTestEvent> >(); Assert.That(eventSystem, Is.Not.Null); eventSystem.Update(); }, // OnUpdate should have added a buffer and one event EachEntity((manager, i, e) => { DynamicBuffer <UnitTestEvent> buffer = default; Assert.DoesNotThrow(() => buffer = manager.GetBuffer <UnitTestEvent>(e)); Assert.That(buffer.IsCreated, Is.True); Assert.That(buffer.Length, Is.EqualTo(1)); Assert.That(buffer[0].i, Is.EqualTo(2f)); }) ); }
public void RandomCallInCoroutine([Values] CodeGenMode mode) { SetupTestGraphMultipleFrames(mode, graph => { for (int i = 0; i < 2; i++) { var query = SetupQuery(graph, "query" + i, new[] { typeof(Translation) }); var onUpdate = SetupOnUpdate(graph, query); onUpdate.CreateStackedNode <CoroutineNodeModel>("wait", setup: n => n.CoroutineType = typeof(Wait).GenerateTypeHandle(Stencil)); var log = onUpdate.CreateStackedNode <LogNodeModel>(); var rnd = graph.CreateNode <RandomNodeModel>(); graph.CreateEdge(log.InputPort, rnd.OutputPort); } }); }
public void MultipleOnUpdateEntities([Values] CodeGenMode mode) { SetupTestGraph(mode, graph => { var translationType = typeof(Translation).GenerateTypeHandle(Stencil); var query = GraphModel.CreateComponentQuery("g1"); query.AddComponent(Stencil, translationType, ComponentDefinitionFlags.None); var queryInstance = GraphModel.CreateVariableNode(query, Vector2.zero); CreateUpdateAndLogEntity(graph, queryInstance); CreateUpdateAndLogEntity(graph, queryInstance); }, (manager, index, entity) => manager.AddComponentData(entity, new Translation()), (manager, index, entity) => Assert.Pass() ); }