bool	btPolyhedralConvexShape::initializePolyhedralFeatures()
{

	if (m_polyhedron)
		btAlignedFree(m_polyhedron);
	
	void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16);
	m_polyhedron = new (mem) btConvexPolyhedron;

		btAlignedObjectArray<btVector3> orgVertices;

	for (int i=0;i<getNumVertices();i++)
	{
		btVector3& newVertex = orgVertices.expand();
		getVertex(i,newVertex);
	}

#if 0
	btAlignedObjectArray<btVector3> planeEquations;
	btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);

	btAlignedObjectArray<btVector3> shiftedPlaneEquations;
	for (int p=0;p<planeEquations.size();p++)
	{
		   btVector3 plane = planeEquations[p];
		   plane[3] -= getMargin();
		   shiftedPlaneEquations.push_back(plane);
	}

	btAlignedObjectArray<btVector3> tmpVertices;

	btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
	btConvexHullComputer conv;
	conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);

#else
	btConvexHullComputer conv;
	conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);

#endif



	btAlignedObjectArray<btVector3> faceNormals;
	int numFaces = conv.faces.size();
	faceNormals.resize(numFaces);
	btConvexHullComputer* convexUtil = &conv;

	
	btAlignedObjectArray<btFace>	tmpFaces;
	tmpFaces.resize(numFaces);

	int numVertices = convexUtil->vertices.size();
	m_polyhedron->m_vertices.resize(numVertices);
	for (int p=0;p<numVertices;p++)
	{
		m_polyhedron->m_vertices[p] = convexUtil->vertices[p];
	}


	for (int i=0;i<numFaces;i++)
	{
		int face = convexUtil->faces[i];
		//printf("face=%d\n",face);
		const btConvexHullComputer::Edge*  firstEdge = &convexUtil->edges[face];
		const btConvexHullComputer::Edge*  edge = firstEdge;

		btVector3 edges[3];
		int numEdges = 0;
		//compute face normals

		btScalar maxCross2 = 0.f;
		int chosenEdge = -1;

		do
		{
			
			int src = edge->getSourceVertex();
			tmpFaces[i].m_indices.push_back(src);
			int targ = edge->getTargetVertex();
			btVector3 wa = convexUtil->vertices[src];

			btVector3 wb = convexUtil->vertices[targ];
			btVector3 newEdge = wb-wa;
			newEdge.normalize();
			if (numEdges<2)
				edges[numEdges++] = newEdge;

			edge = edge->getNextEdgeOfFace();
		} while (edge!=firstEdge);

		btScalar planeEq = 1e30f;

		
		if (numEdges==2)
		{
			faceNormals[i] = edges[0].cross(edges[1]);
			faceNormals[i].normalize();
			tmpFaces[i].m_plane[0] = faceNormals[i].getX();
			tmpFaces[i].m_plane[1] = faceNormals[i].getY();
			tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
			tmpFaces[i].m_plane[3] = planeEq;

		}
		else
		{
			btAssert(0);//degenerate?
			faceNormals[i].setZero();
		}

		for (int v=0;v<tmpFaces[i].m_indices.size();v++)
		{
			btScalar eq = m_polyhedron->m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
			if (planeEq>eq)
			{
				planeEq=eq;
			}
		}
		tmpFaces[i].m_plane[3] = -planeEq;
	}

	//merge coplanar faces and copy them to m_polyhedron

	btScalar faceWeldThreshold= 0.999f;
	btAlignedObjectArray<int> todoFaces;
	for (int i=0;i<tmpFaces.size();i++)
		todoFaces.push_back(i);

	while (todoFaces.size())
	{
		btAlignedObjectArray<int> coplanarFaceGroup;
		int refFace = todoFaces[todoFaces.size()-1];

		coplanarFaceGroup.push_back(refFace);
		btFace& faceA = tmpFaces[refFace];
		todoFaces.pop_back();

		btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]);
		for (int j=todoFaces.size()-1;j>=0;j--)
		{
			int i = todoFaces[j];
			btFace& faceB = tmpFaces[i];
			btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]);
			if (faceNormalA.dot(faceNormalB)>faceWeldThreshold)
			{
				coplanarFaceGroup.push_back(i);
				todoFaces.remove(i);
			}
		}


		bool did_merge = false;
		if (coplanarFaceGroup.size()>1)
		{
			//do the merge: use Graham Scan 2d convex hull

			btAlignedObjectArray<GrahamVector2> orgpoints;

			for (int i=0;i<coplanarFaceGroup.size();i++)
			{
//				m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);

				btFace& face = tmpFaces[coplanarFaceGroup[i]];
				btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
				btVector3 xyPlaneNormal(0,0,1);

				btQuaternion rotationArc = shortestArcQuat(faceNormal,xyPlaneNormal);
				
				for (int f=0;f<face.m_indices.size();f++)
				{
					int orgIndex = face.m_indices[f];
					btVector3 pt = m_polyhedron->m_vertices[orgIndex];
					btVector3 rotatedPt =  quatRotate(rotationArc,pt);
					rotatedPt.setZ(0);
					bool found = false;

					for (int i=0;i<orgpoints.size();i++)
					{
						//if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
						if (orgpoints[i].m_orgIndex == orgIndex)
						{
							found=true;
							break;
						}
					}
					if (!found)
						orgpoints.push_back(GrahamVector2(rotatedPt,orgIndex));
				}
			}

			btFace combinedFace;
			for (int i=0;i<4;i++)
				combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];

			btAlignedObjectArray<GrahamVector2> hull;
			GrahamScanConvexHull2D(orgpoints,hull);

			for (int i=0;i<hull.size();i++)
			{
				combinedFace.m_indices.push_back(hull[i].m_orgIndex);
				for(int k = 0; k < orgpoints.size(); k++) {
					if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex) {
						orgpoints[k].m_orgIndex = -1; // invalidate...
						break;
			}
				}
			}
			// are there rejected vertices?
			bool reject_merge = false;
			for(int i = 0; i < orgpoints.size(); i++) {
				if(orgpoints[i].m_orgIndex == -1)
					continue; // this is in the hull...
				// this vertex is rejected -- is anybody else using this vertex?
				for(int j = 0; j < tmpFaces.size(); j++) {
					btFace& face = tmpFaces[j];
					// is this a face of the current coplanar group?
					bool is_in_current_group = false;
					for(int k = 0; k < coplanarFaceGroup.size(); k++) {
						if(coplanarFaceGroup[k] == j) {
							is_in_current_group = true;
							break;
						}
					}
					if(is_in_current_group) // ignore this face...
						continue;
					// does this face use this rejected vertex?
					for(int v = 0; v < face.m_indices.size(); v++) {
						if(face.m_indices[v] == orgpoints[i].m_orgIndex) {
							// this rejected vertex is used in another face -- reject merge
							reject_merge = true;
							break;
						}
					}
					if(reject_merge)
						break;
				}
				if(reject_merge)
					break;
			}
			if(!reject_merge) {
				// do this merge!
				did_merge = true;
			m_polyhedron->m_faces.push_back(combinedFace);
			}
		}
		if(!did_merge)
		{
			for (int i=0;i<coplanarFaceGroup.size();i++)
			{
				m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
			}

		}



	}
	
	m_polyhedron->initialize();

	return true;
}
Example #2
0
static float getDimWithMargin(css_node_t *node, css_flex_direction_t axis) {
  return node->layout.dimensions[dim[axis]] +
    getMargin(node, leading[axis]) +
    getMargin(node, trailing[axis]);
}
Example #3
0
static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, css_direction_t parentDirection) {
  /** START_GENERATED **/
  css_direction_t direction = resolveDirection(node, parentDirection);
  css_flex_direction_t mainAxis = resolveAxis(getFlexDirection(node), direction);
  css_flex_direction_t crossAxis = getCrossFlexDirection(mainAxis, direction);
  css_flex_direction_t resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);

  // Handle width and height style attributes
  setDimensionFromStyle(node, mainAxis);
  setDimensionFromStyle(node, crossAxis);

  // The position is set by the parent, but we need to complete it with a
  // delta composed of the margin and left/top/right/bottom
  node->layout.position[leading[mainAxis]] += getMargin(node, leading[mainAxis]) +
    getRelativePosition(node, mainAxis);
  node->layout.position[trailing[mainAxis]] += getMargin(node, trailing[mainAxis]) +
    getRelativePosition(node, mainAxis);
  node->layout.position[leading[crossAxis]] += getMargin(node, leading[crossAxis]) +
    getRelativePosition(node, crossAxis);
  node->layout.position[trailing[crossAxis]] += getMargin(node, trailing[crossAxis]) +
    getRelativePosition(node, crossAxis);

  if (isMeasureDefined(node)) {
    float width = CSS_UNDEFINED;
    if (isDimDefined(node, resolvedRowAxis)) {
      width = node->style.dimensions[CSS_WIDTH];
    } else if (!isUndefined(node->layout.dimensions[dim[resolvedRowAxis]])) {
      width = node->layout.dimensions[dim[resolvedRowAxis]];
    } else {
      width = parentMaxWidth -
        getMarginAxis(node, resolvedRowAxis);
    }
    width -= getPaddingAndBorderAxis(node, resolvedRowAxis);

    // We only need to give a dimension for the text if we haven't got any
    // for it computed yet. It can either be from the style attribute or because
    // the element is flexible.
    bool isRowUndefined = !isDimDefined(node, resolvedRowAxis) &&
      isUndefined(node->layout.dimensions[dim[resolvedRowAxis]]);
    bool isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&
      isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]);

    // Let's not measure the text if we already know both dimensions
    if (isRowUndefined || isColumnUndefined) {
      css_dim_t measureDim = node->measure(
        node->context,
        
        width
      );
      if (isRowUndefined) {
        node->layout.dimensions[CSS_WIDTH] = measureDim.dimensions[CSS_WIDTH] +
          getPaddingAndBorderAxis(node, resolvedRowAxis);
      }
      if (isColumnUndefined) {
        node->layout.dimensions[CSS_HEIGHT] = measureDim.dimensions[CSS_HEIGHT] +
          getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
      }
    }
    return;
  }

  int i;
  int ii;
  css_node_t* child;
  css_flex_direction_t axis;

  // Pre-fill some dimensions straight from the parent
  for (i = 0; i < node->children_count; ++i) {
    child = node->get_child(node->context, i);
    // Pre-fill cross axis dimensions when the child is using stretch before
    // we call the recursive layout pass
    if (getAlignItem(node, child) == CSS_ALIGN_STRETCH &&
        getPositionType(child) == CSS_POSITION_RELATIVE &&
        !isUndefined(node->layout.dimensions[dim[crossAxis]]) &&
        !isDimDefined(child, crossAxis)) {
      child->layout.dimensions[dim[crossAxis]] = fmaxf(
        boundAxis(child, crossAxis, node->layout.dimensions[dim[crossAxis]] -
          getPaddingAndBorderAxis(node, crossAxis) -
          getMarginAxis(child, crossAxis)),
        // You never want to go smaller than padding
        getPaddingAndBorderAxis(child, crossAxis)
      );
    } else if (getPositionType(child) == CSS_POSITION_ABSOLUTE) {
      // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both
      // left and right or top and bottom).
      for (ii = 0; ii < 2; ii++) {
        axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
        if (!isUndefined(node->layout.dimensions[dim[axis]]) &&
            !isDimDefined(child, axis) &&
            isPosDefined(child, leading[axis]) &&
            isPosDefined(child, trailing[axis])) {
          child->layout.dimensions[dim[axis]] = fmaxf(
            boundAxis(child, axis, node->layout.dimensions[dim[axis]] -
              getPaddingAndBorderAxis(node, axis) -
              getMarginAxis(child, axis) -
              getPosition(child, leading[axis]) -
              getPosition(child, trailing[axis])),
            // You never want to go smaller than padding
            getPaddingAndBorderAxis(child, axis)
          );
        }
      }
    }
  }

  float definedMainDim = CSS_UNDEFINED;
  if (!isUndefined(node->layout.dimensions[dim[mainAxis]])) {
    definedMainDim = node->layout.dimensions[dim[mainAxis]] -
        getPaddingAndBorderAxis(node, mainAxis);
  }

  // We want to execute the next two loops one per line with flex-wrap
  int startLine = 0;
  int endLine = 0;
  // int nextOffset = 0;
  int alreadyComputedNextLayout = 0;
  // We aggregate the total dimensions of the container in those two variables
  float linesCrossDim = 0;
  float linesMainDim = 0;
  while (endLine < node->children_count) {
    // <Loop A> Layout non flexible children and count children by type

    // mainContentDim is accumulation of the dimensions and margin of all the
    // non flexible children. This will be used in order to either set the
    // dimensions of the node if none already exist, or to compute the
    // remaining space left for the flexible children.
    float mainContentDim = 0;

    // There are three kind of children, non flexible, flexible and absolute.
    // We need to know how many there are in order to distribute the space.
    int flexibleChildrenCount = 0;
    float totalFlexible = 0;
    int nonFlexibleChildrenCount = 0;

    float maxWidth;
    for (i = startLine; i < node->children_count; ++i) {
      child = node->get_child(node->context, i);
      float nextContentDim = 0;

      // It only makes sense to consider a child flexible if we have a computed
      // dimension for the node->
      if (!isUndefined(node->layout.dimensions[dim[mainAxis]]) && isFlex(child)) {
        flexibleChildrenCount++;
        totalFlexible += getFlex(child);

        // Even if we don't know its exact size yet, we already know the padding,
        // border and margin. We'll use this partial information, which represents
        // the smallest possible size for the child, to compute the remaining
        // available space.
        nextContentDim = getPaddingAndBorderAxis(child, mainAxis) +
          getMarginAxis(child, mainAxis);

      } else {
        maxWidth = CSS_UNDEFINED;
        if (!isRowDirection(mainAxis)) {
          maxWidth = parentMaxWidth -
            getMarginAxis(node, resolvedRowAxis) -
            getPaddingAndBorderAxis(node, resolvedRowAxis);

          if (isDimDefined(node, resolvedRowAxis)) {
            maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] -
              getPaddingAndBorderAxis(node, resolvedRowAxis);
          }
        }

        // This is the main recursive call. We layout non flexible children.
        if (alreadyComputedNextLayout == 0) {
          layoutNode(child, maxWidth, direction);
        }

        // Absolute positioned elements do not take part of the layout, so we
        // don't use them to compute mainContentDim
        if (getPositionType(child) == CSS_POSITION_RELATIVE) {
          nonFlexibleChildrenCount++;
          // At this point we know the final size and margin of the element.
          nextContentDim = getDimWithMargin(child, mainAxis);
        }
      }

      // The element we are about to add would make us go to the next line
      if (isFlexWrap(node) &&
          !isUndefined(node->layout.dimensions[dim[mainAxis]]) &&
          mainContentDim + nextContentDim > definedMainDim &&
          // If there's only one element, then it's bigger than the content
          // and needs its own line
          i != startLine) {
        nonFlexibleChildrenCount--;
        alreadyComputedNextLayout = 1;
        break;
      }
      alreadyComputedNextLayout = 0;
      mainContentDim += nextContentDim;
      endLine = i + 1;
    }

    // <Loop B> Layout flexible children and allocate empty space

    // In order to position the elements in the main axis, we have two
    // controls. The space between the beginning and the first element
    // and the space between each two elements.
    float leadingMainDim = 0;
    float betweenMainDim = 0;

    // The remaining available space that needs to be allocated
    float remainingMainDim = 0;
    if (!isUndefined(node->layout.dimensions[dim[mainAxis]])) {
      remainingMainDim = definedMainDim - mainContentDim;
    } else {
      remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim;
    }

    // If there are flexible children in the mix, they are going to fill the
    // remaining space
    if (flexibleChildrenCount != 0) {
      float flexibleMainDim = remainingMainDim / totalFlexible;
      float baseMainDim;
      float boundMainDim;

      // Iterate over every child in the axis. If the flex share of remaining
      // space doesn't meet min/max bounds, remove this child from flex
      // calculations.
      for (i = startLine; i < endLine; ++i) {
        child = node->get_child(node->context, i);
        if (isFlex(child)) {
          baseMainDim = flexibleMainDim * getFlex(child) +
              getPaddingAndBorderAxis(child, mainAxis);
          boundMainDim = boundAxis(child, mainAxis, baseMainDim);

          if (baseMainDim != boundMainDim) {
            remainingMainDim -= boundMainDim;
            totalFlexible -= getFlex(child);
          }
        }
      }
      flexibleMainDim = remainingMainDim / totalFlexible;

      // The non flexible children can overflow the container, in this case
      // we should just assume that there is no space available.
      if (flexibleMainDim < 0) {
        flexibleMainDim = 0;
      }
      // We iterate over the full array and only apply the action on flexible
      // children. This is faster than actually allocating a new array that
      // contains only flexible children.
      for (i = startLine; i < endLine; ++i) {
        child = node->get_child(node->context, i);
        if (isFlex(child)) {
          // At this point we know the final size of the element in the main
          // dimension
          child->layout.dimensions[dim[mainAxis]] = boundAxis(child, mainAxis,
            flexibleMainDim * getFlex(child) + getPaddingAndBorderAxis(child, mainAxis)
          );

          maxWidth = CSS_UNDEFINED;
          if (isDimDefined(node, resolvedRowAxis)) {
            maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] -
              getPaddingAndBorderAxis(node, resolvedRowAxis);
          } else if (!isRowDirection(mainAxis)) {
            maxWidth = parentMaxWidth -
              getMarginAxis(node, resolvedRowAxis) -
              getPaddingAndBorderAxis(node, resolvedRowAxis);
          }

          // And we recursively call the layout algorithm for this child
          layoutNode(child, maxWidth, direction);
        }
      }

    // We use justifyContent to figure out how to allocate the remaining
    // space available
    } else {
      css_justify_t justifyContent = getJustifyContent(node);
      if (justifyContent == CSS_JUSTIFY_CENTER) {
        leadingMainDim = remainingMainDim / 2;
      } else if (justifyContent == CSS_JUSTIFY_FLEX_END) {
        leadingMainDim = remainingMainDim;
      } else if (justifyContent == CSS_JUSTIFY_SPACE_BETWEEN) {
        remainingMainDim = fmaxf(remainingMainDim, 0);
        if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 != 0) {
          betweenMainDim = remainingMainDim /
            (flexibleChildrenCount + nonFlexibleChildrenCount - 1);
        } else {
          betweenMainDim = 0;
        }
      } else if (justifyContent == CSS_JUSTIFY_SPACE_AROUND) {
        // Space on the edges is half of the space between elements
        betweenMainDim = remainingMainDim /
          (flexibleChildrenCount + nonFlexibleChildrenCount);
        leadingMainDim = betweenMainDim / 2;
      }
    }

    // <Loop C> Position elements in the main axis and compute dimensions

    // At this point, all the children have their dimensions set. We need to
    // find their position. In order to do that, we accumulate data in
    // variables that are also useful to compute the total dimensions of the
    // container!
    float crossDim = 0;
    float mainDim = leadingMainDim +
      getPaddingAndBorder(node, leading[mainAxis]);

    for (i = startLine; i < endLine; ++i) {
      child = node->get_child(node->context, i);

      if (getPositionType(child) == CSS_POSITION_ABSOLUTE &&
          isPosDefined(child, leading[mainAxis])) {
        // In case the child is position absolute and has left/top being
        // defined, we override the position to whatever the user said
        // (and margin/border).
        child->layout.position[pos[mainAxis]] = getPosition(child, leading[mainAxis]) +
          getBorder(node, leading[mainAxis]) +
          getMargin(child, leading[mainAxis]);
      } else {
        // If the child is position absolute (without top/left) or relative,
        // we put it at the current accumulated offset.
        child->layout.position[pos[mainAxis]] += mainDim;

        // Define the trailing position accordingly.
        if (!isUndefined(node->layout.dimensions[dim[mainAxis]])) {
          setTrailingPosition(node, child, mainAxis);
        }
      }

      // Now that we placed the element, we need to update the variables
      // We only need to do that for relative elements. Absolute elements
      // do not take part in that phase.
      if (getPositionType(child) == CSS_POSITION_RELATIVE) {
        // The main dimension is the sum of all the elements dimension plus
        // the spacing.
        mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);
        // The cross dimension is the max of the elements dimension since there
        // can only be one element in that cross dimension.
        crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));
      }
    }

    float containerCrossAxis = node->layout.dimensions[dim[crossAxis]];
    if (isUndefined(node->layout.dimensions[dim[crossAxis]])) {
      containerCrossAxis = fmaxf(
        // For the cross dim, we add both sides at the end because the value
        // is aggregate via a max function. Intermediate negative values
        // can mess this computation otherwise
        boundAxis(node, crossAxis, crossDim + getPaddingAndBorderAxis(node, crossAxis)),
        getPaddingAndBorderAxis(node, crossAxis)
      );
    }

    // <Loop D> Position elements in the cross axis

    for (i = startLine; i < endLine; ++i) {
      child = node->get_child(node->context, i);

      if (getPositionType(child) == CSS_POSITION_ABSOLUTE &&
          isPosDefined(child, leading[crossAxis])) {
        // In case the child is absolutely positionned and has a
        // top/left/bottom/right being set, we override all the previously
        // computed positions to set it correctly.
        child->layout.position[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +
          getBorder(node, leading[crossAxis]) +
          getMargin(child, leading[crossAxis]);

      } else {
        float leadingCrossDim = getPaddingAndBorder(node, leading[crossAxis]);

        // For a relative children, we're either using alignItems (parent) or
        // alignSelf (child) in order to determine the position in the cross axis
        if (getPositionType(child) == CSS_POSITION_RELATIVE) {
          css_align_t alignItem = getAlignItem(node, child);
          if (alignItem == CSS_ALIGN_STRETCH) {
            // You can only stretch if the dimension has not already been set
            // previously.
            if (!isDimDefined(child, crossAxis)) {
              child->layout.dimensions[dim[crossAxis]] = fmaxf(
                boundAxis(child, crossAxis, containerCrossAxis -
                  getPaddingAndBorderAxis(node, crossAxis) -
                  getMarginAxis(child, crossAxis)),
                // You never want to go smaller than padding
                getPaddingAndBorderAxis(child, crossAxis)
              );
            }
          } else if (alignItem != CSS_ALIGN_FLEX_START) {
            // The remaining space between the parent dimensions+padding and child
            // dimensions+margin.
            float remainingCrossDim = containerCrossAxis -
              getPaddingAndBorderAxis(node, crossAxis) -
              getDimWithMargin(child, crossAxis);

            if (alignItem == CSS_ALIGN_CENTER) {
              leadingCrossDim += remainingCrossDim / 2;
            } else { // CSS_ALIGN_FLEX_END
              leadingCrossDim += remainingCrossDim;
            }
          }
        }

        // And we apply the position
        child->layout.position[pos[crossAxis]] += linesCrossDim + leadingCrossDim;
      }
    }

    linesCrossDim += crossDim;
    linesMainDim = fmaxf(linesMainDim, mainDim);
    startLine = endLine;
  }

  // If the user didn't specify a width or height, and it has not been set
  // by the container, then we set it via the children.
  if (isUndefined(node->layout.dimensions[dim[mainAxis]])) {
    node->layout.dimensions[dim[mainAxis]] = fmaxf(
      // We're missing the last padding at this point to get the final
      // dimension
      boundAxis(node, mainAxis, linesMainDim + getPaddingAndBorder(node, trailing[mainAxis])),
      // We can never assign a width smaller than the padding and borders
      getPaddingAndBorderAxis(node, mainAxis)
    );

    // Now that the width is defined, we should update the trailing
    // positions for the children.
    for (i = 0; i < node->children_count; ++i) {
      setTrailingPosition(node, node->get_child(node->context, i), mainAxis);
    }
  }

  if (isUndefined(node->layout.dimensions[dim[crossAxis]])) {
    node->layout.dimensions[dim[crossAxis]] = fmaxf(
      // For the cross dim, we add both sides at the end because the value
      // is aggregate via a max function. Intermediate negative values
      // can mess this computation otherwise
      boundAxis(node, crossAxis, linesCrossDim + getPaddingAndBorderAxis(node, crossAxis)),
      getPaddingAndBorderAxis(node, crossAxis)
    );
  }

  // <Loop E> Calculate dimensions for absolutely positioned elements

  for (i = 0; i < node->children_count; ++i) {
    child = node->get_child(node->context, i);
    if (getPositionType(child) == CSS_POSITION_ABSOLUTE) {
      // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both
      // left and right or top and bottom).
      for (ii = 0; ii < 2; ii++) {
        axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
        if (!isUndefined(node->layout.dimensions[dim[axis]]) &&
            !isDimDefined(child, axis) &&
            isPosDefined(child, leading[axis]) &&
            isPosDefined(child, trailing[axis])) {
          child->layout.dimensions[dim[axis]] = fmaxf(
            boundAxis(child, axis, node->layout.dimensions[dim[axis]] -
              getBorderAxis(node, axis) -
              getMarginAxis(child, axis) -
              getPosition(child, leading[axis]) -
              getPosition(child, trailing[axis])
            ),
            // You never want to go smaller than padding
            getPaddingAndBorderAxis(child, axis)
          );
        }
      }
      for (ii = 0; ii < 2; ii++) {
        axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
        if (isPosDefined(child, trailing[axis]) &&
            !isPosDefined(child, leading[axis])) {
          child->layout.position[leading[axis]] =
            node->layout.dimensions[dim[axis]] -
            child->layout.dimensions[dim[axis]] -
            getPosition(child, trailing[axis]);
        }
      }
    }
  }
  /** END_GENERATED **/
}
Example #4
0
void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
	btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
}
Example #5
0
static float getMarginAxis(css_node_t *node, css_flex_direction_t axis) {
  return getMargin(node, leading[axis]) + getMargin(node, trailing[axis]);
}
void btPolyhedralConvexAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
{
    getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin());
}
Example #7
0
void    btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
    btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin();
    inertia.setValue(elem,elem,elem);

}
Example #8
0
	SoundShape *SoundBox::clone() const
	{
		return new SoundBox(getHalfSizes(), getCenterPosition(), getOrientation(), getMargin());
	}
