Author Topic: Get and change current view  (Read 16515 times)

0 Members and 1 Guest are viewing this topic.

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Get and change current view
« on: June 08, 2006, 01:27:50 AM »
I've been tormented by this for a while now and have yet to find a solution (in .net anyway).

This is a snippet that achieves half of the puzzle but still lacks the proper functionality, it will be a start anyway -
Code: [Select]
[CommandMethod("TEST")]
public static void Test()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
Transaction tr = db.TransactionManager.StartTransaction();

//(ideally I'd like to get the 'Current' active view and change it)
//get/create the view table record for our temporary view object:
ViewTable vt = (ViewTable)tr.GetObject(db.ViewTableId, OpenMode.ForWrite);
ViewTableRecord vtr;
//check if it's there, if not create it:
try
{
if(!vt.Has("TempViews"))
{
vtr = new ViewTableRecord();
vtr.Name = "TempViews";
vt.Add(vtr);
}
//ok, got a vtr, change some settings:
vtr = (ViewTableRecord)tr.GetObject(vt["TempViews"], OpenMode.ForWrite);
vtr.Target = db.Ucsorg;
vtr.CenterPoint = new Point2d(db.Ucsorg.X,db.Ucsorg.Y);
vtr.ViewDirection = db.Ucsxdir.CrossProduct(db.Ucsydir);
vtr.BackClipDistance = -500.0;
vtr.BackClipEnabled = true;
vtr.FrontClipDistance = 500.0;
vtr.FrontClipEnabled = true;
//******here is where it needs to be set to the current view*******//
tr.Commit();
}
finally
{
tr.Dispose();
}
}

[CommandMethod("TEST2")]//to turn off clipping:
public static void Test2()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
Transaction tr = db.TransactionManager.StartTransaction();

//get our view and turn off some settings and make it current:
ViewTable vt = (ViewTable)tr.GetObject(db.ViewTableId, OpenMode.ForWrite);
if(!vt.Has("TempViews"))
return;//it's not here...forget it!
try
{
ViewTableRecord vtr = (ViewTableRecord)tr.GetObject(vt["TempViews"], OpenMode.ForWrite);
vtr.BackClipDistance = 0.0;
vtr.FrontClipDistance = 0.0;
vtr.BackClipEnabled = false;
vtr.FrontClipEnabled = false;
//******here is where it needs to be set to the current view*******//
tr.Commit();
}
finally
{
tr.Dispose();
}
}

This will create a view in the view table that I could use as a temp view for changing as required (to avoid creating new views that may only be needed a few times) but I have to go to the view table in the editor and set it as the current view to use it.

I've also tried it with viewports by getting the *Active vp, I could change these values also (checked 'em with arxdbg) but couldn't update the view??

any thoughts??
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Bryco

  • Water Moccasin
  • Posts: 1882
Re: Get and change current view
« Reply #1 on: June 08, 2006, 02:10:01 AM »
Mick I've been working on the same thing in vba. The setvars viewdir etc all are current whereas anything in vba isn't. I found a save or a change space updated the vba view (not the best). But only recently did I find that deleting the active.viewport updates the viewport beautifully. Once this is updated a new view takes on all the same stuff.
Hope this helps.

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Get and change current view
« Reply #2 on: June 08, 2006, 02:28:58 AM »
I wouldn't have a clue how I would delete the vp in the manner you describe but something to think about.

It seems they didn't right the wrapper for acedSetCurrentView() in 2006 but it's available in 2007...doh!
Looks like I have to write my own again.
Thanks Bryco.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Get and change current view
« Reply #3 on: June 08, 2006, 03:21:37 AM »
And here it is:-

