protected override void OnUpdate() { // UI text conversion Entities.ForEach((TextMeshProUGUI displayText) => { // We are converting an entity (textEntity) and creating another (eSubText). // Why? // We want to use the Rectangle Transform system to also position text, rather // than introduce something special. So we need a parent element that is the frame // of the text (textEntity) and a child element that has a pivet on the text string // itself. Systems later will process the child element. var textEntity = GetPrimaryEntity(displayText); // Sub-text child transform SceneSection sceneSection = DstEntityManager.GetSharedComponentData <SceneSection>(textEntity); var eSubText = DstEntityManager.CreateEntity(); DstEntityManager.AddSharedComponentData(eSubText, sceneSection); DstEntityManager.AddComponentData(eSubText, new Tiny.UI.RectTransform { AnchorMin = 0.5f, AnchorMax = 0.5f, SizeDelta = 1f, AnchoredPosition = 0f, Pivot = 0.5f }); DstEntityManager.AddComponentData(eSubText, new UIName() { Name = displayText.name }); DstEntityManager.AddComponentData(eSubText, new RectParent() { Value = textEntity }); DstEntityManager.AddComponentData(eSubText, new Unity.Tiny.Rendering.CameraMask { mask = (ulong)(1 << displayText.gameObject.layer) }); DstEntityManager.AddComponent <RectTransformResult>(eSubText); var fontAsset = GetPrimaryEntity(displayText.font); DstEntityManager.AddComponentData(eSubText, new Tiny.Text.TextRenderer { FontMaterial = fontAsset, MeshColor = displayText.color.linear.ToTiny(), Size = displayText.fontSize * 10, HorizontalAlignment = ConvertHorizontalAlignment(displayText.alignment), VerticalAlignment = ConvertVerticalAlignment(displayText.alignment), }); var text = displayText.text; DstEntityManager.AddBufferFromString <TextRendererString>(eSubText, text); DstEntityManager.AddComponent <LocalToWorld>(eSubText); }); }
protected override void OnUpdate() { Entities.ForEach((ModifyJointLimitsAuthoring modifyJointLimits) => { foreach (var jointAuthoringComponent in modifyJointLimits.GetComponents <Component>()) { // apply modification to joints produced by legacy Joint and BaseJoint if (jointAuthoringComponent as LegacyJoint == null && jointAuthoringComponent as BaseJoint == null) { continue; } var jointEntities = new NativeList <Entity>(16, Allocator.Temp); World.GetOrCreateSystem <EndJointConversionSystem>().GetJointEntities(jointAuthoringComponent, jointEntities); foreach (var jointEntity in jointEntities) { var angularModification = new ParticleSystem.MinMaxCurve( multiplier: math.radians(modifyJointLimits.AngularRangeScalar.curveMultiplier), min: modifyJointLimits.AngularRangeScalar.curveMin, max: modifyJointLimits.AngularRangeScalar.curveMax ); DstEntityManager.AddSharedComponentData(jointEntity, new ModifyJointLimits { InitialValue = DstEntityManager.GetComponentData <PhysicsJoint>(jointEntity), AngularRangeScalar = angularModification, LinearRangeScalar = modifyJointLimits.LinearRangeScalar }); } } }); }
private void ConvertCanvas(Canvas canvas) { var entity = GetPrimaryEntity(canvas); CanvasSortLayer image = new CanvasSortLayer { Value = canvas.sortingOrder }; DstEntityManager.AddComponentData(entity, image); DstEntityManager.AddComponent(entity, typeof(RebuildCanvasHierarchyFlag)); DstEntityManager.AddBuffer <MeshVertex>(entity); DstEntityManager.AddBuffer <MeshVertexIndex>(entity); DstEntityManager.AddBuffer <SubMeshInfo>(entity); if (canvas.renderMode != RenderMode.ScreenSpaceCamera) { throw new InvalidOperationException($"Canvas ({canvas}) render mode ({canvas.renderMode}) is not supported yet"); } if (canvas.worldCamera == null) { throw new InvalidOperationException($"Target camera is null or destroyed. Canvas {canvas}"); } var proxy = canvas.worldCamera.GetComponent <CameraImageRenderProxy>(); if (proxy == null) { proxy = canvas.worldCamera.gameObject.AddComponent <CameraImageRenderProxy>(); } DstEntityManager.AddSharedComponentData(entity, new CanvasTargetCamera() { Target = proxy }); }
protected override void OnUpdate() { Entities.ForEach((BoidAuthoring boidAuthoring) => { var entity = GetPrimaryEntity(boidAuthoring); DstEntityManager.AddSharedComponentData(entity, new Boid { CellRadius = boidAuthoring.CellRadius, SeparationWeight = boidAuthoring.SeparationWeight, AlignmentWeight = boidAuthoring.AlignmentWeight, TargetWeight = boidAuthoring.TargetWeight, ObstacleAversionDistance = boidAuthoring.ObstacleAversionDistance, MoveSpeed = boidAuthoring.MoveSpeed }); // Remove default transform system components DstEntityManager.RemoveComponent <Translation>(entity); DstEntityManager.RemoveComponent <Rotation>(entity); // Add world render bounds components so they do not need to be added at initialization time. DstEntityManager.AddComponent(entity, ComponentType.ChunkComponent <ChunkWorldRenderBounds>()); DstEntityManager.AddComponent <WorldRenderBounds>(entity); }); }
Entity ConstructScreenSpaceCamera(Entity e, UnityEngine.RectTransform urc) { SceneSection sceneSection = DstEntityManager.GetSharedComponentData <SceneSection>(e); Entity eCam = DstEntityManager.CreateEntity(); DstEntityManager.AddSharedComponentData(eCam, sceneSection); var sizeDelta = urc.sizeDelta; var camera = new Unity.Tiny.Rendering.Camera { clearFlags = Tiny.Rendering.CameraClearFlags.DepthOnly, backgroundColor = new Unity.Tiny.Color(0, 0, 0, 0), viewportRect = new Tiny.Rect(0, 0, 1, 1), depth = 0.0f, fov = sizeDelta.y * 0.5f, mode = ProjectionMode.Orthographic, clipZNear = 0, clipZFar = 102, aspect = sizeDelta.x / sizeDelta.y }; DstEntityManager.AddComponentData(eCam, camera); DstEntityManager.AddComponentData(eCam, new Unity.Tiny.Rendering.CameraMask { mask = (ulong)(1 << urc.gameObject.layer) }); // For CameraSettings2D float3 customSortAxisSetting = new float3(0, 0, 1.0f); if (UnityEngine.Rendering.GraphicsSettings.transparencySortMode == UnityEngine.TransparencySortMode.CustomAxis) { customSortAxisSetting = UnityEngine.Rendering.GraphicsSettings.transparencySortAxis; } DstEntityManager.AddComponentData(eCam, new Unity.Tiny.Rendering.CameraSettings2D { customSortAxis = customSortAxisSetting }); // tag the camera as auto aspect DstEntityManager.AddComponentData(eCam, new CameraAutoAspectFromNode { Node = Entity.Null }); DstEntityManager.AddComponentData(eCam, new LocalToWorld { Value = float4x4.identity }); DstEntityManager.AddComponentData(eCam, new Translation { Value = new float3(sizeDelta.x / 2, sizeDelta.y / 2, -10) }); DstEntityManager.AddComponentData(eCam, new Rotation { Value = quaternion.identity }); DstEntityManager.AddComponent <UICamera>(eCam); return(eCam); }
private void ConvertSprite(Sprite sprite) { var assetEntity = GetPrimaryEntity(sprite); DstEntityManager.AddSharedComponentData(assetEntity, new SpriteAsset { Value = sprite }); DstEntityManager.AddComponent <SpriteVertexData>(assetEntity); }
protected override void OnUpdate() { Entities.ForEach((UnityEngine.Sprite sprite) => { var proxyEntity = GetPrimaryEntity(sprite); DstEntityManager.AddSharedComponentData(proxyEntity, new SpriteProxy { Sprite = sprite }); }); }
protected override void OnUpdate() { Entities.ForEach((UnityEngine.Material uMaterial) => { var proxyEntity = GetPrimaryEntity(uMaterial); DstEntityManager.AddSharedComponentData(proxyEntity, new Material2DProxy { Material = uMaterial }); }); }
private void Convert(Camera cam) { var entity = GetPrimaryEntity(cam); AddHybridComponent(cam); DstEntityManager.AddSharedComponentData(entity, new HybridCamera { Camera = cam }); }
protected override void OnUpdate() { Entities .ForEach((ColorSharedComponentTest c) => { var e = GetPrimaryEntity(c); var color = new float4(c.color.r, c.color.g, c.color.b, c.color.a); DstEntityManager.AddSharedComponentData(e, new ColorSharedComponent { Value = color }); }); }
protected override void OnUpdate() { Entities.ForEach((Canvas canvas) => { var parent = canvas.transform.parent; if (parent != null) { #if UNITY_EDITOR UnityEditor.EditorGUIUtility.PingObject(canvas); #endif throw new NotSupportedException($"{canvas.name} is child of {parent.name}, this is not supported!"); } var entity = GetPrimaryEntity(canvas); var canvasScaler = canvas.GetComponent <CanvasScaler>(); DstEntityManager.RemoveComponent <Anchor>(entity); DstEntityManager.AddSharedComponentData(entity, new CanvasSortOrder { Value = canvas.sortingOrder }); DstEntityManager.AddComponentData(entity, new DirtyTag { }); if (!sortOrders.Contains(canvas.sortingOrder)) { sortOrders.Add(canvas.sortingOrder); } switch (canvasScaler.uiScaleMode) { case CanvasScaler.ScaleMode.ScaleWithScreenSize: DstEntityManager.AddComponentData(entity, new ReferenceResolution { Value = canvasScaler.referenceResolution }); // TODO: Should figure out if I want to support shrinking and expanding only... if (canvasScaler.screenMatchMode == CanvasScaler.ScreenMatchMode.MatchWidthOrHeight) { DstEntityManager.AddComponentData(entity, new WidthHeightRatio { Value = canvasScaler.matchWidthOrHeight }); } else { throw new NotSupportedException($"{canvasScaler.screenMatchMode} is not supported!"); } break; default: throw new NotSupportedException($"{canvasScaler.uiScaleMode} is not supported!"); } }); }
protected override void OnUpdate() { ForEach((MeshRenderer meshRenderer, MeshFilter meshFilter) => { var entity = GetPrimaryEntity(meshRenderer); var dst = new RenderMesh(); dst.mesh = meshFilter.sharedMesh; dst.castShadows = meshRenderer.shadowCastingMode; dst.receiveShadows = meshRenderer.receiveShadows; var materials = meshRenderer.sharedMaterials; if (materials.Length == 1 && AttachToPrimaryEntityForSingleMaterial) { dst.material = materials[0]; dst.subMesh = 0; DstEntityManager.AddSharedComponentData(entity, dst); DstEntityManager.AddComponentData(entity, new PerInstanceCullingTag()); } else { for (int m = 0; m != materials.Length; m++) { var meshEntity = CreateAdditionalEntity(meshRenderer); dst.material = materials[m]; dst.subMesh = m; DstEntityManager.AddSharedComponentData(meshEntity, dst); DstEntityManager.AddComponentData(meshEntity, new PerInstanceCullingTag()); //@TODO: Shouldn't be necessary to add Position Component, but looks like TransformSystem doesn't setup LocalToWorld otherwise... DstEntityManager.AddComponentData(meshEntity, new Position()); // Parent it var attach = CreateAdditionalEntity(meshRenderer); DstEntityManager.AddComponentData(attach, new Attach { Parent = entity, Child = meshEntity }); } } //@TODO: Transform system should handle RenderMeshFlippedWindingTag // Flag this thing as positively or negatively scaled, so we can batch the renders correctly for the static case. //if (math.determinant(localToWorld) < 0.0) // entityManager.AddComponent(meshEnt, ComponentType.Create<RenderMeshFlippedWindingTag>()); }); }
protected override void OnUpdate() { Entities.ForEach((TextMeshPro textMesh, MeshFilter meshFilter) => { // We must disable the text mesh for it to be skipped by MeshRenderer conversion system meshFilter.mesh = null; var font = textMesh.font; var entity = GetPrimaryEntity(textMesh); if (!m_textFontAssets.TryGetValue(font, out var fontEntity)) { fontEntity = TextUtility.CreateTextFontAsset(DstEntityManager, font); m_textFontAssets.Add(font, fontEntity); } DstEntityManager.AddSharedComponentData(entity, new FontMaterial { Value = font.material }); var materialId = DstEntityManager.GetSharedComponentDataIndex <FontMaterial>(entity); DstEntityManager.AddComponentData(entity, new TextRenderer() { Font = fontEntity, MaterialId = materialId, Size = textMesh.fontSize, Alignment = textMesh.alignment, Bold = (textMesh.fontStyle & FontStyles.Bold) == FontStyles.Bold, Italic = (textMesh.fontStyle & FontStyles.Italic) == FontStyles.Italic }); DstEntityManager.AddComponentData(entity, new TextData { Value = textMesh.text }); DstEntityManager.AddComponentData(entity, new VertexColor() { Value = textMesh.color.ToFloat4() }); DstEntityManager.AddComponentData(entity, new VertexColorMultiplier() { Value = new float4(1.0f, 1.0f, 1.0f, 1.0f) }); DstEntityManager.AddBuffer <Vertex>(entity); DstEntityManager.AddBuffer <VertexIndex>(entity); DstEntityManager.AddBuffer <TextLine>(entity); if (!DstEntityManager.HasComponent <RenderBounds>(entity)) { // RenderBounds will be calculated on TextMeshBuildSystem DstEntityManager.AddComponentData(entity, default(RenderBounds)); } }); }
protected override void OnUpdate() { if (Settings == null) { return; } if (TryGetBuildConfigurationComponent <DotsRuntimeBuildProfile>(out var profile)) { if (profile.UseNewPipeline) { if (!IsExportingRootScene()) { return; } } } // Get render settings from the current active scene Entity e = DstEntityManager.CreateEntity(); // Render settings should go into the main section of the subscene they are coming from DstEntityManager.AddSharedComponentData(e, new SceneSection() { SceneGUID = Settings.SceneGUID, Section = 0 }); // Ambient light DstEntityManager.AddComponentData <Unity.Tiny.Rendering.Light>(e, new Unity.Tiny.Rendering.Light() { color = new float3(RenderSettings.ambientLight.r, RenderSettings.ambientLight.g, RenderSettings.ambientLight.b), intensity = 1.0f }); DstEntityManager.AddComponent <Unity.Tiny.Rendering.AmbientLight>(e); // Fog var fogLinear = RenderSettings.fogColor.linear; DstEntityManager.AddComponentData <Unity.Tiny.Rendering.Fog>(e, new Unity.Tiny.Rendering.Fog() { mode = RenderSettings.fogMode.ToTiny(RenderSettings.fog), color = new float4(fogLinear.r, fogLinear.g, fogLinear.b, fogLinear.a), density = RenderSettings.fogDensity, startDistance = RenderSettings.fogStartDistance, endDistance = RenderSettings.fogEndDistance }); }
protected override void OnUpdate() { Entities.ForEach((BoidAuthoring boidAuthoring) => { var entity = GetPrimaryEntity(boidAuthoring); DstEntityManager.AddSharedComponentData(entity, new Boid { CellRadius = boidAuthoring.CellRadius, SeparationWeight = boidAuthoring.SeparationWeight, AlignmentWeight = boidAuthoring.AlignmentWeight, TargetWeight = boidAuthoring.TargetWeight, OuterDetectionRadius = boidAuthoring.OuterDetectionRadius, InnerDetectionRadius = boidAuthoring.InnerDetectionRadius, MoveSpeed = boidAuthoring.MoveSpeed, WanderRadius = boidAuthoring.WanderRadius, WanderWeight = boidAuthoring.WanderWeight, VisionAngle = boidAuthoring.VisionAngle, NavigationRayCount = boidAuthoring.NavigationRayCount, }); DynamicBuffer <Float3BufferElement> buffer = DstEntityManager.AddBuffer <Float3BufferElement>(entity); DynamicBuffer <float3> floatBuffer = buffer.Reinterpret <float3>(); for (int i = 0; i < boidAuthoring.NavigationRayCount; i++) { float turnFraction = 0.6180f; float t = i / (boidAuthoring.NavigationRayCount - 1f); float phi = math.acos(1f - 2f * t); float theta = 2 * math.PI * turnFraction * i; float x = math.sin(phi) * math.cos(theta); float y = math.sin(phi) * math.sin(theta); float z = math.cos(phi); float3 p = new float3(x, y, z); if (math.acos(math.dot(p, new float3(0, 0, 1))) < boidAuthoring.VisionAngle) { floatBuffer.Add(p); } } // Remove default transform system components DstEntityManager.RemoveComponent <Translation>(entity); DstEntityManager.RemoveComponent <Rotation>(entity); }); }
private void SetUpScreenSpaceCamera(Canvas canvas, Entity entity) { if (canvas.worldCamera == null) { throw new InvalidOperationException($"Target camera is null or destroyed. Canvas {canvas}"); } var proxy = canvas.worldCamera.GetComponent <CameraImageRenderProxy>(); if (proxy == null) { proxy = canvas.worldCamera.gameObject.AddComponent <CameraImageRenderProxy>(); } DstEntityManager.AddSharedComponentData(entity, new CanvasTargetCamera() { Target = proxy }); DstEntityManager.AddComponentData(entity, new CanvasScreenSize { Value = new int2(canvas.worldCamera.pixelWidth, canvas.worldCamera.pixelHeight) }); }
protected override void OnUpdate() { Entities.ForEach((BoidAuthoring boidAuthoring) => { var entity = GetPrimaryEntity(boidAuthoring); DstEntityManager.AddSharedComponentData(entity, new Boid { CellRadius = boidAuthoring.CellRadius, SeparationWeight = boidAuthoring.SeparationWeight, AlignmentWeight = boidAuthoring.AlignmentWeight, TargetWeight = boidAuthoring.TargetWeight, ObstacleAversionDistance = boidAuthoring.ObstacleAversionDistance, MoveSpeed = boidAuthoring.MoveSpeed }); // Remove default transform system components DstEntityManager.RemoveComponent <Translation>(entity); DstEntityManager.RemoveComponent <Rotation>(entity); }); }
protected unsafe override void OnUpdate() { var contexts = new NativeList <UIContextData>(8, Allocator.TempJob); var graphData = new NativeList <UIGraphData>(8, Allocator.TempJob); Entity schemaEntity = Entity.Null; int nodeCount = 0; meshes.Clear(); Entities.ForEach((UIObject obj) => { //TODO: Writes every conversion frame but will crash under certain conditions otherwise. Crashes observed involving opening and closing subscenes without modifying anything after script reload. var guid = obj.model?.GetOutputGuid(); if (!string.IsNullOrEmpty(guid)) { IntPtr ptr; long allocatedLength; using (var fs = File.OpenRead(UnityEditor.AssetDatabase.GUIDToAssetPath(guid))) { allocatedLength = math.ceilpow2(fs.Length); ptr = (IntPtr)UnsafeUtility.Malloc(allocatedLength, 0, Allocator.Persistent); using (var us = new UnmanagedMemoryStream((byte *)ptr.ToPointer(), 0, fs.Length, FileAccess.Write)) { fs.CopyTo(us); } } var gd = new UIGraphData { value = ptr, allocatedLength = allocatedLength }; graphData.Add(gd); nodeCount += gd.GetNodeCount(); contexts.Add(UIContextData.CreateContext(obj.camera)); meshes.Add(new Mesh()); if (schemaEntity == Entity.Null) { schemaEntity = CreateAdditionalEntity(obj); DstEntityManager.SetName(schemaEntity, "UI Schema"); DstEntityManager.AddSharedComponentData(schemaEntity, new UISchemaData { value = schema }); } DeclareAssetDependency(obj.gameObject, schema); } obj.cachedGuid = guid; }); if (graphData.Length > 0) { var graphDataArray = graphData.AsArray(); var meshData = Mesh.AllocateWritableMeshData(graphData.Length); var submeshes = new NativeArray <int>(graphData.Length, Allocator.TempJob); var stream = new NativeStream(nodeCount, Allocator.TempJob); new UILayoutJob { schema = compiledSchema, graphs = graphDataArray, contexts = contexts, meshDataArray = meshData }.Schedule(graphData.Length, 1).Complete(); new UINodeDecompositionJob { schema = compiledSchema, graphs = graphDataArray, nodes = stream.AsWriter(), submeshCount = submeshes }.Schedule(graphData.Length, 1).Complete(); Mesh.ApplyAndDisposeWritableMeshData(meshData, meshes); var result = stream.ToNativeArray <DedicatedNodeInfo>(Allocator.Temp); var nodes = new NativeMultiHashMap <int, DedicatedNodeInfo>(graphData.Length, Allocator.Temp); for (int i = 0; i < result.Length; i++) { nodes.Add(result[i].graphIndex, result[i]); } stream.Dispose(); submeshes.Dispose(); int index = 0; var nodeEntities = new NativeList <Entity>(Allocator.Temp); Entities.ForEach((UIObject obj) => { if (!string.IsNullOrEmpty(obj.cachedGuid)) { var entity = GetPrimaryEntity(obj); var gd = graphDataArray[index]; DstEntityManager.AddComponentData(entity, new UIGraph { value = new BlittableAssetReference(obj.cachedGuid) }); DstEntityManager.AddSharedComponentData <UIDirtyState>(entity, false); Material material; if (gd.TryGetConfigBlock(0, UIConfigLayoutTable.MaterialConfig, out IntPtr result)) { material = UnityEditor.AssetDatabase.LoadAssetAtPath <Material>(UnityEditor.AssetDatabase.GUIDToAssetPath(((MaterialConfig *)(result.ToPointer()))->material.ToHex())); } else { material = obj.model.GetMaterial(); } DeclareAssetDependency(obj.gameObject, obj.model); DeclareAssetDependency(obj.gameObject, material); DstEntityManager.AddSharedComponentData(entity, new RenderMesh { mesh = meshes[index], material = material, subMesh = 0, castShadows = ShadowCastingMode.Off, receiveShadows = false, needMotionVectorPass = false, layer = obj.gameObject.layer }); DstEntityManager.AddComponentData(entity, new UIPixelScale { value = obj.pixelScale }); var bounds = meshes[index].GetSubMesh(0).bounds.ToAABB(); DstEntityManager.AddComponentData(entity, new RenderBounds { Value = bounds }); DstEntityManager.AddComponent <UIContext>(entity); if (obj.camera != null) { DstEntityManager.AddComponentData(entity, new UIContextSource { value = GetPrimaryEntity(obj.camera) }); var ltc = new LocalToCamera { cameraLTW = obj.camera.transform.localToWorldMatrix, clipPlane = new float2(obj.camera.nearClipPlane, obj.camera.farClipPlane), alignment = obj.alignment, offsetX = obj.offsetX, offsetY = obj.offsetY }; DstEntityManager.AddComponentData(entity, ltc); var rotation = quaternion.LookRotation(ltc.cameraLTW.c2.xyz, ltc.cameraLTW.c1.xyz); var translate = ltc.cameraLTW.c3.xyz + new float3(ltc.alignment.GetOffset(bounds.Size.xy, new float2(Screen.currentResolution.height * obj.camera.aspect, Screen.currentResolution.height)), 0) + math.mul(rotation, math.forward() * ltc.clipPlane.x * 2f) + (math.mul(rotation, math.right()) * ltc.offsetX.Normalize(contexts[index])) + (math.mul(rotation, math.up()) * ltc.offsetY.Normalize(contexts[index])); DstEntityManager.SetComponentData(entity, new LocalToWorld { Value = float4x4.TRS(translate, rotation, obj.pixelScale) }); DeclareDependency(obj, obj.camera); } DstEntityManager.AddComponent <PerInstanceCullingTag>(entity); nodeEntities.Clear(); var nodeInfoIter = nodes.GetValuesForKey(index); while (nodeInfoIter.MoveNext()) { var nodeInfo = nodeInfoIter.Current; var nodeEntity = CreateAdditionalEntity(obj); var name = graphData[index].GetNodeName(nodeInfo.nodeIndex); if (string.IsNullOrEmpty(name)) { name = $"Node#{nodeInfo.nodeIndex}"; } DstEntityManager.SetName(nodeEntity, $"{DstEntityManager.GetName(entity)}[{name}]"); DstEntityManager.AddComponentData(nodeEntity, new UINodeInfo { index = nodeInfo.nodeIndex, submesh = nodeInfo.submesh }); DstEntityManager.AddComponentData(nodeEntity, new UIParent { value = entity }); DstEntityManager.AddComponentData(nodeEntity, new Parent { Value = entity }); DstEntityManager.AddComponentData(nodeEntity, new LocalToWorld { Value = float4x4.identity }); DstEntityManager.AddComponentData(nodeEntity, new Rotation { Value = quaternion.identity }); DstEntityManager.AddComponentData(nodeEntity, new Scale { Value = 1f }); DstEntityManager.AddComponentData(nodeEntity, new LocalToParent { Value = float4x4.identity }); if (gd.TryGetConfigBlock(0, UIConfigLayoutTable.MaterialConfig, out result)) { material = UnityEditor.AssetDatabase.LoadAssetAtPath <Material>(UnityEditor.AssetDatabase.GUIDToAssetPath(((MaterialConfig *)result.ToPointer())->material.ToHex())); } else { material = obj.model.GetMaterial(); } DstEntityManager.AddSharedComponentData(nodeEntity, new RenderMesh { mesh = meshes[index], material = material, subMesh = nodeInfo.submesh, castShadows = ShadowCastingMode.Off, receiveShadows = false, needMotionVectorPass = false, layer = obj.gameObject.layer }); DstEntityManager.AddComponentData(nodeEntity, new RenderBounds { Value = meshes[index].GetSubMesh(nodeInfo.submesh).bounds.ToAABB() }); DstEntityManager.AddComponent <PerInstanceCullingTag>(nodeEntity); nodeEntities.Add(nodeEntity); ConfigureEditorRenderData(nodeEntity, obj.gameObject, true); } var buffer = DstEntityManager.AddBuffer <UINode>(entity); buffer.AddRange(nodeEntities.AsArray().Reinterpret <UINode>()); UnsafeUtility.Free(graphData[index].value.ToPointer(), Allocator.TempJob); index++; ConfigureEditorRenderData(entity, obj.gameObject, true); } }); } contexts.Dispose(); graphData.Dispose(); }
protected override void OnUpdate() { if (Settings == null) { return; } if (TryGetBuildConfigurationComponent <DotsRuntimeBuildProfile>(out var profile)) { if (!IsExportingRootScene()) { return; } } // Get render settings from the current active scene Entity e = DstEntityManager.CreateEntity(); // Render settings should go into the main section of the subscene they are coming from DstEntityManager.AddSharedComponentData(e, new SceneSection() { SceneGUID = Settings.SceneGUID, Section = 0 }); // Ambient light { var ambientLight = new Unity.Tiny.Rendering.AmbientLight { ambientSkyColor = ToFloat3(RenderSettings.ambientSkyColor), // used only for selection when multiple render settings are present. intensity = 1.0f, }; if (RenderSettings.ambientMode == UnityEngine.Rendering.AmbientMode.Flat) { ambientLight.SetAmbientColor(ToFloat3(RenderSettings.ambientSkyColor.linear)); } else if (RenderSettings.ambientMode == UnityEngine.Rendering.AmbientMode.Trilight) { ambientLight.SetAmbientColor( ToFloat3(RenderSettings.ambientSkyColor.linear), ToFloat3(RenderSettings.ambientEquatorColor.linear), ToFloat3(RenderSettings.ambientGroundColor.linear) ); } else { ambientLight.ambientProbe = ToSHCoefficients(RenderSettings.ambientProbe); } DstEntityManager.AddComponentData(e, ambientLight); } // Fog var fogLinear = RenderSettings.fogColor.linear; DstEntityManager.AddComponentData <Unity.Tiny.Rendering.Fog>(e, new Unity.Tiny.Rendering.Fog() { mode = RenderSettings.fogMode.ToTiny(RenderSettings.fog), color = new float4(fogLinear.r, fogLinear.g, fogLinear.b, fogLinear.a), density = RenderSettings.fogDensity, startDistance = RenderSettings.fogStartDistance, endDistance = RenderSettings.fogEndDistance }); }
protected override void OnUpdate() { var sceneBounds = MinMaxAABB.Empty; var materials = new List <Material>(10); Entities.ForEach((MeshRenderer meshRenderer, MeshFilter meshFilter) => { var entity = GetPrimaryEntity(meshRenderer); var mesh = meshFilter.sharedMesh; meshRenderer.GetSharedMaterials(materials); var materialCount = materials.Count; // Don't add RenderMesh (and other required components) unless both mesh and material assigned. if ((mesh != null) && (materialCount > 0)) { var dst = new RenderMesh(); dst.mesh = mesh; dst.castShadows = meshRenderer.shadowCastingMode; dst.receiveShadows = meshRenderer.receiveShadows; dst.layer = meshRenderer.gameObject.layer; //@TODO: Transform system should handle RenderMeshFlippedWindingTag automatically. This should not be the responsibility of the conversion system. float4x4 localToWorld = meshRenderer.transform.localToWorldMatrix; var flipWinding = math.determinant(localToWorld) < 0.0; if (materialCount == 1 && AttachToPrimaryEntityForSingleMaterial) { dst.material = materials[0]; dst.subMesh = 0; DstEntityManager.AddSharedComponentData(entity, dst); DstEntityManager.AddComponentData(entity, new PerInstanceCullingTag()); DstEntityManager.AddComponentData(entity, new RenderBounds { Value = mesh.bounds.ToAABB() }); if (flipWinding) { DstEntityManager.AddComponent(entity, ComponentType.ReadWrite <RenderMeshFlippedWindingTag>()); } ConfigureEditorRenderData(entity, meshRenderer.gameObject, true); } else { for (var m = 0; m != materialCount; m++) { var meshEntity = CreateAdditionalEntity(meshRenderer); dst.material = materials[m]; dst.subMesh = m; DstEntityManager.AddSharedComponentData(meshEntity, dst); DstEntityManager.AddComponentData(meshEntity, new PerInstanceCullingTag()); DstEntityManager.AddComponentData(meshEntity, new RenderBounds { Value = mesh.bounds.ToAABB() }); DstEntityManager.AddComponentData(meshEntity, new LocalToWorld { Value = localToWorld }); if (!DstEntityManager.HasComponent <Static>(meshEntity)) { DstEntityManager.AddComponentData(meshEntity, new Parent { Value = entity }); DstEntityManager.AddComponentData(meshEntity, new LocalToParent { Value = float4x4.identity }); } if (flipWinding) { DstEntityManager.AddComponent(meshEntity, ComponentType.ReadWrite <RenderMeshFlippedWindingTag>()); } ConfigureEditorRenderData(meshEntity, meshRenderer.gameObject, true); } } sceneBounds.Encapsulate(meshRenderer.bounds.ToAABB()); } }); }
protected override void OnUpdate() { using (var context = new BlobAssetComputationContext <int, GhostPrefabMetaData>(BlobAssetStore, 16, Allocator.Temp)) { Entities.ForEach((GhostAuthoringComponent ghostAuthoring) => { bool isPrefab = !ghostAuthoring.gameObject.scene.IsValid() || ghostAuthoring.ForcePrefabConversion; var target = GetConversionTarget(this, isPrefab); // Check if the ghost is valid before starting to process if (String.IsNullOrEmpty(ghostAuthoring.prefabId)) { throw new InvalidOperationException($"The ghost {ghostAuthoring.gameObject.name} is not a valid prefab, all ghosts must be the top-level GameObject in a prefab. Ghost instances in scenes must be instances of such prefabs and changes should be made on the prefab asset, not the prefab instance"); } if (!isPrefab && ghostAuthoring.DefaultGhostMode == GhostAuthoringComponent.GhostMode.OwnerPredicted && target != NetcodeConversionTarget.Server) { throw new InvalidOperationException($"Cannot convert a owner predicted ghost {ghostAuthoring.Name} as a scene instance"); } if (!isPrefab && DstEntityManager.World.GetExistingSystem <ClientSimulationSystemGroup>() != null) { throw new InvalidOperationException($"The ghost {ghostAuthoring.gameObject.name} cannot be created on the client, either put it in a sub-scene or spawn it on the server only"); } if (ghostAuthoring.prefabId.Length != 32) { throw new InvalidOperationException("Invalid guid for ghost prefab type"); } // All ghosts should have a linked entity group DeclareLinkedEntityGroup(ghostAuthoring.gameObject); var entity = GetPrimaryEntity(ghostAuthoring); // Generate a ghost type component so the ghost can be identified by mathcing prefab asset guid var ghostType = new GhostTypeComponent(); ghostType.guid0 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(0, 8), 16); ghostType.guid1 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(8, 8), 16); ghostType.guid2 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(16, 8), 16); ghostType.guid3 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(24, 8), 16); DstEntityManager.AddComponentData(entity, ghostType); // FIXME: maybe stripping should be individual systems running before this to make sure it can be changed in a way that always triggers a reconvert - and to avoid reflection var components = DstEntityManager.GetComponentTypes(entity); if (target != NetcodeConversionTarget.Client) { // If this ghost should be usable on a server we must add a shared ghost type to make sure different ghost types // with the same archetype end up in different chunks. If conversion is client and server the client needs to remove // this at runtime DstEntityManager.AddSharedComponentData(entity, new SharedGhostTypeComponent { SharedValue = ghostType }); } if (target != NetcodeConversionTarget.Server) { // Converting to client or client and server, if client and server this should be stripped from servers at runtime DstEntityManager.AddComponentData(entity, new SnapshotData()); DstEntityManager.AddBuffer <SnapshotDataBuffer>(entity); } // All types have the ghost components DstEntityManager.AddComponentData(entity, new GhostComponent()); // No need to add the predicted ghost component for interpolated only ghosts if the data is only used by the client if (target != NetcodeConversionTarget.Client || ghostAuthoring.SupportedGhostModes != GhostAuthoringComponent.GhostModeMask.Interpolated) { DstEntityManager.AddComponentData(entity, new PredictedGhostComponent()); } if (target == NetcodeConversionTarget.Server) { // If converting server-only data we can remove all components which are not used on the server foreach (var comp in components) { var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>(); if (attr != null && (attr.PrefabType & GhostPrefabType.Server) == 0) { DstEntityManager.RemoveComponent(entity, comp); } } } else if (target == NetcodeConversionTarget.Client) { // If converting client-only data we can remove all components which are not used on the client // If the ghost is interpolated only we can also remove all componens which are not used on interpolated clients, // and if it is predicted only we can remove everything which is not used on predicted clients foreach (var comp in components) { var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>(); if (attr == null) { continue; } if ((attr.PrefabType & GhostPrefabType.Client) == 0) { DstEntityManager.RemoveComponent(entity, comp); } else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Interpolated && (attr.PrefabType & GhostPrefabType.InterpolatedClient) == 0) { DstEntityManager.RemoveComponent(entity, comp); } else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Predicted && (attr.PrefabType & GhostPrefabType.PredictedClient) == 0) { DstEntityManager.RemoveComponent(entity, comp); } } } // Even if converting for client and server we can remove components which are only for predicted clients when // the ghost is always interpolated, or components which are only for interpolated clients if the ghost is always // predicted else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Interpolated) { foreach (var comp in components) { var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>(); if (attr != null && (attr.PrefabType & (GhostPrefabType.InterpolatedClient | GhostPrefabType.Server)) == 0) { DstEntityManager.RemoveComponent(entity, comp); } } } else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Predicted) { foreach (var comp in components) { var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>(); if (attr != null && (attr.PrefabType & (GhostPrefabType.PredictedClient | GhostPrefabType.Server)) == 0) { DstEntityManager.RemoveComponent(entity, comp); } } } // This logic needs to match the logic creating LinkedEntityGroups, gather a list of all child entities var linkedEntities = new NativeList <Entity>(1, Allocator.Temp); var selfAndChildren = ghostAuthoring.gameObject.GetComponentsInChildren <Transform>(true); foreach (var transform in selfAndChildren) { foreach (var child in GetEntities(transform.gameObject)) { if (DstEntityManager.Exists(child)) { linkedEntities.Add(child); } } } // Mark all child entities as ghost children, entity 0 is the root and hsould not be marked for (int i = 1; i < linkedEntities.Length; ++i) { DstEntityManager.AddComponentData(linkedEntities[i], default(GhostChildEntityComponent)); } if (isPrefab) { var contentHash = TypeHash.FNV1A64(ghostAuthoring.Importance); contentHash = TypeHash.CombineFNV1A64(contentHash, TypeHash.FNV1A64((int)ghostAuthoring.SupportedGhostModes)); contentHash = TypeHash.CombineFNV1A64(contentHash, TypeHash.FNV1A64((int)ghostAuthoring.DefaultGhostMode)); contentHash = TypeHash.CombineFNV1A64(contentHash, TypeHash.FNV1A64((int)ghostAuthoring.OptimizationMode)); contentHash = TypeHash.CombineFNV1A64(contentHash, TypeHash.FNV1A64(ghostAuthoring.Name.ToString())); foreach (var comp in components) { contentHash = TypeHash.CombineFNV1A64(contentHash, TypeManager.GetTypeInfo(comp.TypeIndex).StableTypeHash); var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>(); if (attr != null) { contentHash = TypeHash.CombineFNV1A64(contentHash, TypeHash.FNV1A64((int)attr.PrefabType)); } } var blobHash = new Unity.Entities.Hash128(ghostType.guid0 ^ (uint)(contentHash >> 32), ghostType.guid1 ^ (uint)(contentHash), ghostType.guid2, ghostType.guid3); context.AssociateBlobAssetWithUnityObject(blobHash, ghostAuthoring.gameObject); if (context.NeedToComputeBlobAsset(blobHash)) { var builder = new BlobBuilder(Allocator.Temp); ref var root = ref builder.ConstructRoot <GhostPrefabMetaData>(); // Store importance, supported modes, default mode and name in the meta data blob asset root.Importance = ghostAuthoring.Importance; root.SupportedModes = GhostPrefabMetaData.GhostMode.Both; root.DefaultMode = GhostPrefabMetaData.GhostMode.Interpolated; if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Interpolated) { root.SupportedModes = GhostPrefabMetaData.GhostMode.Interpolated; } else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Predicted) { root.SupportedModes = GhostPrefabMetaData.GhostMode.Predicted; root.DefaultMode = GhostPrefabMetaData.GhostMode.Predicted; } else if (ghostAuthoring.DefaultGhostMode == GhostAuthoringComponent.GhostMode.OwnerPredicted) { if (!DstEntityManager.HasComponent <GhostOwnerComponent>(entity)) { throw new InvalidOperationException("OwnerPrediction mode can only be used on prefabs which have a GhostOwnerComponent"); } root.DefaultMode = GhostPrefabMetaData.GhostMode.Both; } else if (ghostAuthoring.DefaultGhostMode == GhostAuthoringComponent.GhostMode.Predicted) { root.DefaultMode = GhostPrefabMetaData.GhostMode.Predicted; } root.StaticOptimization = (ghostAuthoring.OptimizationMode == GhostAuthoringComponent.GhostOptimizationMode.Static); builder.AllocateString(ref root.Name, ghostAuthoring.Name); var serverComponents = new NativeList <ulong>(components.Length, Allocator.Temp); var removeOnServer = new NativeList <ulong>(components.Length, Allocator.Temp); var removeOnClient = new NativeList <ulong>(components.Length, Allocator.Temp); var disableOnPredicted = new NativeList <ulong>(components.Length, Allocator.Temp); var disableOnInterpolated = new NativeList <ulong>(components.Length, Allocator.Temp); // Snapshot data buffers should be removed from the server, and shared ghost type from the client removeOnServer.Add(TypeManager.GetTypeInfo(ComponentType.ReadWrite <SnapshotData>().TypeIndex).StableTypeHash); removeOnServer.Add(TypeManager.GetTypeInfo(ComponentType.ReadWrite <SnapshotDataBuffer>().TypeIndex).StableTypeHash); removeOnClient.Add(TypeManager.GetTypeInfo(ComponentType.ReadWrite <SharedGhostTypeComponent>().TypeIndex).StableTypeHash); // If both interpolated and predicted clients are supported the interpolated client needs to disable the prediction component // If the ghost is interpolated only the prediction component can be removed on clients if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.All) { disableOnInterpolated.Add(TypeManager.GetTypeInfo(ComponentType.ReadWrite <PredictedGhostComponent>().TypeIndex).StableTypeHash); } else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Interpolated) { removeOnClient.Add(TypeManager.GetTypeInfo(ComponentType.ReadWrite <PredictedGhostComponent>().TypeIndex).StableTypeHash); } foreach (var comp in components) { var hash = TypeManager.GetTypeInfo(comp.TypeIndex).StableTypeHash; var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>(); if (attr == null) { serverComponents.Add(hash); continue; } if ((attr.PrefabType & GhostPrefabType.Server) == 0) { removeOnServer.Add(hash); } else { serverComponents.Add(hash); } // If something is not used on the client, remove it. Make sure to include things that is interpolated only if ghost // is predicted only and the other way around if ((attr.PrefabType & GhostPrefabType.Client) == 0) { removeOnClient.Add(hash); } else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Interpolated && (attr.PrefabType & GhostPrefabType.InterpolatedClient) == 0) { removeOnClient.Add(hash); } else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Predicted && (attr.PrefabType & GhostPrefabType.PredictedClient) == 0) { removeOnClient.Add(hash); } // If the prefab only supports a single mode on the client there is no need to enable / disable, if is handled by the // previous loop removing components on the client instead if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.All) { // Components available on predicted but not interpolated should be disabled on interpolated clients if ((attr.PrefabType & GhostPrefabType.InterpolatedClient) == 0 && (attr.PrefabType & GhostPrefabType.PredictedClient) != 0) { disableOnInterpolated.Add(hash); } if ((attr.PrefabType & GhostPrefabType.InterpolatedClient) != 0 && (attr.PrefabType & GhostPrefabType.PredictedClient) == 0) { disableOnPredicted.Add(hash); } } } var blobServerComponents = builder.Allocate(ref root.ServerComponentList, serverComponents.Length); for (int i = 0; i < serverComponents.Length; ++i) { blobServerComponents[i] = serverComponents[i]; } // A pre-spawned instance can be created in ClientServer even if the prefab is not, so anything which should // be usable on the server needs to know what to remove from the server version if (target != NetcodeConversionTarget.Client) { // Client only data never needs information about the server var blobRemoveOnServer = builder.Allocate(ref root.RemoveOnServer, removeOnServer.Length); for (int i = 0; i < removeOnServer.Length; ++i) { blobRemoveOnServer[i] = removeOnServer[i]; } } else { builder.Allocate(ref root.RemoveOnServer, 0); } if (target != NetcodeConversionTarget.Server) { var blobRemoveOnClient = builder.Allocate(ref root.RemoveOnClient, removeOnClient.Length); for (int i = 0; i < removeOnClient.Length; ++i) { blobRemoveOnClient[i] = removeOnClient[i]; } } else { builder.Allocate(ref root.RemoveOnClient, 0); } if (target != NetcodeConversionTarget.Server) { // The data for interpolated / predicted diff is required unless this is server-only var blobDisableOnPredicted = builder.Allocate(ref root.DisableOnPredictedClient, disableOnPredicted.Length); for (int i = 0; i < disableOnPredicted.Length; ++i) { blobDisableOnPredicted[i] = disableOnPredicted[i]; } var blobDisableOnInterpolated = builder.Allocate(ref root.DisableOnInterpolatedClient, disableOnInterpolated.Length); for (int i = 0; i < disableOnInterpolated.Length; ++i) { blobDisableOnInterpolated[i] = disableOnInterpolated[i]; } } else { builder.Allocate(ref root.DisableOnPredictedClient, 0); builder.Allocate(ref root.DisableOnInterpolatedClient, 0); } var blobAsset = builder.CreateBlobAssetReference <GhostPrefabMetaData>(Allocator.Persistent); context.AddComputedBlobAsset(blobHash, blobAsset); } context.GetBlobAsset(blobHash, out var blob); DstEntityManager.AddComponentData(entity, new GhostPrefabMetaDataComponent { Value = blob }); } });
protected override void OnUpdate() { var hashToEntity = new NativeHashMap <ulong, Entity>(128, Allocator.TempJob); // TODO: Check that the GhostAuthoringComponent is interpolated, as we don't support predicted atm Entities.ForEach((GhostAuthoringComponent ghostAuthoring) => { var entity = GetPrimaryEntity(ghostAuthoring); var isInSubscene = DstEntityManager.HasComponent <SceneSection>(entity); bool isPrefab = !ghostAuthoring.gameObject.scene.IsValid() || ghostAuthoring.ForcePrefabConversion; var activeInScene = ghostAuthoring.gameObject.activeInHierarchy; if (!isPrefab && isInSubscene && activeInScene) { var hashData = new NativeList <ulong>(Allocator.TempJob); var componentTypes = DstEntityManager.GetComponentTypes(entity, Allocator.TempJob); // Hash all the data on the entity (first each component data then all together) for (int i = 0; i < componentTypes.Length; ++i) { // Do not include components which might be included or not included depending on if you are a // client or a server // TODO: Check the interpolated/predicted/server bools instead // Only iterate ghostAuthoring.Components // Should skip PhysicsCollider, WorldRenderBounds, XXXSnapshotData, PredictedGhostComponent if (componentTypes[i] == typeof(Translation) || componentTypes[i] == typeof(Rotation)) { var componentDataHash = ComponentDataToHash(entity, componentTypes[i]); hashData.Add(componentDataHash); } } hashData.Sort(); ulong combinedComponentHash; unsafe { combinedComponentHash = Unity.Core.XXHash.Hash64((byte *)hashData.GetUnsafeReadOnlyPtr(), hashData.Length * sizeof(ulong)); } // When duplicating a scene object it will have the same position/rotation as the original, so until that // changes there will always be a duplicate hash until it's moved to it's own location if (!hashToEntity.ContainsKey(combinedComponentHash)) { hashToEntity.Add(combinedComponentHash, entity); } componentTypes.Dispose(); hashData.Dispose(); } }); if (hashToEntity.Count() > 0) { var keys = hashToEntity.GetKeyArray(Allocator.TempJob); keys.Sort(); // Assign ghost IDs to the pre-spawned entities sorted by component data hash for (int i = 0; i < keys.Length; ++i) { DstEntityManager.AddComponentData(hashToEntity[keys[i]], new PreSpawnedGhostId { Value = i + 1 }); } // Save the final subscene hash with all the pre-spawned ghosts unsafe { var hash = Unity.Core.XXHash.Hash64((byte *)keys.GetUnsafeReadOnlyPtr(), keys.Length * sizeof(ulong)); for (int i = 0; i < keys.Length; ++i) { // Track the subscene which is the parent of this entity DstEntityManager.AddSharedComponentData(hashToEntity[keys[i]], new SubSceneGhostComponentHash { Value = hash }); } } keys.Dispose(); } hashToEntity.Dispose(); }
protected override void OnUpdate() { var typeLookup = new Dictionary <string, Type>(); var allTypes = TypeManager.GetAllTypes(); foreach (var compType in allTypes) { if (compType.Category == TypeManager.TypeCategory.BufferData && compType.Type != null && compType.Type.Name.EndsWith("SnapshotData")) { if (typeLookup.ContainsKey(compType.Type.Name)) { throw new InvalidOperationException( $"Found multiple snapshot data types named {compType.Type.Name}, namespaces are not fully supported for snapshot data"); } typeLookup.Add(compType.Type.Name, compType.Type); } } Entities.ForEach((GhostAuthoringComponent ghostAuthoring) => { if (String.IsNullOrEmpty(ghostAuthoring.prefabId)) { throw new InvalidOperationException($"The ghost {ghostAuthoring.gameObject.name} is not a valid prefab, all ghosts must be the top-level GameObject in a prefab. Ghost instances in scenes must be instances of such prefabs."); } DeclareLinkedEntityGroup(ghostAuthoring.gameObject); if (ghostAuthoring.doNotStrip) { return; } var entity = GetPrimaryEntity(ghostAuthoring); var target = GetConversionTarget(this); // FIXME: A2 hack if (target == NetcodeConversionTarget.Undefined) { // throw new InvalidOperationException($"A ghost prefab can only be created in the client or server world, not {DstEntityManager.World.Name}"); Debug.LogWarning( $"A ghost prefab can only be created in the client or server world, not {DstEntityManager.World.Name}.\nDefaulting to server conversion."); target = NetcodeConversionTarget.Server; } if (ghostAuthoring.prefabId.Length != 32) { throw new InvalidOperationException("Invalid guid for ghost prefab type"); } var ghostType = new GhostTypeComponent(); ghostType.guid0 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(0, 8), 16); ghostType.guid1 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(8, 8), 16); ghostType.guid2 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(16, 8), 16); ghostType.guid3 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(24, 8), 16); DstEntityManager.AddComponentData(entity, ghostType); var toRemove = new HashSet <string>(); if (target == NetcodeConversionTarget.Server) { // Make sure different ghost types are in different chunks DstEntityManager.AddSharedComponentData(entity, new SharedGhostTypeComponent { SharedValue = ghostType }); DstEntityManager.AddComponentData(entity, new GhostComponent()); DstEntityManager.AddComponentData(entity, new PredictedGhostComponent()); // Create server version of prefab foreach (var comp in ghostAuthoring.Components) { if (!comp.server && comp.entityIndex == 0) { toRemove.Add(comp.name); } } } else if (target == NetcodeConversionTarget.Client) { var snapshotTypeName = $"{ghostAuthoring.name}SnapshotData"; if (!typeLookup.TryGetValue(snapshotTypeName, out var snapshotType)) { throw new InvalidOperationException( $"Could not find snapshot data {snapshotTypeName}, did you generate the ghost code?"); } DstEntityManager.AddComponent(entity, snapshotType); DstEntityManager.AddComponentData(entity, new GhostComponent()); if (ghostAuthoring.DefaultClientInstantiationType == GhostAuthoringComponent.ClientInstantionType.Interpolated) { foreach (var comp in ghostAuthoring.Components) { if (!comp.interpolatedClient && comp.entityIndex == 0) { toRemove.Add(comp.name); } } } else { DstEntityManager.AddComponentData(entity, new PredictedGhostComponent()); foreach (var comp in ghostAuthoring.Components) { if (!comp.predictedClient && comp.entityIndex == 0) { toRemove.Add(comp.name); } } } } // Add list of things to strip based on target world // Strip the things in GhostAuthoringConversion var components = DstEntityManager.GetComponentTypes(entity); foreach (var comp in components) { if (toRemove.Contains(comp.GetManagedType().FullName)) { DstEntityManager.RemoveComponent(entity, comp); } } }); }
protected override void OnUpdate() { var sceneBounds = MinMaxAABB.Empty; var materials = new List <Material>(10); Entities.ForEach((MeshRenderer meshRenderer, MeshFilter meshFilter) => { var entity = GetPrimaryEntity(meshRenderer); var dst = new RenderMesh(); dst.mesh = meshFilter.sharedMesh; dst.castShadows = meshRenderer.shadowCastingMode; dst.receiveShadows = meshRenderer.receiveShadows; dst.layer = meshRenderer.gameObject.layer; //@TODO: Transform system should handle RenderMeshFlippedWindingTag automatically. This should not be the responsibility of the conversion system. float4x4 localToWorld = meshRenderer.transform.localToWorldMatrix; var flipWinding = math.determinant(localToWorld) < 0.0; meshRenderer.GetSharedMaterials(materials); var materialCount = materials.Count; if (materialCount == 1 && AttachToPrimaryEntityForSingleMaterial) { dst.material = materials[0]; dst.subMesh = 0; DstEntityManager.AddSharedComponentData(entity, dst); DstEntityManager.AddComponentData(entity, new PerInstanceCullingTag()); if (flipWinding) { DstEntityManager.AddComponent(entity, ComponentType.ReadWrite <RenderMeshFlippedWindingTag>()); } } else { for (var m = 0; m != materialCount; m++) { var meshEntity = CreateAdditionalEntity(meshRenderer); dst.material = materials[m]; dst.subMesh = m; DstEntityManager.AddSharedComponentData(meshEntity, dst); DstEntityManager.AddComponentData(meshEntity, new PerInstanceCullingTag()); DstEntityManager.AddComponentData(meshEntity, new LocalToWorld { Value = localToWorld }); if (!DstEntityManager.HasComponent <Static>(meshEntity)) { DstEntityManager.AddComponentData(meshEntity, new Parent { Value = entity }); DstEntityManager.AddComponentData(meshEntity, new LocalToParent { Value = float4x4.identity }); } if (flipWinding) { DstEntityManager.AddComponent(meshEntity, ComponentType.ReadWrite <RenderMeshFlippedWindingTag>()); } } } sceneBounds.Encapsulate(meshRenderer.bounds.ToAABB()); }); using (var boundingVolume = DstEntityManager.CreateEntityQuery(typeof(SceneBoundingVolume))) { if (!boundingVolume.IsEmptyIgnoreFilter) { var bounds = boundingVolume.GetSingleton <SceneBoundingVolume>(); bounds.Value.Encapsulate(sceneBounds); boundingVolume.SetSingleton(bounds); } } }
void CreateWireEntities(Component rootComponent, Wire wirePrefab, Vector3 wireEndPos, params Gate[] inputNodes) { if (wirePrefab == null) { return; } var wireMeshFilter = wirePrefab.GetComponent <MeshFilter>(); var wireTransform = wirePrefab.GetComponent <Transform>(); var wireMaterial = wirePrefab.GetComponent <MeshRenderer>().sharedMaterial; // Copy & modify the gate's RenderMesh to reference the correct mesh/material. var gateEntity = GetPrimaryEntity(rootComponent); var baseRenderMesh = DstEntityManager.GetSharedComponentData <RenderMesh>(gateEntity); baseRenderMesh.mesh = wireMeshFilter.sharedMesh; baseRenderMesh.material = wireMaterial; foreach (var inputNode in inputNodes) { // Create a linked entity for the wires leading from the input to this gate var wireStartPos = inputNode.outputAttachTransform.position; // TODO(cort): conversionSystem.InstantiateAdditionalEntity() would be ideal here. Instead, copy what we need from the prefab. var wireEntity = CreateAdditionalEntity(rootComponent); #if UNITY_EDITOR DstEntityManager.SetName(wireEntity, "Wire"); // TODO: make this call [Conditional] #endif DstEntityManager.AddComponents(wireEntity, new ComponentTypes(new ComponentType[] { typeof(LocalToWorld), typeof(RenderBounds), typeof(Translation), typeof(Rotation), typeof(NonUniformScale), typeof(WireInput), typeof(WireState), })); DstEntityManager.AddSharedComponentData(wireEntity, baseRenderMesh); // TODO(https://github.com/cdwfs/RubyGates/issues/9): pre-bake the LocalToWorld and add the Static tag DstEntityManager.SetComponentData(wireEntity, new Translation { Value = wireStartPos, }); var wireScale = wireTransform.localScale; wireScale.y = Vector3.Distance(wireStartPos, wireEndPos); DstEntityManager.SetComponentData(wireEntity, new NonUniformScale { Value = wireScale, }); // We want to measure an angle relative to +Y while looking in -Z. float3 wireDir = wireEndPos - wireStartPos; float wireAngle = math.atan2(-wireDir.x, wireDir.y); DstEntityManager.SetComponentData(wireEntity, new Rotation { Value = quaternion.RotateZ(wireAngle), }); DstEntityManager.SetComponentData(wireEntity, new WireInput { InputEntity = GetPrimaryEntity(inputNode.gameObject), }); } }
protected override void OnUpdate() { Entities.ForEach((UnityEngine.Light unityLight) => { var entity = GetPrimaryEntity(unityLight); LightComponent light; light.type = unityLight.type; light.color = unityLight.color; light.colorTemperature = unityLight.colorTemperature; light.range = unityLight.range; light.intensity = unityLight.intensity; light.cullingMask = unityLight.cullingMask; light.renderingLayerMask = unityLight.renderingLayerMask; light.spotAngle = unityLight.spotAngle; light.innerSpotAngle = unityLight.innerSpotAngle; light.shadows = unityLight.shadows; light.shadowCustomResolution = unityLight.shadowCustomResolution; light.shadowNearPlane = unityLight.shadowNearPlane; light.shadowBias = unityLight.shadowBias; light.shadowNormalBias = unityLight.shadowNormalBias; light.shadowStrength = unityLight.shadowStrength; DstEntityManager.AddComponentData(entity, light); if (unityLight.cookie) { LightCookie cookie; cookie.texture = unityLight.cookie; DstEntityManager.AddSharedComponentData(entity, cookie); } // Optional dependency to com.unity.render-pipelines.high-definition #if HDRP_6_EXISTS HDLightData hdData; var unityHdData = unityLight.GetComponent <HDAdditionalLightData>(); hdData.lightTypeExtent = unityHdData.lightTypeExtent; hdData.intensity = unityHdData.intensity; hdData.lightDimmer = unityHdData.lightDimmer; hdData.fadeDistance = unityHdData.fadeDistance; hdData.affectDiffuse = unityHdData.affectDiffuse; hdData.affectSpecular = unityHdData.affectSpecular; hdData.shapeWidth = unityHdData.shapeWidth; hdData.shapeHeight = unityHdData.shapeHeight; hdData.aspectRatio = unityHdData.aspectRatio; hdData.shapeRadius = unityHdData.shapeRadius; hdData.maxSmoothness = unityHdData.maxSmoothness; hdData.applyRangeAttenuation = unityHdData.applyRangeAttenuation; hdData.spotLightShape = unityHdData.spotLightShape; hdData.enableSpotReflector = unityHdData.enableSpotReflector; hdData.innerSpotPercent = unityHdData.m_InnerSpotPercent; var unityShadowData = unityLight.GetComponent <AdditionalShadowData>(); hdData.shadowResolution = unityShadowData.shadowResolution; hdData.shadowDimmer = unityShadowData.shadowDimmer; hdData.volumetricShadowDimmer = unityShadowData.volumetricShadowDimmer; hdData.shadowFadeDistance = unityShadowData.shadowFadeDistance; hdData.contactShadows = unityShadowData.contactShadows; hdData.viewBiasMin = unityShadowData.viewBiasMin; hdData.viewBiasMax = unityShadowData.viewBiasMax; hdData.viewBiasScale = unityShadowData.viewBiasScale; hdData.normalBiasMin = unityShadowData.normalBiasMin; hdData.normalBiasMax = unityShadowData.normalBiasMax; hdData.normalBiasScale = unityShadowData.normalBiasScale; hdData.sampleBiasScale = unityShadowData.sampleBiasScale; hdData.edgeLeakFixup = unityShadowData.edgeLeakFixup; hdData.edgeToleranceNormal = unityShadowData.edgeToleranceNormal; hdData.edgeTolerance = unityShadowData.edgeTolerance; DstEntityManager.AddComponentData(entity, hdData); #elif HDRP_7_EXISTS var unityHdData = unityLight.GetComponent <HDAdditionalLightData>(); HDLightData hdData; hdData.lightTypeExtent = unityHdData.lightTypeExtent; hdData.intensity = unityHdData.intensity; hdData.lightDimmer = unityHdData.lightDimmer; hdData.fadeDistance = unityHdData.fadeDistance; hdData.affectDiffuse = unityHdData.affectDiffuse; hdData.affectSpecular = unityHdData.affectSpecular; hdData.shapeWidth = unityHdData.shapeWidth; hdData.shapeHeight = unityHdData.shapeHeight; hdData.aspectRatio = unityHdData.aspectRatio; hdData.shapeRadius = unityHdData.shapeRadius; hdData.maxSmoothness = unityHdData.maxSmoothness; hdData.applyRangeAttenuation = unityHdData.applyRangeAttenuation; hdData.spotLightShape = unityHdData.spotLightShape; hdData.enableSpotReflector = unityHdData.enableSpotReflector; hdData.innerSpotPercent = unityHdData.innerSpotPercent; hdData.customResolution = unityHdData.customResolution; hdData.shadowDimmer = unityHdData.shadowDimmer; hdData.volumetricShadowDimmer = unityHdData.volumetricShadowDimmer; hdData.shadowFadeDistance = unityHdData.shadowFadeDistance; hdData.contactShadows = unityHdData.contactShadows; hdData.shadowTint = unityHdData.shadowTint; hdData.normalBias = unityHdData.normalBias; hdData.constantBias = unityHdData.constantBias; hdData.shadowUpdateMode = unityHdData.shadowUpdateMode; DstEntityManager.AddComponentData(entity, hdData); #endif }); }