Example #9
0
void UILayout::update(float dt) {

    updateZIndex();

    vec2 inner = vec2(0.0f, 0.0f);

    int visible_elements = 0;

    std::list<UIElement*> fill_vert_elements;
    std::list<UIElement*> fill_horiz_elements;

    for(UIElement* e: elements) {
        e->resetRect();
        e->update(dt);

        if(e->isVisible()) {
            visible_elements++;

            if(e->fillHorizontal()) fill_horiz_elements.push_back(e);
            if(e->fillVertical())   fill_vert_elements.push_back(e);

            vec2 r = e->getRect();

            if(horizontal) {
                inner.x += r.x;
                inner.y = std::max(inner.y, r.y);
            } else {
                inner.x = std::max(inner.x, r.x);
                inner.y += r.y;
            }
        }
    }

    vec4 margin = getMargin();

    if(horizontal) {
        inner.x += margin.x+margin.z + ((float)visible_elements-1) * padding.x;
        inner.y += margin.y+margin.w;
    } else {
        inner.x += margin.x+margin.z;
        inner.y += margin.y+margin.w + ((float)visible_elements-1) * padding.y;
    }

    rect = glm::max(min_rect, inner);

    if(fill_vert_elements.empty() && fill_horiz_elements.empty()) return;

    vec2 filler = glm::max(vec2(0.0f), vec2(rect-inner)) + expanded_rect;

    if(horizontal && !fill_horiz_elements.empty()) {
        filler.x /= (float) fill_horiz_elements.size();
    } else if(!fill_vert_elements.empty()) {
        filler.y /= (float) fill_vert_elements.size();
    }

    std::list<UIElement*> fill_elements;
    fill_elements.insert(fill_elements.end(), fill_horiz_elements.begin(), fill_horiz_elements.end());
    fill_elements.insert(fill_elements.end(), fill_vert_elements.begin(), fill_vert_elements.end());

    fill_elements.unique();

    for(UIElement* e: fill_elements) {

        vec2 efill(0.0f);

        if(e->fillHorizontal()) {
            if(!horizontal) efill.x = filler.x + glm::max(0.0f, inner.x - e->rect.x - margin.x - margin.z);
            else efill.x = filler.x;
        }

        if(e->fillVertical()) {
            if(horizontal) efill.y = filler.y + glm::max(0.0f, inner.y - e->rect.y - margin.y - margin.w);
            else efill.y = filler.y;
        }

        if(efill.x > 0.0f || efill.y > 0.0f) {
            e->expandRect(efill);
            e->update(0.0f);
        }
    }

    if(!elements.empty() && elements.front()->getType() == UI_SELECT) debugLog("first element is a select");
}
Example #10
0
	void TextField::resizeHeightToContents()
	{
		setSize(getSize().getWidth(), getFont()->getLineHeight()
			+ getMargin(SIDE_TOP) + getMargin(SIDE_BOTTOM)
			+ 4); //added 4 to ensure everything shows up comfortably
	}