Пример #1
0
void
inDOMView::ContentInserted(nsIDocument *aDocument, nsIContent* aContainer,
                           nsIContent* aChild, PRInt32 /* unused */)
{
  if (!mTree)
    return;

  nsresult rv;
  nsCOMPtr<nsIDOMNode> childDOMNode(do_QueryInterface(aChild));
  nsCOMPtr<nsIDOMNode> parent;
  if (!mDOMUtils) {
    mDOMUtils = do_GetService("@mozilla.org/inspector/dom-utils;1");
    if (!mDOMUtils) {
      return;
    }
  }
  mDOMUtils->GetParentForNode(childDOMNode, mShowAnonymous,
                              getter_AddRefs(parent));

  // find the inDOMViewNode for the parent of the inserted content
  PRInt32 parentRow = 0;
  if (NS_FAILED(rv = NodeToRow(parent, &parentRow)))
    return;
  inDOMViewNode* parentNode = nsnull;
  if (NS_FAILED(rv = RowToNode(parentRow, &parentNode)))
    return;

  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
  
  if (!parentNode->isOpen) {
    // Parent is not open, so don't bother creating tree rows for the
    // kids.  But do indicate that it's now a container, if needed.
    if (!parentNode->isContainer) {
      parentNode->isContainer = PR_TRUE;
      mTree->InvalidateRow(parentRow);
    }
    return;
  }

  // get the previous sibling of the inserted content
  nsCOMPtr<nsIDOMNode> previous;
  GetRealPreviousSibling(childDOMNode, parent, getter_AddRefs(previous));
  inDOMViewNode* previousNode = nsnull;

  PRInt32 row = 0;
  if (previous) {
    // find the inDOMViewNode for the previous sibling of the inserted content
    PRInt32 previousRow = 0;
    if (NS_FAILED(rv = NodeToRow(previous, &previousRow)))
      return;
    if (NS_FAILED(rv = RowToNode(previousRow, &previousNode)))
      return;

    // get the last descendant of the previous row, which is the row
    // after which to insert this new row
    GetLastDescendantOf(previousNode, previousRow, &row);
    ++row;
  } else {
    // there is no previous sibling, so the new row will be inserted after the parent
    row = parentRow+1;
  }

  inDOMViewNode* newNode = CreateNode(childDOMNode, parentNode);

  if (previous) {
    InsertLinkAfter(newNode, previousNode);
  } else {
    PRInt32 firstChildRow;
    if (NS_SUCCEEDED(GetFirstDescendantOf(parentNode, parentRow, &firstChildRow))) {
      inDOMViewNode* firstChild;
      RowToNode(firstChildRow, &firstChild);
      InsertLinkBefore(newNode, firstChild);
    }
  }

  // insert new node
  InsertNode(newNode, row);

  mTree->RowCountChanged(row, 1);
}
Пример #2
0
void
inDOMView::AttributeChanged(nsIDocument* aDocument, dom::Element* aElement,
                            PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                            PRInt32 aModType)
{
  if (!mTree) {
    return;
  }

  if (!(mWhatToShow & nsIDOMNodeFilter::SHOW_ATTRIBUTE)) {
    return;
  }

  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
  
  // get the dom attribute node, if there is any
  nsCOMPtr<nsIDOMNode> content(do_QueryInterface(aElement));
  nsCOMPtr<nsIDOMElement> el(do_QueryInterface(aElement));
  nsCOMPtr<nsIDOMAttr> domAttr;
  nsDependentAtomString attrStr(aAttribute);
  if (aNameSpaceID) {
    nsCOMPtr<nsINameSpaceManager> nsm =
      do_GetService(NS_NAMESPACEMANAGER_CONTRACTID);
    if (!nsm) {
      // we can't find out which attribute we want :(
      return;
    }
    nsString attrNS;
    nsresult rv = nsm->GetNameSpaceURI(aNameSpaceID, attrNS);
    if (NS_FAILED(rv)) {
      return;
    }
    (void)el->GetAttributeNodeNS(attrNS, attrStr, getter_AddRefs(domAttr));
  } else {
    (void)el->GetAttributeNode(attrStr, getter_AddRefs(domAttr));
  }

  if (aModType == nsIDOMMutationEvent::MODIFICATION) {
    // No fancy stuff here, just invalidate the changed row
    if (!domAttr) {
      return;
    }
    PRInt32 row = 0;
    NodeToRow(domAttr, &row);
    mTree->InvalidateRange(row, row);
  } else if (aModType == nsIDOMMutationEvent::ADDITION) {
    if (!domAttr) {
      return;
    }
    // get the number of attributes on this content node
    nsCOMPtr<nsIDOMNamedNodeMap> attrs;
    content->GetAttributes(getter_AddRefs(attrs));
    PRUint32 attrCount;
    attrs->GetLength(&attrCount);

    inDOMViewNode* contentNode = nsnull;
    PRInt32 contentRow;
    PRInt32 attrRow;
    if (mRootNode == content &&
        !(mWhatToShow & nsIDOMNodeFilter::SHOW_ELEMENT)) {
      // if this view has a root node but is not displaying it,
      // it is ok to act as if the changed attribute is on the root.
      attrRow = attrCount - 1;
    } else {
      if (NS_FAILED(NodeToRow(content, &contentRow))) {
        return;
      }
      RowToNode(contentRow, &contentNode);
      if (!contentNode->isOpen) {
        return;
      }
      attrRow = contentRow + attrCount;
    }

    inDOMViewNode* newNode = CreateNode(domAttr, contentNode);
    inDOMViewNode* insertNode = nsnull;
    RowToNode(attrRow, &insertNode);
    if (insertNode) {
      if (contentNode &&
          insertNode->level <= contentNode->level) {
        RowToNode(attrRow-1, &insertNode);
        InsertLinkAfter(newNode, insertNode);
      } else
        InsertLinkBefore(newNode, insertNode);
    }
    InsertNode(newNode, attrRow);
    mTree->RowCountChanged(attrRow, 1);
  } else if (aModType == nsIDOMMutationEvent::REMOVAL) {
    // At this point, the attribute is already gone from the DOM, but is still represented
    // in our mRows array.  Search through the content node's children for the corresponding
    // node and remove it.

    // get the row of the content node
    inDOMViewNode* contentNode = nsnull;
    PRInt32 contentRow;
    PRInt32 baseLevel;
    if (NS_SUCCEEDED(NodeToRow(content, &contentRow))) {
      RowToNode(contentRow, &contentNode);
      baseLevel = contentNode->level;
    } else {
      if (mRootNode == content) {
        contentRow = -1;
        baseLevel = -1;
      } else
        return;
    }

    // search for the attribute node that was removed
    inDOMViewNode* checkNode = nsnull;
    PRInt32 row = 0;
    for (row = contentRow+1; row < GetRowCount(); ++row) {
      checkNode = GetNodeAt(row);
      if (checkNode->level == baseLevel+1) {
        domAttr = do_QueryInterface(checkNode->node);
        if (domAttr) {
          nsAutoString attrName;
          domAttr->GetNodeName(attrName);
          if (attrName.Equals(attrStr)) {
            // we have found the row for the attribute that was removed
            RemoveLink(checkNode);
            RemoveNode(row);
            mTree->RowCountChanged(row, -1);
            break;
          }
        }
      }
      if (checkNode->level <= baseLevel)
        break;
    }

 }
}
Пример #3
0
void SV_LinkEdict(edict_t *ent)
{
	guard(SV_LinkEdict);

	int		i, j, k;

	//!! HOOK - move outside ?
	if (bspfile.type != map_q2)
	{
		if (ent->s.modelindex >= 0 && ent->s.modelindex < MAX_MODELS)
		{
			// link model hook
			const char *modelName = sv.configstrings[CS_MODELS + ent->s.modelindex];
			if (!strcmp(modelName, "models/objects/dmspot/tris.md2"))
			{
				// teleporter (source+target) was found
//				appPrintf(S_CYAN"teleport: %g %g %g\n", VECTOR_ARG(ent->s.origin));
				return;			// simply do not link model; trigger entity will be added anyway
			}
		}
	}

	if (ent->area.prev)
		SV_UnlinkEdict(ent);	// unlink from old position (i.e. relink edict)

	if (ent == ge->edicts)
		return;					// don't add the world

	if (!ent->inuse)
		return;

	entityHull_t &ex = ents[NUM_FOR_EDICT(ent)];
	memset(&ex, 0, sizeof(entityHull_t));
	ex.owner = ent;
	ex.axis.FromEuler(ent->s.angles);

	// set the size
	VectorSubtract(ent->bounds.maxs, ent->bounds.mins, ent->size);

	// encode the size into the entity_state for client prediction
	if (ent->solid == SOLID_BBOX)
	{
		// assume that x/y are equal and symetric
		i = appRound(ent->bounds.maxs[0] / 8);
		// z is not symetric
		j = appRound(-ent->bounds.mins[2] / 8);
		// and z maxs can be negative...
		k = appRound((ent->bounds.maxs[2] + 32) / 8);
		// original Q2 have bounded i/j/k/ with lower margin==1 (for client prediction only); this will
		// produce incorrect collision test when bbox mins/maxs is (0,0,0)
		i = bound(i, 0, 31);		// mins/maxs[0,1] range is -248..0/0..248
		j = bound(j, 0, 31);		// mins[2] range is [-248..0]
		k = bound(k, 0, 63);		// maxs[2] range is [-32..472]

		// if SVF_DEADMONSTER, s.solid should be 0
		ent->s.solid = (ent->svflags & SVF_DEADMONSTER) ? 0 : (k<<10) | (j<<5) | i;

		i *= 8;
		j *= 8;
		k *= 8;
		ex.bounds.mins.Set(-i, -i, -j);
		ex.bounds.maxs.Set(i, i, k - 32);
		ex.bounds.GetCenter(ex.center);
		ex.center.Add(ent->s.origin);
		ex.model  = NULL;
		ex.radius = VectorDistance(ex.bounds.maxs, ex.bounds.mins) / 2;
	}
	else if (ent->solid == SOLID_BSP)
	{
		ex.model = sv.models[ent->s.modelindex];
		if (!ex.model) Com_DropError("MOVETYPE_PUSH with a non bsp model");
		CVec3	v;
		ex.model->bounds.GetCenter(v);
		UnTransformPoint(ent->s.origin, ex.axis, v, ex.center);
		ex.radius = ex.model->radius;

		ent->s.solid = 31;		// a SOLID_BBOX will never create this value (mins=(-248,-248,0) maxs=(248,248,-32))
	}
	else if (ent->solid == SOLID_TRIGGER)
	{
		ent->s.solid = 0;
		// check for model link
		ex.model = sv.models[ent->s.modelindex];
		if (!ex.model)
		{
			// model not attached by game, check entstring
			//?? can optimize: add 'bool spawningEnts', set to 'true' before SpawnEntities()
			//?? and 'false' after; skip code below when 'false'
			for (triggerModelLink_t *link = bspfile.modelLinks; link; link = link->next)
#define CMP(n)	(fabs(ent->s.origin[n] - link->origin[n]) < 0.5f)
				if (CMP(0) && CMP(1) && CMP(2))
				{
					CBspModel *model = CM_InlineModel(link->modelIdx);
					VectorSubtract(model->bounds.maxs, ent->s.origin, ent->bounds.maxs);
					VectorSubtract(model->bounds.mins, ent->s.origin, ent->bounds.mins);
					break;
				}
#undef CMP
		}
	}
	else
		ent->s.solid = 0;

	// set the abs box
	if (ent->solid == SOLID_BSP && (ent->s.angles[0] || ent->s.angles[1] || ent->s.angles[2]))
	{
		// expand for rotation
		for (i = 0; i < 3 ; i++)
		{
			ent->absBounds.mins[i] = ex.center[i] - ex.radius;
			ent->absBounds.maxs[i] = ex.center[i] + ex.radius;
		}
	}
	else
	{	// normal
		VectorAdd(ent->s.origin, ent->bounds.mins, ent->absBounds.mins);
		VectorAdd(ent->s.origin, ent->bounds.maxs, ent->absBounds.maxs);
	}

	// because movement is clipped an epsilon away from an actual edge,
	// we must fully check even when bounding boxes don't quite touch
	for (i = 0; i < 3; i++)
	{
		ent->absBounds.mins[i] -= 1;
		ent->absBounds.maxs[i] += 1;
	}

	// link to PVS leafs
	ent->num_clusters = 0;
	ent->zonenum      = 0;
	ent->zonenum2     = 0;

	// get all leafs, including solids
	CBspLeaf *leafs[MAX_TOTAL_ENT_LEAFS];
	int topnode;
	int num_leafs = CM_BoxLeafs(ent->absBounds, ARRAY_ARG(leafs), &topnode);

	// set zones
	int clusters[MAX_TOTAL_ENT_LEAFS];
	for (i = 0; i < num_leafs; i++)
	{
		clusters[i] = leafs[i]->cluster;
		int zone = leafs[i]->zone;
		if (zone)
		{	// doors may legally straggle two zones,
			// but nothing should evern need more than that
			if (ent->zonenum && ent->zonenum != zone)
			{
				if (ent->zonenum2 && ent->zonenum2 != zone && sv.state == ss_loading)
					Com_DPrintf("Object touching 3 zones at %g %g %g\n", VECTOR_ARG(ent->absBounds.mins));
				ent->zonenum2 = zone;
			}
			else
				ent->zonenum = zone;
		}
	}

	if (num_leafs >= MAX_TOTAL_ENT_LEAFS)
	{	// assume we missed some leafs, and mark by headnode
		ent->num_clusters = -1;
		ent->headnode     = topnode;
	}
	else
	{
		ent->num_clusters = 0;
		for (i = 0; i < num_leafs; i++)
		{
			if (clusters[i] == -1)
				continue;		// not a visible leaf
			for (j = 0; j < i; j++)
				if (clusters[j] == clusters[i])
					break;
			if (j == i)
			{
				if (ent->num_clusters == MAX_ENT_CLUSTERS)
				{	// assume we missed some leafs, and mark by headnode
					ent->num_clusters = -1;
					ent->headnode     = topnode;
					break;
				}

				ent->clusternums[ent->num_clusters++] = clusters[i];
			}
		}
	}

	// if first time, make sure old_origin is valid
	if (!ent->linkcount)
		ent->s.old_origin = ent->s.origin;
	ent->linkcount++;

	if (ent->solid == SOLID_NOT)
		return;

	// find the first node that the ent's box crosses
	areanode_t *node = areaNodes;
	while (node->axis != -1)
	{
		if (ent->absBounds.mins[node->axis] > node->dist)
			node = node->children[0];
		else if (ent->absBounds.maxs[node->axis] < node->dist)
			node = node->children[1];
		else
			break;		// crosses the node
	}

	// link it in
	areanode_t *node2 = node;
	if (ent->solid == SOLID_TRIGGER)
	{
		InsertLinkBefore(ent->area, node->trigEdicts);
		for ( ; node2; node2 = node2->parent)
			node2->numTrigEdicts++;
	}
	else
	{
		InsertLinkBefore(ent->area, node->solidEdicts);
		for ( ; node2; node2 = node2->parent)
			node2->numSolidEdicts++;
	}
	ex.area = node;

	unguard;
}
Пример #4
0
void SV_LinkEdict (edict_t *ent)
{
	areanode_t	*node;
	int			leafs[MAX_TOTAL_ENT_LEAFS];
	int			clusters[MAX_TOTAL_ENT_LEAFS];
	int			num_leafs;
	int			i, j, k;
	int			area;
	int			topnode;

	if (ent->area.prev)
		SV_UnlinkEdict (ent);	// unlink from old position
		
	if (ent == ge->edicts)
		return;		// don't add the world

	if (!ent->inuse)
		return;

	// set the size
	VectorSubtract (ent->maxs, ent->mins, ent->size);
	
	// encode the size into the entity_state for client prediction
	if (ent->solid == SOLID_BBOX && !(ent->svflags & SVF_DEADMONSTER))
	{	// assume that x/y are equal and symetric
		i = ent->maxs[0]/8;
		if (i<1)
			i = 1;
		if (i>31)
			i = 31;

		// z is not symetric
		j = (-ent->mins[2])/8;
		if (j<1)
			j = 1;
		if (j>31)
			j = 31;

		// and z maxs can be negative...
		k = (ent->maxs[2]+32)/8;
		if (k<1)
			k = 1;
		if (k>63)
			k = 63;

		ent->s.solid = (k<<10) | (j<<5) | i;
	}
	else if (ent->solid == SOLID_BSP)
	{
		ent->s.solid = 31;		// a solid_bbox will never create this value
	}
	else
		ent->s.solid = 0;

	// set the abs box
	if (ent->solid == SOLID_BSP && 
	(ent->s.angles[0] || ent->s.angles[1] || ent->s.angles[2]) )
	{	// expand for rotation
		float		max, v;
		int			i;

		max = 0;
		for (i=0 ; i<3 ; i++)
		{
			v =fabs( ent->mins[i]);
			if (v > max)
				max = v;
			v =fabs( ent->maxs[i]);
			if (v > max)
				max = v;
		}
		for (i=0 ; i<3 ; i++)
		{
			ent->absmin[i] = ent->s.origin[i] - max;
			ent->absmax[i] = ent->s.origin[i] + max;
		}
	}
	else
	{	// normal
		VectorAdd (ent->s.origin, ent->mins, ent->absmin);	
		VectorAdd (ent->s.origin, ent->maxs, ent->absmax);
	}

	// because movement is clipped an epsilon away from an actual edge,
	// we must fully check even when bounding boxes don't quite touch
	ent->absmin[0] -= 1;
	ent->absmin[1] -= 1;
	ent->absmin[2] -= 1;
	ent->absmax[0] += 1;
	ent->absmax[1] += 1;
	ent->absmax[2] += 1;

// link to PVS leafs
	ent->num_clusters = 0;
	ent->areanum = 0;
	ent->areanum2 = 0;

	//get all leafs, including solids
	num_leafs = CM_BoxLeafnums (ent->absmin, ent->absmax,
		leafs, MAX_TOTAL_ENT_LEAFS, &topnode);

	// set areas
	for (i=0 ; i<num_leafs ; i++)
	{
		clusters[i] = CM_LeafCluster (leafs[i]);
		area = CM_LeafArea (leafs[i]);
		if (area)
		{	// doors may legally straggle two areas,
			// but nothing should evern need more than that
			if (ent->areanum && ent->areanum != area)
			{
				if (ent->areanum2 && ent->areanum2 != area && sv.state == ss_loading)
					Com_DPrintf ("Object touching 3 areas at %f %f %f\n",
					ent->absmin[0], ent->absmin[1], ent->absmin[2]);
				ent->areanum2 = area;
			}
			else
				ent->areanum = area;
		}
	}

	if (num_leafs >= MAX_TOTAL_ENT_LEAFS)
	{	// assume we missed some leafs, and mark by headnode
		ent->num_clusters = -1;
		ent->headnode = topnode;
	}
	else
	{
		ent->num_clusters = 0;
		for (i=0 ; i<num_leafs ; i++)
		{
			if (clusters[i] == -1)
				continue;		// not a visible leaf
			for (j=0 ; j<i ; j++)
				if (clusters[j] == clusters[i])
					break;
			if (j == i)
			{
				if (ent->num_clusters == MAX_ENT_CLUSTERS)
				{	// assume we missed some leafs, and mark by headnode
					ent->num_clusters = -1;
					ent->headnode = topnode;
					break;
				}

				ent->clusternums[ent->num_clusters++] = clusters[i];
			}
		}
	}

	// if first time, make sure old_origin is valid
	if (!ent->linkcount)
	{
		VectorCopy (ent->s.origin, ent->s.old_origin);
	}
	ent->linkcount++;

	if (ent->solid == SOLID_NOT)
		return;

// find the first node that the ent's box crosses
	node = sv_areanodes;
	while (1)
	{
		if (node->axis == -1)
			break;
		if (ent->absmin[node->axis] > node->dist)
			node = node->children[0];
		else if (ent->absmax[node->axis] < node->dist)
			node = node->children[1];
		else
			break;		// crosses the node
	}
	
	// link it in	
	if (ent->solid == SOLID_TRIGGER)
		InsertLinkBefore (&ent->area, &node->trigger_edicts);
	else
		InsertLinkBefore (&ent->area, &node->solid_edicts);

}
Пример #5
0
/*
===============
SV_LinkEdict

===============
*/
void SV_LinkEdict (edict_t *ent, qbool touch_triggers)
{
	areanode_t	*node;
	
	if (ent->area.prev)
		SV_UnlinkEdict (ent);	// unlink from old position
		
	if (ent == sv.edicts)
		return;		// don't add the world

	if (!ent->inuse)
		return;

// set the abs box
	VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);	
	VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);

