AcGiVisualStyle : Custom entity.

AcGiVisualStyle : Custom entity.

tech
Enthusiast Enthusiast
1,652 Views
7 Replies
Message 1 of 8

AcGiVisualStyle : Custom entity.

tech
Enthusiast
Enthusiast

I am trying to render my entity differently depending on the current visual style selected. I am trying to get the current visual style for the subEntityTraits of the drawing context but the call is returning a null object id. Any ideas?

Adesk::Boolean TPG_Drawable::Draw(AcArray<TPG_Entity*>& ents, AcGiWorldDraw* dc, int options, bool cacheExtents)
{
	auto styleId = dc->subEntityTraits().visualStyle();
	AcRxObject* rxObj = nullptr;

	if (acdbOpenObject(rxObj, styleId, AcDb::kForRead) == Acad::eOk)
	{
		auto style = static_cast<AcGiVisualStyle*>(rxObj);
		switch (style->type())
		{
		case AcGiVisualStyle::Type::k2DWireframe:
			break;
		case AcGiVisualStyle::Type::k3DWireframe:
		{
			auto rep = GetRepresentation3D();
			rep->worldDraw(dc);
		}
			return Adesk::kTrue;
		case AcGiVisualStyle::Type::kRealistic:
			break;
		}
	}
        return Adesk::kTrue;
}

Mike

0 Likes
Accepted solutions (1)
1,653 Views
7 Replies
Replies (7)
Message 2 of 8

tbrammer
Advisor
Advisor
Accepted solution

The visual style is a property of the viewport - either of an AcDbViewport entity in a layout if tilemode=0 or of an AcDbViewportTableRecord if tilemode=1. So I would expect to find a style ID<>null only via the AcGiViewportDraw that is provided in subViewportDraw() and not in AcGiWorldDraw, which contains the properties common to all views.

 

 


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes
Message 3 of 8

tech
Enthusiast
Enthusiast

The code I have provided is being called from the subWorldDraw(….) call of the containing AcDbEntity derived class. This drawing context is that of the world draw not a viewport.

0 Likes
Message 4 of 8

tbrammer
Advisor
Advisor

@tech wrote:

The code I have provided is being called from the subWorldDraw(….) call of the containing AcDbEntity derived class. This drawing context is that of the world draw not a viewport.


...and the world draw context does only contain information that is common to all views/viewports.
But the shademode is viewport specific. So you can't react to the shademode within world draw.

You have to move your code to viewport draw to do this.


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes
Message 5 of 8

tech
Enthusiast
Enthusiast

I have made the following changes to force a call to subViewportDraw but the visual style id returned from the sub entity traits is still AcDbObjectId::kNull.

 

/// <summary> Overridden to call the custom Draw method. </summary>
Adesk::Boolean TPG_Entity::subWorldDraw(AcGiWorldDraw* dc)
{
	if (dc->regenAbort()) 
		return Adesk::kTrue; // Stop drawing.
	

	return Adesk::kFalse; // Force call to subViewportDraw(...)
}

/// <summary> </summary>
void TPG_Entity::subViewportDraw(AcGiViewportDraw* dc)
{
	auto visualStyleId = dc->subEntityTraits().visualStyle();
	if (visualStyleId != AcDbObjectId::kNull)
	{
		AcGiVisualStyle* style = nullptr;
		if (acdbOpenObject((AcRxObject*&)style, visualStyleId, AcDb::kForRead) == Acad::eOk)
		{
			if (style->type() != AcGiVisualStyle::Type::k2DWireframe)
				acutPrintf(L"3D Mode");
		}
	}
	
	Draw(AcArray<TPG_Entity*>(), dc);
}

Any ideas from anyone on how to get the current visual style selected by the user?

 

Regards,

 

Mike

0 Likes
Message 6 of 8

tbrammer
Advisor
Advisor

AcGiVisualStyle is not derived from AcDbObject. So acdbOpenObject() will do an illegal cast!

AcDbObjectId visualStyleId is the objectId of an AcDbVisualStyle object located in the ACAD_VISUALSTYLE dictionary. Just replace AcGiVisualStyle in your code by AcDbVisualStyle

 

If you are in not tilemode, you can get the visual style ID from the AcDbViewport like this:

 

void TPG_Entity::subViewportDraw(AcGiViewportDraw* dc) 
{
	AcDbObjectId idVP = dc->viewportObjectId(); // null if TILEMODE=1
	AcDbObjectId visualStyleId;
	AcDbViewport *vp;
	if ( (es=acdbOpenObject(vp, idVP, AcDb::kForRead)) == Acad::eOk )
	{
		visualStyleId = vp->visualStyle();
		vp->close();
	}
}

 

 


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes
Message 7 of 8

tech
Enthusiast
Enthusiast

Thanks, that works, but what if tilemode = 1? Any ideas. I set TILEMODE = 0 and the code you provided works, the only problem is that TILEMODE = 1 by default I think.

 

Thanks,

 

Mike

0 Likes
Message 8 of 8

tech
Enthusiast
Enthusiast

The following code does what I want. The hint was from TBrammer and the suggestion of viewports.

 

/// <summary> </summary>
void TPG_Entity::subViewportDraw(AcGiViewportDraw* dc)
{
	AcDbDatabase*db =
		acdbHostApplicationServices()->workingDatabase();

	AcDbViewportTable *vpt = nullptr;
	if (db->getViewportTable(vpt, AcDb::kForRead) == Acad::eOk)
	{
		AcDbViewportTableRecord *vp = nullptr;
		if (vpt->getAt(L"*Active", vp, AcDb::kForRead) == Acad::eOk)
		{
			auto vsid = vp->visualStyle();
			AcDbVisualStyle* style = nullptr;
			if (acdbOpenObject(style, vsid, AcDb::kForRead) == Acad::eOk)
			{
				auto type = style->type();
				if (type == AcGiVisualStyle::k2DWireframe)
					acutPrintf(L"2D");
				else
					acutPrintf(L"3D");
				style->close();
			}
			vp->close();
		}
		vpt->close();
	}

	CommonDraw(AcArray<TPG_Entity*>(), dc);
}

Although I am able to get the current visual style, I don't believe this is the best solution to this problem. Surely, this information should be accessible through the drawing context or sub-entity traits?

 

Mike

0 Likes