Highlighting only part of custom entity

Highlighting only part of custom entity

Anonymous
Not applicable
1,637 Views
9 Replies
Message 1 of 10

Highlighting only part of custom entity

Anonymous
Not applicable

Hi!

 

I see a lot of threads about this topic, but none seem to answer my questions. I have a custom entity (derived from AcDbPolyline). In it's Draw override it draws a lot of extra lines and circles with calls like:

 

wd->subEntityTraits().setSelectionMarker(someLongValue); // someLongValue is different for each circle, of course

wd->geometry().circle(pt1, r1, normal());

 

I am trying to override subHighlight to highlight only the geometry of my entity that's under the mouse. I thought this would do it:

 

Acad::ErrorStatus CvWSPolyline::subHighlight(const AcDbFullSubentPath& subId /* = kNullSubent */, const Adesk::Boolean highlightAll /* = false */) const
{
   const Adesk::GsMarker gsMarker = subId.subentId().index();
   if (showThis(gsMarker))
      return AcDbPolyline::subHighlight(subId, highlightAll);
   return Acad::eOk;
}

 But gsMarker is always 0. Isn't setSelectionMarker they right way to set this, or is something else wrong here?

0 Likes
Accepted solutions (1)
1,638 Views
9 Replies
Replies (9)
Message 2 of 10

owenwengerd
Advisor
Advisor

Based on your description, your subHighlight() is being called and asked to highlight the entire object. You are then passing those instructions along to your superclass, which is predictably highlighting the entire polyline. It sounds like you're expecting subHighlight to be called for each marker, which is possible of course, but I wouldn't expect that to occur naturally.

 

You also haven't shown how you're avoiding gsmarker conflicts between your markers and those of the superclass. If there is a conflict, all bets are off.

--
Owen Wengerd
ManuSoft
0 Likes
Message 3 of 10

Anonymous
Not applicable

I thought that calling subHighlight once for each GSMarker is how it's supposed to work? The AcDbFullSubentpath contains only one subEntId. And I thought that a subEntId corresponds to a GSMarker? How else do I find which GSMarker was the reason to call highlight?

 

I had no idea I had to do something to avoid conflicts of GSMarkers. Are they unique for each drawing or only for each Entity?

0 Likes
Message 4 of 10

owenwengerd
Advisor
Advisor

I don't have much experience with subentity highlighting, so this is just guesswork on my part, but I'm hypothesizing that a "subentity" at marker zero means "highlight everything". If you want to experiment, take the polyline implementation out of the equation by calling AcDbEntity::highlight() directly instead of supermessaging AcDbPolyline::subHighlight().

 

As for marker collisions, you only have to ensure that your markers are unique for a single object. Since your object derives from AcDbPolyline, this means you have to use markers that AcDbPolyline does not use. In practice, that means starting at a number higher than the number of vertices, or using negative values.

--
Owen Wengerd
ManuSoft
0 Likes
Message 5 of 10

Anonymous
Not applicable

The AcDbPolyline here has only one vertex, and all the GSMarkers have quite high values. I don't think that's the problem.

 

And calling AcDbEntity::highlight? I am not looking for a function to highlight things, but to interfer with the standard highlighting that happens when the mouse moves over my entity. So I think I need to do this in subHighlight, right?

 

The problem is I don't understand how this is supposed to work. More concrete:

 

- is the function AcGiWorldDraw::subEntityTraits::setSelectionmarker really what specifies a GSMarker for the following AcGiWorldDraw::geometry().circle/line calls? Then why is the parameter of setSelectionmarker Adesk::LongPtr, not Adesk::GSMarker?

- In subHighlight, what is the parameter subId really? Is subId.subentId().index() supposed to give me the same value as I set when drawing a circle after calling setSelectionMarker?

- How does getGsMarkersAtSubentPath come into play? The documentation states you need to override this to get highlight to work properly, but I can't find any example of how?

 

 

0 Likes
Message 6 of 10

owenwengerd
Advisor
Advisor
Accepted solution

Hopefully someone more knowledgable than me can answer your questions with more authority.

 