//
// to make items easier to pick up and allow them to be grabbed off
// of shelves, the abs sizes are expanded
//
	if ((int)ent->v.flags & FL_ITEM)
	{
		ent->v.absmin[0] -= 15;
		ent->v.absmin[1] -= 15;
		ent->v.absmax[0] += 15;
		ent->v.absmax[1] += 15;
	}
	else
	{	// because movement is clipped an epsilon away from an actual edge,
		// we must fully check even when bounding boxes don't quite touch
		ent->v.absmin[0] -= 1;
		ent->v.absmin[1] -= 1;
		ent->v.absmin[2] -= 1;
		ent->v.absmax[0] += 1;
		ent->v.absmax[1] += 1;
		ent->v.absmax[2] += 1;
	}
	
// link to PVS leafs
	if (ent->v.modelindex)
		SV_LinkToLeafs (ent);
	else
		ent->num_leafs = 0;

	if (ent->v.solid == SOLID_NOT)
		return;

// find the first node that the ent's box crosses
	node = sv_areanodes;
	while (1)
	{
		if (node->axis == -1)
			break;
		if (ent->v.absmin[node->axis] > node->dist)
			node = node->children[0];
		else if (ent->v.absmax[node->axis] < node->dist)
			node = node->children[1];
		else
			break;		// crosses the node
	}
	
// link it in	

	if (ent->v.solid == SOLID_TRIGGER)
		InsertLinkBefore (&ent->area, &node->trigger_edicts);
	else
		InsertLinkBefore (&ent->area, &node->solid_edicts);
	
// if touch_triggers, touch all entities at this node and decend for more
	if (touch_triggers)
		SV_TouchLinks ( ent, sv_areanodes );
}