public static GraphInfo GetGraphInfo(this UIGraphData graph, BlobAssetReference <CompiledUISchema> schema, out NativeArray <NodeInfo> configLayout, Allocator allocator) { var offset = sizeof(ulong) + sizeof(int); configLayout = new NativeArray <NodeInfo>(graph.GetNodeCount(), allocator); var graphInfo = new GraphInfo(); for (int currentIndex = 0; currentIndex < graph.GetNodeCount(); currentIndex++) { //var size = UnsafeUtility.AsRef<int>((((IntPtr)graph.Value.initialConfiguration.GetUnsafePtr()) + offset).ToPointer()); var size = *(int *)(graph.value + offset).ToPointer(); var header = (HeaderConfig *)(graph.value + offset + sizeof(int)).ToPointer(); //var size = graph.GetNodeLength(currentIndex); if (header->IsDedicatedNode) { graphInfo.subMeshCount++; } offset += UnsafeUtility.SizeOf <int>(); NodeInfo info = new NodeInfo { configurationMask = header->configurationMask, nodeOffset = offset, childrenOffset = offset + UnsafeUtility.SizeOf <HeaderConfig>(), configOffset = offset + UnsafeUtility.SizeOf <HeaderConfig>() + (sizeof(int) * header->childCount), length = size, index = currentIndex }; var call = header->schemaIndex >= 0 ? schema.Value.elements[header->schemaIndex].renderBoxCounter : default; info.renderBoxCount = call.IsCreated ? call.Invoke(graph.value, (NodeInfo *)UnsafeUtility.AddressOf(ref info)) : 1; configLayout[currentIndex] = info; graphInfo.renderBoxCount += info.renderBoxCount; offset += size; } return(graphInfo); }
public static IntPtr GetNodeConfigPointer(this UIGraphData self, int index) { HeaderConfig *header = (HeaderConfig *)(GetNodePointer(self, index) + sizeof(int)).ToPointer(); var childCount = header->childCount; return(((IntPtr)header) + UnsafeUtility.SizeOf <HeaderConfig>() + (sizeof(int) * childCount)); }
public static ulong GetNodeConfigurationMask(this UIGraphData self, int index) { HeaderConfig result = default; GetNodeHeader(self, index, ref result); return(result.configurationMask); }
public static HeaderConfig GetNodeHeader(this UIGraphData self, int index) { HeaderConfig result = default; GetNodeHeader(self, index, ref result); return(result); }
public static IntPtr GetConfigBlock(this UIGraphData self, int index, byte config) { HeaderConfig *header = (HeaderConfig *)(GetNodePointer(self, index) + sizeof(int)).ToPointer(); var childCount = header->childCount; var offset = UIConfigUtility.GetOffset(header->configurationMask, config); return(((IntPtr)header) + UnsafeUtility.SizeOf <HeaderConfig>() + (sizeof(int) * childCount) + offset); }
public static IntPtr GetNodePointer(this UIGraphData self, int index) { var offset = sizeof(ulong) + sizeof(int); for (int currentIndex = 0; currentIndex < index; currentIndex++) { offset += *(int *)(self.value + offset).ToPointer() + sizeof(int); } return(self.value + offset); }
private void Layout(int index, UIGraphData graph, NativeArray <NodeInfo> configLayout, NativeArray <UIPassState> stateLayout, UIContextData *context) { if (!graph.TryGetConfigBlock(index, UIConfigLayoutTable.DisplayConfig, out IntPtr displayConfig) || (((DisplayConfig *)displayConfig.ToPointer())->display == VisibilityStyle.Visible)) { var nodeInfo = configLayout[index]; var headerConfig = (HeaderConfig *)(graph.value + nodeInfo.nodeOffset).ToPointer(); var configSource = graph.value + nodeInfo.configOffset; var state = (UIPassState *)(((IntPtr)stateLayout.GetUnsafePtr()) + (UnsafeUtility.SizeOf <UIPassState>() * index)).ToPointer(); IntPtr boxConfig; bool hasBoxConfig = graph.TryGetConfigBlock(index, UIConfigLayoutTable.BoxModelConfig, out boxConfig); if (hasBoxConfig) { BoxModelConfig *boxConfigPtr = (BoxModelConfig *)boxConfig.ToPointer(); state->localBox += boxConfigPtr->margin.Normalize(*context); state->inner = boxConfigPtr->padding.Normalize(*context); } FunctionPointer <UILayoutPass> layout = headerConfig->schemaIndex >= 0 ? schema.Value.elements[headerConfig->schemaIndex].layout : default; for (int childIndex = 0; childIndex < headerConfig->childCount; childIndex++) { if (layout.IsCreated) { layout.Invoke( childIndex, graph.value, (NodeInfo *)UnsafeUtility.AddressOf(ref nodeInfo), (IntPtr)stateLayout.GetUnsafePtr(), context ); } Layout(UnsafeUtility.ReadArrayElement <int>((graph.value + nodeInfo.childrenOffset).ToPointer(), childIndex), graph, configLayout, stateLayout, context); } if (layout.IsCreated) { layout.Invoke( -1, graph.value, (NodeInfo *)UnsafeUtility.AddressOf(ref nodeInfo), (IntPtr)stateLayout.GetUnsafePtr(), context ); } if (graph.TryGetConfigBlock(index, UIConfigLayoutTable.SizeConfig, out IntPtr sizeConfig)) { var sizeConfigPtr = ((SizeConfig *)sizeConfig.ToPointer()); state->size = new float2( math.clamp(state->size.x, sizeConfigPtr->minWidth.Normalize(*context), sizeConfigPtr->maxWidth.Normalize(*context)), math.clamp(state->size.y, sizeConfigPtr->minHeight.Normalize(*context), sizeConfigPtr->maxHeight.Normalize(*context))); } if (hasBoxConfig) { state->size += new float2(state->inner.x + state->inner.z, state->inner.y + state->inner.w); } } }
public static int CountRenderBoxes(this UIGraphData graph, NativeArray <NodeInfo> configLayout, NativeArray <UISchema.CompiledElement> schema) { int count = 0; for (int currentIndex = 0; currentIndex < configLayout.Length; currentIndex++) { var info = configLayout[currentIndex]; var header = (HeaderConfig *)(graph.value + info.nodeOffset); var call = header->schemaIndex >= 0 ? schema[header->schemaIndex].renderBoxCounter : default; count += call.IsCreated ? call.Invoke(graph.value, (NodeInfo *)UnsafeUtility.AddressOf(ref info)) : 1; } return(count); }
public static bool HasConfigBlock(this UIGraphData self, int index, byte config) { HeaderConfig *header = (HeaderConfig *)(GetNodePointer(self, index) + sizeof(int)).ToPointer(); var childCount = header->childCount; var offset = UIConfigUtility.GetOffset(header->configurationMask, config); if (offset < 0) { return(false); } else { return(true); } }
public unsafe void DecomposeHead(UIGraphData graph, int threadIndex) { var graphInfo = graph.GetGraphInfo(schema, out NativeArray <NodeInfo> configLayout, Allocator.Temp); int currentSubmesh = 0; var dedicatedNodeInfo = new NativeArray <DedicatedNodeInfo>(graphInfo.subMeshCount, Allocator.Temp); Decompose(graph, threadIndex, 0, configLayout, ref currentSubmesh, dedicatedNodeInfo, graphInfo.subMeshCount + 1); nodes.BeginForEachIndex(threadIndex); this.submeshCount[threadIndex] = graphInfo.subMeshCount; for (int i = 0; i < graphInfo.subMeshCount; i++) { nodes.Write(dedicatedNodeInfo[i]); } nodes.EndForEachIndex(); }
public unsafe void Decompose(UIGraphData graph, int threadIndex, int currentIndex, NativeArray <NodeInfo> nodeInfo, ref int currentSubmesh, NativeArray <DedicatedNodeInfo> nodes, int subMeshCount) { var ptr = graph.GetNodePointer(currentIndex) + sizeof(int); var header = (HeaderConfig *)ptr; if (header->IsDedicatedNode) { nodes[currentSubmesh] = new DedicatedNodeInfo(threadIndex, currentIndex, nodeInfo[currentIndex], subMeshCount - (++currentSubmesh)); } var children = ptr + UnsafeUtility.SizeOf <HeaderConfig>(); for (int i = 0; i < header->childCount; i++) { Decompose(graph, threadIndex, UnsafeUtility.ReadArrayElement <int>(children.ToPointer(), i), nodeInfo, ref currentSubmesh, nodes, subMeshCount); } }
public static bool TryGetConfigBlock(this UIGraphData self, int index, byte config, out IntPtr result) { HeaderConfig *header = (HeaderConfig *)(GetNodePointer(self, index) + sizeof(int)).ToPointer(); var childCount = header->childCount; var offset = UIConfigUtility.GetOffset(header->configurationMask, config); if (offset < 0) { result = IntPtr.Zero; return(false); } else { result = ((IntPtr)header) + UnsafeUtility.SizeOf <HeaderConfig>() + (sizeof(int) * childCount) + offset; return(true); } }
public void Execute(UIGraphData graph, MeshData meshData, int index) { if (graph.GetNodeCount() > 0) { var states = new NativeArray <UIPassState>(graph.GetNodeCount(), Allocator.Temp); var initial = UIPassState.Null; UnsafeUtility.MemCpyReplicate(states.GetUnsafePtr(), UnsafeUtility.AddressOf(ref initial), UnsafeUtility.SizeOf <UIPassState>(), states.Length); var graphInfo = graph.GetGraphInfo(schema, out NativeArray <NodeInfo> layout, Allocator.Temp); InitMeshData(ref meshData, graphInfo); NativeArray <UIVertexData> vertices = meshData.GetVertexData <UIVertexData>(); var contextPtr = (UIContextData *)((IntPtr)contexts.GetUnsafePtr() + (UnsafeUtility.SizeOf <UIContextData>() * index)).ToPointer(); Layout(0, graph, layout, states, contextPtr); Render(vertices, contextPtr, ref meshData, graph, layout, graphInfo, states); states.Dispose(); layout.Dispose(); } }
protected unsafe override void OnUpdate() { var ecb = entityCommandBufferSystem.CreateCommandBuffer(); Entities .WithoutBurst() .WithNone <UIGraphData, UIGraphHandleData>() .ForEach((Entity entity, in UIGraph ui) => { var handle = Addressables.LoadAssetAsync <TextAsset>(ui.value.ToHex()); var id = this.handles.Count; ecb.AddComponent(entity, new UIGraphHandleData { id = id }); this.handles.Add(handle); }) .Run(); Entities .WithoutBurst() .WithNone <UIGraphData>() .ForEach((Entity entity, in UIGraphHandleData handleData, in UIGraph ui) => { var handle = this.handles[handleData.id]; if (handle.IsDone) { IntPtr ptr; long allocatedLength; using (var ms = new MemoryStream(handle.Result.bytes)) { allocatedLength = math.ceilpow2(ms.Length); ptr = (IntPtr)UnsafeUtility.Malloc(allocatedLength, 0, Allocator.Persistent); using (var us = new UnmanagedMemoryStream((byte *)ptr.ToPointer(), 0, ms.Length, FileAccess.Write)) { ms.CopyTo(us); } } //int id = this.graphs.Length; var graph = new UIGraphData { value = ptr, allocatedLength = allocatedLength }; //this.graphs.Add(graph); ecb.AddComponent(entity, graph); } })
public static int GetFirstSelectableIndex(this UIGraphData graph) { if (!graph.IsCreated) { return(-1); } //Index, priority ValueTuple <int, int> selectableIndex = (-1, int.MinValue); for (int currentIndex = 0; currentIndex < graph.GetNodeCount(); currentIndex++) { if (graph.TryGetConfigBlock(currentIndex, UIConfigLayoutTable.SelectableConfig, out IntPtr block)) { SelectableConfig *selectableConfig = (SelectableConfig *)block; if (selectableConfig->onSelect.IsCreated && selectableIndex.Item2.CompareTo(selectableConfig->priority) < 0) { selectableIndex = (currentIndex, selectableConfig->priority); } } } return(selectableIndex.Item1); }
public static int GetNodeCount(this UIGraphData self) => self.IsCreated ? *(int *)(self.value + sizeof(ulong)).ToPointer() : 0;
private void Render(NativeArray <UIVertexData> vertices, UIContextData *context, ref MeshData meshData, UIGraphData graph, NativeArray <NodeInfo> layout, GraphInfo graphInfo, NativeArray <UIPassState> stateLayout) { var indices = meshData.GetIndexData <ushort>(); var subMeshes = new NativeArray <SubMeshInfo>(graphInfo.subMeshCount, Allocator.Temp); int submeshIndex = 0; int renderIndex = 0; float4 bounds = float4.zero; RenderMesh(0, -1, 0, vertices, context, indices, graph, graphInfo, layout, stateLayout, subMeshes, true, true, true, ref submeshIndex, ref renderIndex, ref bounds); float4 totalBounds = bounds; int submesh0RenderIndexCount = renderIndex; for (int i = 0; i < subMeshes.Length; i++) { SubMeshInfo current = subMeshes[i]; var initialRenderIndex = renderIndex; RenderMesh(current.nodeIndex, -1, current.nodeIndex, vertices, context, indices, graph, graphInfo, layout, stateLayout, subMeshes, true, false, false, ref submeshIndex, ref renderIndex, ref bounds); totalBounds = new float4(math.min(totalBounds.x, bounds.x), math.min(totalBounds.y, bounds.y), math.max(totalBounds.z, bounds.z), math.max(totalBounds.w, bounds.w)); current.meshIndexStart = initialRenderIndex * 6; current.meshIndexCount = (renderIndex - initialRenderIndex) * 6; current.bounds = bounds; subMeshes[i] = current; for (int j = 0; j < (renderIndex - initialRenderIndex); j++) { for (int k = 0; k < 4; k++) { UIVertexData vertex = vertices[(initialRenderIndex + j) * 4 + k]; vertex.position.z -= 0.001f * (i + 1); vertices[(initialRenderIndex + j) * 4 + k] = vertex; } } } //Center Mesh float3 totalSize = new float3(math.abs(totalBounds.z - totalBounds.x), math.abs(totalBounds.y - totalBounds.w), 0f); var adjust = new float3(totalSize.x / 2f, totalSize.y / 2f, 0); for (int i = 0; i < vertices.Length; i++) { UIVertexData vertex = vertices[i]; vertex.position -= adjust; vertices[i] = vertex; } for (int i = 0; i < subMeshes.Length; i++) { SubMeshInfo current = subMeshes[i]; var size = new float3(math.abs(current.bounds.z - current.bounds.x), math.abs(current.bounds.y - current.bounds.w), 0.00001f); meshData.SetSubMesh(meshData.subMeshCount - (i + 1), new UnityEngine.Rendering.SubMeshDescriptor(current.meshIndexStart, current.meshIndexCount) { //bounds = new Bounds(new float3(current.bounds.x + (size.x / 2f), bounds.y + (size.y / 2f), 0f) - adjust, size), bounds = new Bounds(float3.zero, size), firstVertex = (current.meshIndexStart / 6) * 4, vertexCount = (current.meshIndexCount / 6) * 4 } //,MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices ); } meshData.SetSubMesh(0, new UnityEngine.Rendering.SubMeshDescriptor(0, submesh0RenderIndexCount * 6) { bounds = new Bounds(float3.zero, new float3(totalSize.x, totalSize.y, 0.00001f)), firstVertex = 0, vertexCount = submesh0RenderIndexCount * 4 } //,MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices ); subMeshes.Dispose(); }
public static ulong GetLength(this UIGraphData self) => self.IsCreated ? *(ulong *)self.value.ToPointer() : 0UL;
private void RenderMesh( int startIndex, int parentIndex, int currentIndex, NativeArray <UIVertexData> vertexData, UIContextData *context, NativeArray <ushort> indices, UIGraphData graph, GraphInfo graphInfo, NativeArray <NodeInfo> nodeInfo, NativeArray <UIPassState> stateLayout, NativeArray <SubMeshInfo> subMeshes, bool renderNow, bool updateSubmeshCount, bool accumulate, ref int subMeshIndex, ref int renderIndex, ref float4 bounds ) { var info = nodeInfo[currentIndex]; HeaderConfig *headerConfig = (HeaderConfig *)(graph.value + info.nodeOffset).ToPointer(); var state = stateLayout[currentIndex]; if (accumulate) { state.globalBox += state.localBox; if (parentIndex >= 0) { state.globalBox += stateLayout[parentIndex].inner; } stateLayout[currentIndex] = state; } if (headerConfig->IsDedicatedNode) { if (updateSubmeshCount) { subMeshes[subMeshIndex] = new SubMeshInfo(++subMeshIndex, currentIndex); } renderNow = currentIndex == startIndex; } if (renderNow) { bool display = true; bool visible = true; if (graph.TryGetConfigBlock(currentIndex, UIConfigLayoutTable.DisplayConfig, out IntPtr displayConfig)) { var dc = ((DisplayConfig *)displayConfig.ToPointer()); display = dc->display == VisibilityStyle.Visible; visible = dc->visible == VisibilityStyle.Visible; } if (display) { FunctionPointer <UIRenderPass> render = headerConfig->schemaIndex >= 0 ? schema.Value.elements[headerConfig->schemaIndex].render : default; if (render.IsCreated) { render.Invoke( graph.value, (NodeInfo *)UnsafeUtility.AddressOf(ref info), (UIPassState *)UnsafeUtility.AddressOf(ref state), (UIVertexData *)(((IntPtr)vertexData.GetUnsafePtr()) + (renderIndex * UnsafeUtility.SizeOf <UIVertexData>() * 4)).ToPointer(), context ); } for (int j = 0; j < info.renderBoxCount; j++) { indices[(renderIndex + j) * 6] = (ushort)((renderIndex + j) * 4); indices[((renderIndex + j) * 6) + 1] = (ushort)(((renderIndex + j) * 4) + 2); indices[((renderIndex + j) * 6) + 2] = (ushort)(((renderIndex + j) * 4) + 1); indices[((renderIndex + j) * 6) + 3] = (ushort)(((renderIndex + j) * 4) + 2); indices[((renderIndex + j) * 6) + 4] = (ushort)(((renderIndex + j) * 4) + 3); indices[((renderIndex + j) * 6) + 5] = (ushort)(((renderIndex + j) * 4) + 1); UpdateBounds(vertexData, (renderIndex + j) * 4, ref bounds); } } if (!display || !visible) { UnsafeUtility.MemClear((((IntPtr)vertexData.GetUnsafePtr()) + (renderIndex * UnsafeUtility.SizeOf <UIVertexData>() * 4)).ToPointer(), UnsafeUtility.SizeOf <UIVertexData>() * info.renderBoxCount * 4); UnsafeUtility.MemClear((((IntPtr)indices.GetUnsafePtr()) + (renderIndex * UnsafeUtility.SizeOf <ushort>() * 6)).ToPointer(), UnsafeUtility.SizeOf <ushort>() * info.renderBoxCount * 6); } renderIndex += info.renderBoxCount; } for (int i = 0; i < headerConfig->childCount; i++) { RenderMesh(startIndex, currentIndex, UnsafeUtility.ReadArrayElement <int>((graph.value + info.childrenOffset).ToPointer(), i), vertexData, context, indices, graph, graphInfo, nodeInfo, stateLayout, subMeshes, renderNow, updateSubmeshCount, accumulate, ref subMeshIndex, ref renderIndex, ref bounds); } }
public static void GetNodeHeader(this UIGraphData self, int index, ref HeaderConfig result) { result = UnsafeUtility.AsRef <HeaderConfig>((GetNodePointer(self, index) + sizeof(int)).ToPointer()); }
public static string GetNodeName(this UIGraphData self, int index) { if (TryGetConfigBlock(self, index, UIConfigLayoutTable.NameConfig, out IntPtr block, out IntPtr header)) { return(((NameConfig *)block.ToPointer())->name.ToString(header.ToPointer())); }
public static bool IsDedicatedNode(this UIGraphData self, int index) => GetNodeHeader(self, index).IsDedicatedNode;
public static int GetNodeLength(this UIGraphData self, int index) { return(*(int *)GetNodePointer(self, index).ToPointer()); }