internal void ClearPropertyMap() { // when clearing the property map we want to retain the styles that we have inherited from elsewhere // to do this, we need to read in the inherited values, store them, clear the map, then write the values back LightList <StyleProperty> inherited = LightList <StyleProperty> .Get(); inherited.EnsureCapacity(StyleUtil.InheritedProperties.Count); StyleProperty[] inheritedArray = inherited.Array; for (int i = 0; i < StyleUtil.InheritedProperties.Count; i++) { int key = BitUtil.SetHighLowBits(1, (int)StyleUtil.InheritedProperties[i]); if (propertyMap.TryGetValue(key, out StyleProperty inheritedValue)) { inherited.AddUnchecked(inheritedValue); } } propertyMap.Clear(); // re-apply values for (int i = 0; i < inherited.Count; i++) { int key = BitUtil.SetHighLowBits(1, (int)inheritedArray[i].propertyId); propertyMap.Add(key, inheritedArray[i]); } LightList <StyleProperty> .Release(ref inherited); }
public void Run(UIElement origin) { LightList <UIElement> result = LightList <UIElement> .Get(); rootQuery.Gather(origin, result); if (result.size == 0) { result.Release(); return; } if (rootQuery.next == null) { // match! for (int i = 0; i < result.size; i++) { // result.array[i].style.SetSelectorStyle(matchStyle); } result.Release(); return; } for (int i = 0; i < result.size; i++) { if (rootQuery.next.Run(origin, result.array[i])) { // result.array[i].style.SetSelectorStyle(matchStyle); } } result.Release(); }
public void internal_Initialize() { containedStates = 0; hasAttributeStyles = false; LightList <StylePropertyId> toUpdate = LightList <StylePropertyId> .Get(); if (instanceStyle != null) { CreateStyleEntry(toUpdate, instanceStyle, instanceStyle.normal, StyleType.Instance, StyleState.Normal, 0); CreateStyleEntry(toUpdate, instanceStyle, instanceStyle.hover, StyleType.Instance, StyleState.Hover, 0); CreateStyleEntry(toUpdate, instanceStyle, instanceStyle.focused, StyleType.Instance, StyleState.Focused, 0); CreateStyleEntry(toUpdate, instanceStyle, instanceStyle.active, StyleType.Instance, StyleState.Active, 0); } for (int i = 0; i < styleGroupContainers.size; i++) { CreateStyleGroups(styleGroupContainers.array[i], toUpdate); } SortStyles(); UpdatePropertyMap(toUpdate); LightList <StylePropertyId> .Release(ref toUpdate); }
private StyleParser(StyleTokenStream stream) { tokenStream = stream; nodes = LightList <StyleASTNode> .Get(); operatorStack = StackPool <StyleOperatorNode> .Get(); expressionStack = StackPool <StyleASTNode> .Get(); groupExpressionStack = StackPool <AttributeNodeContainer> .Get(); groupOperatorStack = StackPool <StyleOperatorType> .Get(); }
private void ResetSharedStyles(LightList <UIStyleGroupContainer> updatedStyles) { int count = updatedStyles.Count; UIStyleGroupContainer[] updatedStyleArray = updatedStyles.array; for (int i = 0; i < styleGroupContainers.size; i++) { if (!updatedStyles.Contains(styleGroupContainers.array[i])) { for (int j = 0; j < styleGroupContainers.array[i].groups.Length; j++) { RunCommands(styleGroupContainers.array[i].groups[j].normal.runCommands, false); } } } availableStyles.Clear(); styleGroupContainers.Clear(); isInheritedMap = 0; propertyMap.Clear(); styleGroupContainers.EnsureCapacity(updatedStyles.size); containedStates = 0; hasAttributeStyles = false; LightList <StylePropertyId> toUpdate = LightList <StylePropertyId> .Get(); if (instanceStyle != null) { CreateStyleEntry(toUpdate, instanceStyle, instanceStyle.normal, StyleType.Instance, StyleState.Normal, 0); CreateStyleEntry(toUpdate, instanceStyle, instanceStyle.hover, StyleType.Instance, StyleState.Hover, 0); CreateStyleEntry(toUpdate, instanceStyle, instanceStyle.focused, StyleType.Instance, StyleState.Focused, 0); CreateStyleEntry(toUpdate, instanceStyle, instanceStyle.active, StyleType.Instance, StyleState.Active, 0); } for (int i = 0; i < count; i++) { CreateStyleGroups(updatedStyleArray[i], toUpdate); styleGroupContainers.array[i] = updatedStyleArray[i]; } styleGroupContainers.size = count; SortStyles(); UpdatePropertyMap(toUpdate); LightList <StylePropertyId> .Release(ref toUpdate); }
private static LightList <Type> ResolveGenericTypes(TypeLookup typeLookup, IReadOnlyList <string> namespaces = null, Type scopeType = null) { int count = typeLookup.generics.size; LightList <Type> results = LightList <Type> .Get(); results.EnsureCapacity(count); Type[] array = results.array; Type[] generics = null; Type[] concreteArgs = null; if (scopeType != null) { if (scopeType.IsGenericType) { generics = scopeType.GetGenericTypeDefinition().GetGenericArguments(); concreteArgs = scopeType.GetGenericArguments(); } } for (int i = 0; i < count; i++) { if (generics != null) { for (int j = 0; j < generics.Length; j++) { if (typeLookup.generics[i].typeName == generics[j].Name) { array[i] = concreteArgs[i]; break; } } } array[i] = array[i] ?? ResolveType(typeLookup.generics[i], namespaces); if (array[i] == null) { throw new TypeResolutionException($"Failed to find a type from string {typeLookup.generics[i]}"); } } results.Count = typeLookup.generics.size; return(results); }
public static RouteMatch Match(string path, string matchPath, bool parentMatch = false) { if (path == "*") { return(new RouteMatch(matchPath, false, parentMatch, null)); } LightList <RouteParameter> routeParameters = LightList <RouteParameter> .Get(); // note: /test/url does not match /test/url/ string[] pathSegments = path.Split('/'); string[] destinationPathSegments = matchPath.Split('/'); for (int i = 0; i < pathSegments.Length; i++) { if (string.IsNullOrEmpty(pathSegments[i])) { continue; } if (destinationPathSegments.Length <= i) { return(new RouteMatch(matchPath, false, parentMatch, routeParameters)); } if (pathSegments[i] == "*" && i == pathSegments.Length - 1) { return(new RouteMatch(matchPath, false, parentMatch, routeParameters)); } if (pathSegments[i].StartsWith(":")) { string pathVariableName = pathSegments[i].Substring(1, pathSegments[i].Length - 1); routeParameters.Add(new RouteParameter(pathVariableName, destinationPathSegments[i])); } else if (pathSegments[i] != destinationPathSegments[i]) { return(new RouteMatch(matchPath, false, parentMatch, routeParameters)); } } return(new RouteMatch(matchPath, destinationPathSegments.Length == pathSegments.Length, parentMatch, routeParameters)); }
private bool ParseListExpression(ref LightList <ASTNode> retn, ExpressionTokenType openExpressionToken, ExpressionTokenType closeExpressionToken) { if (tokenStream.Current != openExpressionToken) { return(false); } int range = tokenStream.FindMatchingIndex(openExpressionToken, closeExpressionToken); tokenStream.Save(); if (range == 1) { tokenStream.Advance(2); retn = LightList <ASTNode> .Get(); return(true); } if (retn != null) { LightList <ASTNode> .Release(ref retn); } retn = LightList <ASTNode> .Get(); //todo find next comma at same level (meaning not inside [ or ( or < ExpressionParser parser = CreateSubParser(range); bool valid = parser.ParseListExpressionStep(ref retn); parser.Release(); if (!valid) { tokenStream.Restore(); ReleaseList(retn); return(false); } return(true); }
public void ClearStore() { if (onRecordRemoved == null) { recordStore.Clear(); return; } LightList <T> records = LightList <T> .Get(); records.EnsureCapacity(recordStore.Count); recordStore.GetAllRecords(records); T[] recordsArray = records.Array; recordStore.Clear(); for (int i = 0; i < records.Count; i++) { onRecordRemoved.Invoke(recordsArray[i]); } LightList <T> .Release(ref records); }
internal void EnterState(StyleState state) { if (state == StyleState.Normal || (currentState & state) != 0) { return; } StyleState oldState = currentState; currentState |= state; if ((containedStates & state) == 0) { return; } LightList <StylePropertyId> toUpdate = LightList <StylePropertyId> .Get(); IStyleSystem styleSystem = element.application.styleSystem; StyleEntry[] styleEntries = availableStyles.Array; for (int i = 0; i < availableStyles.Count; i++) { StyleEntry entry = styleEntries[i]; // if this is a state we had not been in before, mark it's properties for update if ((entry.state & oldState) == 0 && (entry.state & state) != 0) { AddMissingProperties(toUpdate, entry.styleRunCommand.style); RunCommands(entry.styleRunCommand.runCommands); } } UpdatePropertyMap(toUpdate); LightList <StylePropertyId> .Release(ref toUpdate); }
internal void ExitState(StyleState state) { if (state == StyleState.Normal || (currentState & state) == 0) { return; } StyleState oldState = currentState; currentState &= ~(state); currentState |= StyleState.Normal; if ((containedStates & state) == 0) { return; } LightList <StylePropertyId> toUpdate = LightList <StylePropertyId> .Get(); StyleEntry[] styleEntries = availableStyles.Array; for (int i = 0; i < availableStyles.Count; i++) { StyleEntry entry = styleEntries[i]; // if this a state we were in that is now invalid, mark it's properties for update if ((entry.state & oldState) != 0 && (entry.state & state) != 0) { AddMissingProperties(toUpdate, entry.styleRunCommand.style); RunCommands(entry.styleRunCommand.runCommands, false); } } UpdatePropertyMap(toUpdate); LightList <StylePropertyId> .Release(ref toUpdate); }
private void AppendSharedStyles(LightList <UIStyleGroupContainer> updatedStyles, int index) { int count = updatedStyles.Count; UIStyleGroupContainer[] updatedStyleArray = updatedStyles.Array; LightList <StylePropertyId> toUpdate = LightList <StylePropertyId> .Get(); styleGroupContainers.EnsureAdditionalCapacity(updatedStyles.Count - index); for (int i = index; i < count; i++) { CreateStyleGroups(updatedStyleArray[i], toUpdate); styleGroupContainers.array[i] = updatedStyleArray[i]; } styleGroupContainers.size = count; SortStyles(); UpdatePropertyMap(toUpdate); LightList <StylePropertyId> .Release(ref toUpdate); }
// something.someValue // something[i] // something(*).x(*).y private bool ParseAccessExpression(ref ASTNode retn) { if (tokenStream.Current != ExpressionTokenType.Identifier) { return(false); } string identifier = tokenStream.Current.value; tokenStream.Save(); LightList <ASTNode> parts = LightList <ASTNode> .Get(); tokenStream.Advance(); while (tokenStream.HasMoreTokens) { if (tokenStream.Current == ExpressionTokenType.Dot || tokenStream.Current == ExpressionTokenType.Elvis) { if (tokenStream.Next != ExpressionTokenType.Identifier) { break; } tokenStream.Advance(); parts.Add(ASTNode.DotAccessNode(tokenStream.Current.value, tokenStream.Previous == ExpressionTokenType.Elvis)); tokenStream.Advance(); if (tokenStream.HasMoreTokens) { continue; } } else if (tokenStream.Current == ExpressionTokenType.ArrayAccessOpen || tokenStream.Current == ExpressionTokenType.QuestionMark && tokenStream.NextTokenIs(ExpressionTokenType.ArrayAccessOpen)) { bool isElvis = false; if (tokenStream.Current == ExpressionTokenType.QuestionMark) { isElvis = true; tokenStream.Advance(); } int advance = tokenStream.FindMatchingIndex(ExpressionTokenType.ArrayAccessOpen, ExpressionTokenType.ArrayAccessClose); if (advance == -1) { Abort("Unmatched array bracket"); } ExpressionParser subParser = CreateSubParser(advance); parts.Add(ASTNode.IndexExpressionNode(subParser.ParseLoop(), isElvis)); subParser.Release(); if (tokenStream.HasMoreTokens) { continue; } } else if (tokenStream.Current == ExpressionTokenType.ParenOpen) { LightList <ASTNode> parameters = null; if (!ParseListExpression(ref parameters, ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose)) { Abort(); } parts.Add(ASTNode.InvokeNode(parameters)); if (tokenStream.HasMoreTokens) { continue; } } else if (tokenStream.Current == ExpressionTokenType.LessThan) { // shortcut the << operator since we can't have a << in a generic type node. List<<string>> is invalid for example if (tokenStream.HasMoreTokens && tokenStream.Next == ExpressionTokenType.LessThan) { tokenStream.Restore(); LightList <ASTNode> .Release(ref parts); return(false); } TypeLookup typePath = new TypeLookup(); if (!(ParseTypePathGenerics(ref typePath))) { tokenStream.Restore(); LightList <ASTNode> .Release(ref parts); return(false); } parts.Add(ASTNode.GenericTypePath(typePath)); if (tokenStream.HasMoreTokens) { continue; } } if (parts.Count == 0) { tokenStream.Restore(); LightList <ASTNode> .Release(ref parts); return(false); } retn = ASTNode.MemberAccessExpressionNode(identifier, parts).WithLocation(tokenStream.Peek()); return(true); } ReleaseList(parts); tokenStream.Restore(); return(false); }
public void PushBlock() { statementStacks.Push(LightList <Expression> .Get()); }
private bool ParseIfStatement(ref ASTNode node) { if (tokenStream.Current != ExpressionTokenType.If) { return(false); } LightList <ElseIfNode> statements = LightList <ElseIfNode> .Get(); tokenStream.Advance(); ASTNode condition = null; if (!ParseParenExpression(ref condition)) { throw new ParseException("Expected a condition statement wrapped in parentheses but failed."); } BlockNode thenBlock = ParseBlock(); if (thenBlock == null) { throw new ParseException("Expected a block statement following an if statement but failed to parse the block"); } if (tokenStream.Current != ExpressionTokenType.ElseIf && tokenStream.Current != ExpressionTokenType.Else) { node = new IfStatementNode() { // elseIfStatements = statements.ToArray(), condition = condition, thenBlock = thenBlock }; return(true); } while (tokenStream.Current == ExpressionTokenType.ElseIf) { tokenStream.Advance(); ASTNode elseIfCondition = null; if (!ParseParenExpression(ref elseIfCondition)) { throw new ParseException("Expected a condition statement wrapped in parentheses but failed."); } BlockNode block = ParseBlock(); if (block == null) { throw new ParseException("Expected a block statement following an if statement but failed to parse the block"); } statements.Add(new ElseIfNode() { condition = elseIfCondition, thenBlock = block }); } BlockNode elseBlock = null; if (tokenStream.Current == ExpressionTokenType.Else) { tokenStream.Advance(); elseBlock = ParseBlock(); if (elseBlock == null) { throw new ParseException("Expected a block statement following an else statement but failed to parse the block"); } } node = new IfStatementNode() { condition = condition, thenBlock = thenBlock, elseIfStatements = statements.size == 0 ? null : statements.ToArray(), elseBlock = elseBlock }; statements.Release(); return(true); }
private bool ParseDeclaration(ref ASTNode node) { AttributeNode attrNode = null; LightList <AttributeNode> attributes = LightList <AttributeNode> .Get(); while (ParseAttribute(ref attrNode)) { attributes.Add(attrNode); if (tokenStream.Current != ExpressionTokenType.ArrayAccessOpen) { break; } } if (attributes.size == 0) { LightList <AttributeNode> .Release(ref attributes); } if (tokenStream.Current != ExpressionTokenType.Identifier) { return(false); } // modifiers? -> returnType -> name -> signature -> openBrace * closeBrace tokenStream.Save(); bool isStatic = false; if (tokenStream.Current == "static") { isStatic = true; tokenStream.Advance(); } ExpressionParser parser = new ExpressionParser(tokenStream); StructList <LambdaArgument> signature = null; TypeLookup typeLookup = default; if (!parser.ParseTypePath(ref typeLookup)) { goto fail; } tokenStream.Set(parser.GetTokenPosition()); parser.Release(false); if (tokenStream.Current != ExpressionTokenType.Identifier) { goto fail; } string name = tokenStream.Current.value; tokenStream.Advance(); // if semi colon then we have a field! if (tokenStream.Current == ExpressionTokenType.SemiColon) { tokenStream.Advance(); node = new FieldNode() { name = name, isStatic = isStatic, attributes = attributes, typeLookup = typeLookup }; return(true); } if (tokenStream.Current != ExpressionTokenType.ParenOpen) { goto fail; } signature = StructList <LambdaArgument> .Get(); if (tokenStream.NextTokenIs(ExpressionTokenType.ParenClose)) { tokenStream.Advance(2); } else { int matchingIndex = tokenStream.FindMatchingIndex(ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose); if (matchingIndex == -1) { goto fail; } TokenStream subStream = tokenStream.AdvanceAndReturnSubStream(matchingIndex); subStream.Advance(); tokenStream.Advance(); if (!ExpressionParser.ParseSignature(subStream, signature)) { goto fail; } for (int i = 0; i < signature.size; i++) { if (signature.array[i].type == null) { throw new ParseException($"When defining a method you must specify a type for all arguments. Found identifier {signature.array[i].identifier} but no type was given."); } } } if (tokenStream.Current != ExpressionTokenType.ExpressionOpen) { goto fail; } BlockNode block = ParseBlock(); node = new MethodNode() { body = block, returnTypeLookup = typeLookup, attributes = attributes, name = name, isStatic = isStatic, signatureList = signature != null?signature.ToArray() : s_EmptySignature }; StructList <LambdaArgument> .Release(ref signature); parser.Release(false); return(true); fail: { tokenStream.Restore(); parser.Release(false); typeLookup.Release(); signature?.Release(); return(false); } }
private void RunDragEvent(List <UIElement> elements, InputEventType eventType) { if (currentDragEvent.IsCanceled && eventType != InputEventType.DragCancel) { return; } currentDragEvent.CurrentEventType = eventType; currentDragEvent.source = m_EventPropagator; m_EventPropagator.Reset(mouseState); LightList <Action <DragEvent> > captureList = LightList <Action <DragEvent> > .Get(); for (int i = 0; i < elements.Count; i++) { UIElement element = elements[i]; if (element.isDestroyed || element.isDisabled) { continue; } if (element.inputHandlers == null) { continue; } if ((element.inputHandlers.handledEvents & eventType) == 0) { continue; } for (int j = 0; j < element.inputHandlers.eventHandlers.size; j++) { ref InputHandlerGroup.HandlerData handler = ref element.inputHandlers.eventHandlers.array[j]; if ((handler.eventType & eventType) == 0) { continue; } Action <DragEvent> castHandler = (Action <DragEvent>)handler.handlerFn; if (handler.eventPhase != EventPhase.Bubble) { captureList.Add(castHandler); continue; } CurrentDragEvent.element = element; castHandler.Invoke(currentDragEvent); if (currentDragEvent.IsCanceled || m_EventPropagator.shouldStopPropagation) { break; } } if (currentDragEvent.IsCanceled || m_EventPropagator.shouldStopPropagation) { captureList.Release(); return; } }
private LightList <UIElement> BuildBindingUpdateList(UIElement rootElement) { LightList <UIElement> bindingUpdateList = LightList <UIElement> .Get(); if (currentDragEvent == null) { if (rootElement != null) { UIElement ptr = rootElement; while (ptr != null) { bindingUpdateList.Add(ptr); ptr = ptr.parent; } } } else { UIElement dragEventBranch = currentDragEvent.origin; UIElement rootElementBranch = rootElement; while (dragEventBranch != null || rootElementBranch != null) { if (dragEventBranch != null && rootElementBranch != null) { if (dragEventBranch.layoutBox.traversalIndex > rootElementBranch.layoutBox.traversalIndex) { bindingUpdateList.Add(dragEventBranch); dragEventBranch = dragEventBranch.parent; } else if (dragEventBranch.layoutBox.traversalIndex < rootElementBranch.layoutBox.traversalIndex) { bindingUpdateList.Add(rootElementBranch); rootElementBranch = rootElementBranch.parent; } else { while (rootElementBranch != null) { bindingUpdateList.Add(rootElementBranch); rootElementBranch = rootElementBranch.parent; } break; } } else { if (dragEventBranch == null) { bindingUpdateList.Add(rootElementBranch); rootElementBranch = rootElementBranch.parent; } else if (rootElementBranch == null) { bindingUpdateList.Add(dragEventBranch); dragEventBranch = dragEventBranch.parent; } } } } bindingUpdateList.Sort((e1, e2) => e1.layoutBox?.traversalIndex > e2.layoutBox?.traversalIndex ? -1 : 1); return(bindingUpdateList); }
// Namespace resolution // if there is only one element with a name then no namespace is needed // if there are multiple elements with a name // namespace is required in order to match the correct one // using declarations can provide implicit namespaces public static ProcessedType ResolveTagName(string tagName, string namespacePrefix, IReadOnlyList <string> namespaces) { FilterAssemblies(); namespaces = namespaces ?? EmptyNamespaceList; if (string.IsNullOrEmpty(namespacePrefix)) { namespacePrefix = null; } if (string.IsNullOrWhiteSpace(namespacePrefix)) { namespacePrefix = null; } if (templateTypeMap.TryGetValue(tagName, out TypeList typeList)) { // if this is null we resolve using just the tag name if (namespacePrefix == null) { // if only one type has this tag name we can safely return it if (typeList.types == null) { return(typeList.mainType.Reference()); } // if there are multiple tags with this name, we need to search our namespaces // if only one match is found, we can return it. If multiple are found, throw // and ambiguous reference exception LightList <ProcessedType> resultList = LightList <ProcessedType> .Get(); for (int i = 0; i < namespaces.Count; i++) { for (int j = 0; j < typeList.types.Length; j++) { string namespaceName = namespaces[i]; ProcessedType testType = typeList.types[j]; if (namespaceName == testType.namespaceName) { resultList.Add(testType); } } } if (resultList.size == 1) { ProcessedType retn = resultList[0]; resultList.Release(); return(retn.Reference()); } List <string> list = resultList.Select((s) => s.namespaceName).ToList(); throw new ParseException("Ambiguous TagName reference: " + tagName + ". References found in namespaces " + StringUtil.ListToString(list, ", ")); } if (typeList.types == null) { if (namespacePrefix == typeList.mainType.namespaceName) { return(typeList.mainType.Reference()); } } else { // if prefix is not null we can only return a match for that namespace for (int j = 0; j < typeList.types.Length; j++) { ProcessedType testType = typeList.types[j]; if (namespacePrefix == testType.namespaceName) { return(testType.Reference()); } } } return(null); } if (s_GenericMap.TryGetValue(tagName, out ProcessedType processedType)) { return(processedType); } return(null); }
private void ProcessMouseInput() { // if element does not have state requested -> hover flag, drag listener, pointer events = none, don't add // buckets feel like a lot of overhead // for each element, track if has overflowing children // if it does not and element is culled, skip directly to children's children and repeat // if aabb yMin is below screen height or aabb ymax is less than 0 -> cull // broadphase culling and input querying are related // neither uses render bounds, just obb and aabb // if dragging only attempt intersections with elements who have drag responders // if not dragging only attempt intersections with elements who have hover state (if mouse is present) or drag create or mouse / touch interactions LightList <UIElement> queryResults = (LightList <UIElement>)m_LayoutSystem.QueryPoint(mouseState.mousePosition, LightList <UIElement> .Get()); // todo -- bug! queryResults.Sort((a, b) => { int viewDepthComparison = b.View.Depth - a.View.Depth; if (viewDepthComparison != 0) { return(viewDepthComparison); } if (b.layoutBox.layer != a.layoutBox.layer) { return(b.layoutBox.layer - a.layoutBox.layer); } if (b.layoutBox.zIndex != a.layoutBox.zIndex) { return(b.layoutBox.zIndex - a.layoutBox.zIndex); } return(b.layoutBox.traversalIndex - a.layoutBox.traversalIndex); }); m_AllElementsThisFrame.Clear(); m_AllElementsThisFrame.AddRange(queryResults); if (!IsDragging) { LightList <UIElement> ancestorElements = LightList <UIElement> .Get(); if (queryResults.size > 0) { /* * Every following element must be a parent of the first. * This makes no sense for drag events but a lot for every other. */ UIElement firstElement = queryResults[0]; ancestorElements.Add(firstElement); for (int index = 1; index < queryResults.size; index++) { UIElement element = queryResults[index]; if (IsParentOf(element, firstElement)) { ancestorElements.Add(element); } } LightList <UIElement> .Release(ref queryResults); queryResults = ancestorElements; } } bool didMouseMove = mouseState.DidMove; if (didMouseMove) { for (int i = 0; i < hoveredElements.size; i++) { UIElement element = hoveredElements.array[i]; if ((element.flags & UIElementFlags.EnabledFlagSet) != UIElementFlags.EnabledFlagSet) { hoveredElements.RemoveAt(i--); continue; } if (!queryResults.Contains(element)) { hoveredElements.RemoveAt(i--); element.style.ExitState(StyleState.Hover); } } for (int i = 0; i < queryResults.Count; i++) { UIElement element = queryResults.array[i]; if ((element.style.currentState & StyleState.Hover) == 0) { hoveredElements.Add(element); element.style.EnterState(StyleState.Hover); } } } for (int i = 0; i < queryResults.Count; i++) { UIElement element = queryResults[i]; m_ElementsThisFrame.Add(element); if (!m_ElementsLastFrame.Contains(element)) { m_EnteredElements.Add(element); } if (IsMouseLeftDownThisFrame) { element.style?.EnterState(StyleState.Active); m_ActiveElements.Add(element); } } for (int i = 0; i < m_ElementsLastFrame.Count; i++) { if (!m_ElementsThisFrame.Contains(m_ElementsLastFrame[i])) { m_ExitedElements.Add(m_ElementsLastFrame[i]); } } if (IsMouseLeftUpThisFrame) { for (int i = 0; i < m_ActiveElements.Count; i++) { m_ActiveElements[i].style?.ExitState(StyleState.Active); } m_ActiveElements.Clear(); } if (!IsDragging) { CursorStyle newCursor = null; if (m_ElementsThisFrame.Count > 0) { for (int i = 0; i < m_ElementsThisFrame.Count; i++) { UIElement element = m_ElementsThisFrame[i]; if (element.isDestroyed) { continue; } if (element.style.IsDefined(StylePropertyId.Cursor)) { newCursor = element.style.Cursor; if (!newCursor.Equals(currentCursor)) { Cursor.SetCursor(newCursor.texture, newCursor.hotSpot, CursorMode.Auto); } break; } } } if (currentCursor != null && newCursor == null) { Cursor.SetCursor(null, new Vector2(0, 0), CursorMode.Auto); } currentCursor = newCursor; if (mouseState.AnyMouseDownThisFrame) { m_MouseDownElements.AddRange(m_ElementsThisFrame); } } LightList <UIElement> .Release(ref queryResults); }
// depth buffer means our regions are locked per channel // 2 options: 1. each channel is its own set of draw calls, this is easy but maybe not as fast. do this as a first pass // 2. try to re-use regions for different channels, almost certainly leads to less throughput but faster since we don't need extra draw calls // probably means we have sub-sorting regions, ie large packers would have sub-packers // would definitely want to sort by size in that case and first try to pack larger regions into themselves // would likely update rect packer to be channel aware, when trying to place next item instead of moving over try colliding a different channel instead public void Clip(Camera camera, CommandBuffer commandBuffer) { // breaks on refresh if we don't do this :( this.clearMaterial.SetColor(s_Color, Color.white); this.clearCountMaterial.SetColor(s_Color, new Color(0, 0, 0, 0)); requireRegionCounting = false; for (int i = 0; i < batchesToRender.size; i++) { batchesToRender[i].pooledMesh.Release(); StructList <Matrix4x4> .Release(ref batchesToRender.array[i].transforms); StructList <Vector4> .Release(ref batchesToRender.array[i].objectData); StructList <Vector4> .Release(ref batchesToRender.array[i].colorData); } batchesToRender.Clear(); Gather(); Vector3 cameraOrigin = camera.transform.position; cameraOrigin.x -= 0.5f * Screen.width; cameraOrigin.y += (0.5f * Screen.height); cameraOrigin.z += 2; Matrix4x4 origin = Matrix4x4.TRS(cameraOrigin, Quaternion.identity, Vector3.one); LightList <ClipData> texturedClippers = LightList <ClipData> .Get(); regionMesh?.Release(); regionMesh = GetRegionMesh(out requireRegionCounting); clipTexture = RenderTexture.GetTemporary(Screen.width, Screen.height, 24, RenderTextureFormat.Default); // todo -- use lower resolution #if DEBUG commandBuffer.BeginSample("UIFora Clip Draw"); #endif commandBuffer.SetRenderTarget(clipTexture); // probably don't need this actually, can bake it into clear. keep for debugging commandBuffer.ClearRenderTarget(true, true, Color.black); commandBuffer.DrawMesh(regionMesh.mesh, origin, clearMaterial, 0, 0); // todo -- handle multiple shapes from one path ClipBatch batch = new ClipBatch(); batch.transforms = StructList <Matrix4x4> .Get(); batch.colorData = StructList <Vector4> .Get(); batch.objectData = StructList <Vector4> .Get(); for (int i = 0; i < clippers.size; i++) { ClipData clipData = clippers[i]; Path2D clipPath = clipData.clipPath; if (clipPath == null) { // todo if transform is not identity we need to generate a rotated or skewed rect for the clip shape continue; } clipPath.UpdateGeometry(); // should early out if no update required if (AnyShapeUsesTextures(clipPath)) { // todo -- handle textures // todo -- handle text continue; } batch = DrawShapesInPath(batch, clipPath, clipData, clipData); for (int j = 0; j < clipData.dependents.size; j++) { batch = DrawShapesInPath(batch, clipPath, clipData, clipData.dependents[j]); } } FinalizeBatch(batch, false); for (int i = 0; i < batchesToRender.size; i++) { ref ClipBatch clipBatch = ref batchesToRender.array[i]; ClipPropertyBlock propertyBlock = clipMaterialPool.GetPropertyBlock(clipBatch.transforms.size); propertyBlock.SetData(clipBatch); commandBuffer.DrawMesh(clipBatch.pooledMesh.mesh, origin, clipDrawMaterial, 0, 0, propertyBlock.matBlock); }
public BlockDefinition2() { this.variables = StructList <Parameter> .Get(); this.statements = LightList <Expression> .Get(); }
public bool Run(UIElement origin, UIElement element) { LightList <UIElement> list = LightList <UIElement> .Get(); int templateId = origin.templateMetaData.id; switch (navigationOperator) { case NavigationOperator.Parent: { UIElement ptr = element.parent; while (ptr != origin) { if (ptr.templateMetaData.id == templateId) { list.Add(ptr); break; } ptr = ptr.parent; } break; } case NavigationOperator.Ancestor: { UIElement ptr = element.parent; while (ptr != origin) { if (ptr.templateMetaData.id == templateId) { list.Add(ptr); } ptr = ptr.parent; } break; } case NavigationOperator.Sibling: break; default: throw new ArgumentOutOfRangeException(); } ApplyModifiers(origin, list); Filter(origin, list); if (list.size == 0) { list.Release(); return(false); } if (next == null) { list.Release(); return(true); } for (int i = 0; i < list.size; i++) { if (!next.Run(origin, list.array[i])) { list.Release(); return(false); } } list.Release(); return(true); }