The code for a function in the C++ managed arx dll (there's a lot more to setting it up it but this is the most important part)
Code: [Select]
void DCS_3D::HlrEngine::DCSViews::SetCurrentView(ObjectId viewId)
{
AcDbViewTableRecord * pVtr;
AcDbViewport * pVP = NULL;

AcTransaction *pTrans = actrTransactionManager->startTransaction();
assert(pTrans != NULL);
AcDbObject   *pObj = NULL;
AcDbObjectId  objId;
Acad::ErrorStatus es = eOk;
if ((es = pTrans->getObject(pObj, GETOBJECTID(viewId),AcDb::kForRead)) != Acad::eOk)
{
acutPrintf("\nFailed to obtain the pVtr");
actrTransactionManager->abortTransaction();
return;
}

assert(pObj != NULL);
pVtr = AcDbViewTableRecord::cast(pObj);

if (pVtr == NULL)
{
acutPrintf("\nNot a VP!!!");
actrTransactionManager->abortTransaction();
return;
}
acedSetCurrentView(pVtr,pVP);

actrTransactionManager->endTransaction();

}

and I replace my comment in the above code (ie //****here's...) with this after adding the ref to my manged wrapper dll -
Code: [Select]
DCSViews viewtools = new DCSViews();
viewtools.SetCurrentView(vtr.ObjectId);

The only problem is I still need the temp view, I still have to work out how to get the current one.

I'm off for a beer :)
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • Cry havoc and let loose the dogs of war.
Re: Get and change current view
« Reply #4 on: June 08, 2006, 12:26:12 PM »
This will create a view in the view table that I could use as a temp view for changing as required (to avoid creating new views that may only be needed a few times) but I have to go to the view table in the editor and set it as the current view to use it.

I've also tried it with viewports by getting the *Active vp, I could change these values also (checked 'em with arxdbg) but couldn't update the view??

any thoughts??
Hey Mick,
I'm actually planning on doing something very similar this afternoon.  Do you have to add the temp VTR to the VT in order to set it current via acadSetCurrentView()?  I would guess not, but I haven't tried it yet.

BTW, In 2007 there is a method to set the current view :-)

I'll post back whatever I come up with.
Bobby C. Jones

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Get and change current view
« Reply #5 on: June 08, 2006, 02:40:38 PM »
The code for a function in the C++
What about to P/Invoke acedSetCurrentView from C#?

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • Cry havoc and let loose the dogs of war.
Re: Get and change current view
« Reply #6 on: June 08, 2006, 04:31:55 PM »
I'll post back whatever I come up with.
2007 makes this very easy

Code: [Select]
Editor currentEditor = acadApp.DocumentManager.MdiActiveDocument.Editor;

ViewTableRecord currentView = currentEditor.GetCurrentView();

ViewTableRecord modifiedView = DoMagicallStuffWithView(currentView);

currentEditor.SetCurrentView(modifiedView);

I started looking at what it would take to mimic this in 2006, and quit :-) 

This partial code is %100 completely untested (and unrefined)
Code: [Select]
    private static ViewTableRecord GetCurrentView2006()
    {
      Editor currentEditor = acadApp.DocumentManager.MdiActiveDocument.Editor;
      Database currentDatabase = currentEditor.Document.Database;

      ViewTableRecord currentView = new ViewTableRecord();

      SetViewMode(ref currentView);
      SetBackZ(ref currentView);
      SetFrontZ(ref currentView);
      EtcEtcEtcAdNaseumForOtherViewProperties(ref currentView);

      return currentView;
    }

    private static void SetViewMode(ref ViewTableRecord currentView)
    {
      const short PERSPECTIVE_ENABLED = 1;
      const short FRONT_CLIP_ENABLED = 2;
      const short BACK_CLIP_ENABLED = 4;
      const short FRONT_CLIP_AT_EYE = 16;

      currentView.PerspectiveEnabled = false;
      currentView.FrontClipEnabled = false;
      currentView.BackClipEnabled = false;
      currentView.FrontClipAtEye = false;

      ResultBuffer viewModeInfo = acadApp.GetSystemVariable("VIEWMODE") as ResultBuffer;
      foreach (TypedValue valuePair in viewModeInfo)
      {
        switch ((short)valuePair.Value)
        {
          case PERSPECTIVE_ENABLED:
            currentView.PerspectiveEnabled = true;
            break;
          case FRONT_CLIP_ENABLED:
            currentView.FrontClipEnabled = true;
            break;
          case BACK_CLIP_ENABLED:
            currentView.BackClipEnabled = true;
            break;
          case FRONT_CLIP_AT_EYE:
            currentView.FrontClipAtEye = true;
            break;
        }
      }
    }
« Last Edit: June 08, 2006, 04:52:42 PM by Bobby C. Jones »
Bobby C. Jones

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Get and change current view
« Reply #7 on: June 08, 2006, 05:54:45 PM »
...  Do you have to add the temp VTR to the VT in order to set it current via acadSetCurrentView()?  I would guess not, but I haven't tried it yet.

At the moment yes because it's easy to pass objectId's back and forth with the managed wrapper, I need the objectId to exist in the db for the transaction to get it.

As Alexander said though it's probably easier to use pInvoke and I wouldn't have to create a new table record, just pass the pointer of the new view in memory, I'll give that a go and let you know.
Cheers,
Mick.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Get and change current view
« Reply #8 on: June 08, 2006, 07:18:01 PM »
When will it end!

Ok, trying pInvoke but I have a problem with the null pVP.
In the help it says-
Quote
This function uses the information from the AcDbViewTableRecord pointed to by pVwRec to set the view in the AcDbViewport pointed to by pVP (if pVP != NULL) or in the current viewport (if pVP == NULL).