I'm pretty sure that you *must* call AcDbEntity::highlight() either directly or indirectly if you want to highlight anything. If you want nothing to ever be highlighted, then you can simply skip the call altogether. But my suggestion was not about AcDbEntity::highlight() per se, but about AcDbPolyline::subHighlight() -- since it is opaque and we can't know what all it does, it can be useful to remove it from the equation in order to narrow down what is going on.

 

I don't know why Adesk::LongPtr, but could just be an oversight. In my experience, calling AcGiSubEntityTraits::setSelectionmarker() is the primary requirement for using gs markers in generated graphics (it's all I've ever needed to worry about), but the gs marker system may be used in other ways that I'm not familiar with.

--
Owen Wengerd
ManuSoft
0 Likes
Message 7 of 10

Anonymous
Not applicable

I have started another thread with a slightly different "Subject" to see if that triggers anything useful.

0 Likes
Message 8 of 10

Anonymous
Not applicable

Finally I found a way to do this, but I'm not sure it's the best way. Doesn't seem to slow things down, though. I have attached a reactor monitorInputPoint and call highlight/unhighlight from there as the mouse moves over entities. The code follows below.

 

Acad::ErrorStatus MyGraphic::monitorInputPoint( // Gigantic parameter list here...
{
  static AcDbFullSubentPathArray highlightedSubents; // Keeps the subentities currently highlighted

  const int gsLength = gsSelectionMark.length();
  const int apLength = apertureEntities.length();
  if (gsLength != apLength) // Just an assertion while debugging, will not be kept in production code
    acutPrintf(_T("\ngsLength != apLength!"));
  // I can't find any documentation of these parameters to monitorInputPoint, but it seems that gsSelectionMark and apertureEntities
  // go hand in hand, so that gsSelectionMark[i] is the GsMarker to the subentity apertureEntities[i].
  AcDbFullSubentPathArray subentsToHighlight; // The subentityPaths of all subentities currently under the mouse, the ones we want to highlight right now
  for (int i = 0; i < gsLength && i < apLength; ++i)
    subentsToHighlight.append(AcDbFullSubentPath(apertureEntities[i], AcDb::kVertexSubentType, gsSelectionMark[i]));

  // Now unhighlight previously highlighted subentities that should not be highlighted anymore and remove already highlighted subentities from subentsToHighlight
  for (int highlightIndex = 0; highlightIndex < highlightedSubents.length(); )
  {
    if (subentsToHighlight.length() > 0 && subentsToHighlight.remove(highlightedSubents[highlightIndex])) // If it was already highlighted, remove it from subentsToHighlight
      ++highlightIndex;
    else
    {
      AcDbObjectPointer<AcDbEntity> pEntity(highlightedSubents[highlightIndex].objectIds()[0], AcDb::kForRead);
      if (pEntity.openStatus() == Acad::eOk)
        pEntity->unhighlight(highlightedSubents[highlightIndex]);
      else
        acutPrintf(_T("\nCouldn't open highlighted object to unhighlight it!")); // Just an assertion while debugging, will not be kept in production code
      highlightedSubents.removeAt(highlightIndex); // If we couldn't open the object, I don't know what will happen. Let's remove it from here anyway, to avoid accumulating dead objects.
    }
  }

  // Now highlight the remaining subentities
  for (int highlightIndex = 0; highlightIndex < subentsToHighlight.length(); ++highlightIndex)
  {
    AcDbObjectPointer<AcDbEntity> pEntity(subentsToHighlight[highlightIndex].objectIds()[0], AcDb::kForRead);
    if (pEntity.openStatus() == Acad::eOk)
    {
      pEntity->highlight(subentsToHighlight[highlightIndex]);
      highlightedSubents.append(subentsToHighlight[highlightIndex]);
    }
  }
...
}

 

0 Likes
Message 9 of 10

Anonymous
Not applicable

I accepted this as solution partly because you took the time to try and secondly because your insistance on calling highlight directly made me rethink the approach, leading to the solution.

 

Thank you!

0 Likes
Message 10 of 10

Anonymous
Not applicable

This wasn't actually a total solution, since I'm getting problems with highlighting after certain operations. I'll get back to this in other threads.

0 Likes