Here's the code, any ideas?
Code: [Select]
[DllImport("acad.exe",CallingConvention=CallingConvention.Cdecl)]
private static extern int acedSetCurrentView(IntPtr pVtr, IntPtr pVP);

[CommandMethod("TEST")]
public static void Test()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
Transaction tr = db.TransactionManager.StartTransaction();

ViewTableRecord vtr = new ViewTableRecord();
Autodesk.AutoCAD.DatabaseServices.Viewport pVP = new Autodesk.AutoCAD.DatabaseServices.Viewport();
pVP = null;
try
{
vtr.Target = db.Ucsorg;
vtr.CenterPoint = new Point2d(db.Ucsorg.X,db.Ucsorg.Y);
vtr.ViewDirection = db.Ucsxdir.CrossProduct(db.Ucsydir);
vtr.BackClipDistance = -500.0;
vtr.BackClipEnabled = true;
vtr.FrontClipDistance = 500.0;
vtr.FrontClipEnabled = true;
int i = acedSetCurrentView(vtr.UnmanagedObject,pVP.UnmanagedObject);
tr.Commit();
}
finally
{
tr.Dispose();
}
}
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Get and change current view
« Reply #9 on: June 09, 2006, 04:17:12 AM »
int i = acedSetCurrentView(vtr.UnmanagedObject,IntPtr.Zero);

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Get and change current view
« Reply #10 on: June 12, 2006, 07:09:38 PM »
no go Alexander, big crash!

I tried setting the pVP = IntPtr.Zero; too but it would not cast it.

any ideas??
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Glenn R

  • Guest
Re: Get and change current view
« Reply #11 on: June 12, 2006, 08:22:22 PM »
Try passing null as the second parameter there Mick...

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Get and change current view
« Reply #12 on: June 12, 2006, 08:38:14 PM »
That was the first thing I tried - no good. I need to pass a C NULL which IntPtr.Zero should do??

I've searched and found some vb.net code at the adesk ng which passed 'Nothing' as this parameter which basically sets an object to it's default values (according to help), here's the link -> http://discussion.autodesk.com/thread.jspa?messageID=5087519
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Glenn R

  • Guest
Re: Get and change current view
« Reply #13 on: June 12, 2006, 09:45:30 PM »
Pieced together from several places:

Code: [Select]
public class tcgsClass
{
[DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedSetCurrentView@@YA?AW4ErrorStatus@Acad@@PAVAcDbViewTableRecord@@PAVAcDbViewport@@@Z")]
private static extern int acedSetCurrentView(IntPtr pVtr, IntPtr pVP);

[DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedTrans")]
static extern int acedTrans(double[] point, IntPtr fromRb, IntPtr toRb, int disp, double[] result);

public tcgsClass()
{
//
// Nothing to do here...
//
}

// Define Command "MickyDViewTest"
[CommandMethod("MickyDViewTest")]
static public void MickyDViewCommand()
{
Document pCurrentDoc = acadApp.DocumentManager.MdiActiveDocument;
Editor pEd = pCurrentDoc.Editor;

short viewMode = (short)acadApp.GetSystemVariable("VIEWMODE");

double backZ = (double)acadApp.GetSystemVariable("BACKZ");
double frontZ = (double)acadApp.GetSystemVariable("FRONTZ");
double lensLength = (double)acadApp.GetSystemVariable("LENSLENGTH");
double viewSize = (double)acadApp.GetSystemVariable("VIEWSIZE");
double viewTwist = (double)acadApp.GetSystemVariable("VIEWTWIST");

Point3d viewCtr = (Point3d)acadApp.GetSystemVariable("VIEWCTR");
Point3d target = (Point3d)acadApp.GetSystemVariable("TARGET");
// Direct cast to vector3d fails here, so go for a point...
Point3d viewDirTemp = (Point3d)acadApp.GetSystemVariable("VIEWDIR");
//...now convert it to an AcGeVector3d...
Vector3d viewDir = new Vector3d(viewDirTemp[0], viewDirTemp[1], viewDirTemp[2]);

ViewTableRecord pVtr = new ViewTableRecord();

pVtr.PerspectiveEnabled = (viewMode & 1) == 1;
pVtr.FrontClipEnabled = (viewMode & 2) == 2;
pVtr.BackClipEnabled = (viewMode & 4) == 4;
pVtr.FrontClipAtEye = (viewMode & 16) == 16;
pVtr.BackClipDistance = backZ;

ResultBuffer rbWCS = new ResultBuffer(new TypedValue(5003, 0));
ResultBuffer rbUCS = new ResultBuffer(new TypedValue(5003, 1));
ResultBuffer rbDCS = new ResultBuffer(new TypedValue(5003, 2));

double[] result = new double[]{0,0,0};

acedTrans(viewCtr.ToArray(), rbUCS.UnmanagedObject, rbDCS.UnmanagedObject, 0, result);
pVtr.CenterPoint = new Point2d(result[0], result[1]);

pVtr.FrontClipDistance = frontZ;
pVtr.LensLength = lensLength;

acedTrans(target.ToArray(), rbUCS.UnmanagedObject, rbWCS.UnmanagedObject, 0, result);
pVtr.Target = new Point3d(result);

acedTrans(viewDir.ToArray(), rbUCS.UnmanagedObject, rbWCS.UnmanagedObject, 1, result);
pVtr.ViewDirection = new Vector3d(result);

pVtr.Height = viewSize;
pVtr.Width = 1;

// Add some twist magic to see that it works...
pVtr.ViewTwist = viewTwist + 0.01;

acedSetCurrentView(pVtr.UnmanagedObject, IntPtr.Zero);

// Just to be safe...
pVtr.Dispose();


}

Dumpbin.exe from memory will give you the function name to call (the mangled one).

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Get and change current view
« Reply #14 on: June 12, 2006, 09:54:54 PM »
The entry point...the penny finally drops!

Thanks again Glenn.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Get and change current view
« Reply #15 on: June 12, 2006, 10:10:14 PM »
Ooohhhh ... bookmarked .. !

Thanks Glenn
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Get and change current view
« Reply #16 on: June 13, 2006, 02:33:42 AM »
Here is another approach to getting the current view param's.
I'm having trouble setting the view centre, acedTrans'ing it in a large model put's me out in the paddock so some work needs to be done there.
This sets up a view to the current ucs z direction using the current vport size (plus a bit more to centre the view just a little). I will probably use a db object's extents to set up a view with clipping for my application needs but this is a start.
Many thanks Glenn and to rwilkins (from the adesk ng).

Code: [Select]
                [DllImport("acad.exe",CallingConvention=CallingConvention.Cdecl,
EntryPoint = "?acedSetCurrentView@@YA?AW4ErrorStatus@Acad@@PAVAcDbViewTableRecord@@PAVAcDbViewport@@@Z")]
private static extern int acedSetCurrentView(IntPtr pVtr, /*IntPtr.Zero*/IntPtr pVP);

[DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedTrans")]
static extern int acedTrans(double[] point, IntPtr fromRb, IntPtr toRb, int disp, double[] result);

[DllImport("acad.exe", CallingConvention=CallingConvention.Cdecl,
EntryPoint="?acedVports2VportTableRecords@@YA?AW4ErrorStatus@Acad@@XZ")]
private static extern bool acedVports2VportTableRecords();

[CommandMethod("ViewTest2")]
static public void MickyDViewCommand2()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed =
Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
Transaction tr = db.TransactionManager.StartTransaction();
try
{
if(db.TileMode == true)//make sure we're in model space, else leave:
{
//convert current vport info to our viewtable objects:
//note:there can be more than one view
acedVports2VportTableRecords();
//get the current view, should be the first un-erased viewtable record:
ViewportTable vpt = (ViewportTable)tr.GetObject(db.ViewportTableId,OpenMode.ForRead);
ViewportTableRecord currVptr = null;
foreach(ObjectId id in vpt)
{
if(!id.IsErased)
{
//got the first un erased record, return:
currVptr = (ViewportTableRecord)tr.GetObject(id,OpenMode.ForRead);
break;
}
}

//use some of the info in the current vtr to set to our new one:
ViewTableRecord newVtr = new ViewTableRecord();
newVtr.IsPaperspaceView = false;
newVtr.Target = db.Ucsorg;
newVtr.Height = currVptr.Height*2;
newVtr.Width = currVptr.Width*2;
newVtr.ViewDirection = db.Ucsxdir.CrossProduct(db.Ucsydir);
//set the new view:
acedSetCurrentView(newVtr.UnmanagedObject, IntPtr.Zero);
//Just to be safe...
newVtr.Dispose();
}
tr.Commit();
}
finally
{
tr.Dispose();
}
}
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Get and change current view
« Reply #17 on: February 23, 2008, 03:03:53 AM »

Glenn, Mick :
Thanks for this ... I'm doing some prep' work for next weekend :-)

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
Re: Get and change current view
« Reply #18 on: February 23, 2008, 04:57:27 PM »
What's happening next weekend Kerry...???

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Get and change current view
« Reply #19 on: February 23, 2008, 04:59:32 PM »

What's happening next weekend Kerry...???

I'll be writing some code, just for a change ... :-)
just planning this weekend .. and doing some painting.
« Last Edit: February 23, 2008, 05:09:34 PM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.