Hi, below I show fragment of my code:
JigPromptPointOptions prOptions2 = new JigPromptPointOptions("\nOdległość:"); prOptions2.Keywords.Add("Koniec"); prOptions2.Keywords.Add("Zamień"); prOptions2.Keywords.Default = "Zamień"; prOptions2.BasePoint = mStartPoint; prOptions2.UseBasePoint = true; prOptions2.UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.AcceptOtherInputString | UserInputControls.AnyBlankTerminatesInput | UserInputControls.GovernedByOrthoMode | UserInputControls.GovernedByUCSDetect | UserInputControls.UseBasePointElevation | UserInputControls.NullResponseAccepted | UserInputControls.NoNegativeResponseAccepted | UserInputControls.InitialBlankTerminatesInput; PromptPointResult prResult2 = prompts.AcquirePoint(prOptions2);
My problem is:
How Can I get from User a point or keyword or string value from prResult2???? This fragment is in jig code (in SamplerStatus function). I would like user give me point or keyword or string from prResult2. How can I get it?
I know that:
1) point is in prResult2.Value
2) keyword is in prResult2.StringResult
3) what about string value, where is it? how can I get it? Does it save itself somewhere?
P.S. Sorry for my bad English.
Well, you question is a bit difficult to answer in a few lines of code. That is why poeple hesitate to post reply.
Basically. you need to understand is that your code is inside Jig's Sampler() override method, which is called by Jig when you move the cursor. When user enters something (clicking a point, entering expected value, or entering one of the keyword, jig dragging is terminated.
Usually, a custom Jig is called this way:
PromptResult res=theEditor.Drag(theJig);
So, if user enters a keyword, the jig drag stops, and you test PromptResult to see if a point is picked, or a keyword is entered, then doing things accordingly.
In most cases, while dragging jig with keyword options, the purpose is to change some dragging initial data and after user select a keyword, you probably want the dragging continue/resume. For example, in your case, the draggin originally expects user to pick point. But if user enter a keyword, you want toi dragging for a rotation angle. In this case, you can do this (the code is just off top of my head and not tested):
public class MyJig:DrawJig
{
private string dragMode;
...
public void DoDrag()
{
dragMode=:DIST"
while(true)
{
PromptResult res=_editor.Drag(this);
if (res.Status==PromptStatus.OK ||res.Status==PromptStatus.Keyword)
{
if (res.Status=PromptStatus.OK)
{
//Obtain geometric information changed by the jig dragging and update the target entity accordingly
break;
}
else
{
if (res.StringResult=="ROTATE")
{
dragMode="ROTATE"; //do not break the while() loop, so that draging resumes
}
}
}
else
break;
}
}
private override SamplerStatus Sampler(...)
{
if (dragMode=="DIST")
{
//use JigPromptPointOptions to acquire point. which provides a keyword "ROTATE"
}
if (dragMode=="ROTATE")
{
//use JigPromptAngleOptions to acquire a double value as angle, which provides a keyword "DIST"
}
}
....
}
You can also use Editor.GetKeyword to guide the work flow to different Editor.Drag() call, instea of providing keyword inside dragging process.
Hope this psedocode gives some ideas.
Norman Yuan
Good job Norman, you couldn't be more clearer. Besides, your post reminded me of one from Kean's blog, here a working code sample adapted from that article:
/// <summary> /// Helper function for multiple block jigging and insert /// with rotation support. Optional layer as destination /// </summary> /// <param name="tr">Current transaction</param> /// <param name="doc">Current document</param> /// <param name="idBlock">ObjectID Block to jig</param> /// <param name="idLayer">Destination layer ObjectID, may be null</param> /// <param name="dDefaultRotation">Initial rotation (radiants)</param> /// <param name="offset_x">Optional offset from real inserction point</param> /// <param name="offset_y">Optional offset from real inserction point</param>public static void JigBlock(Transaction tr, Document doc, ObjectId idBlockDef, ObjectId idLayer, Double dDefaultRotation, Double offset_x, Double offset_y) {
// check parameters
if (idBlockDef == ObjectId.Null) return;
if (doc == null) return;
PromptResult pr;
Double dLastRot = 0.0;
// Create the block reference and add it to the jig
Point3d pt = new Point3d(0, 0, 0);
BlockReference br = new BlockReference(pt, idBlockDef);
if (idLayer != ObjectId.Null) br.SetLayerId(idLayer, false);
BlockJig entJig = new BlockJig(br);
entJig.Rotation = dDefaultRotation;
entJig.SetOffset(offset_x, offset_y);
do
{
// Perform the jig operation
pr = doc.Editor.Drag(entJig);
if (pr.Status == PromptStatus.OK)
{
dLastRot = entJig.Rotation;
// If all is OK, let's go and add the entity to the current space
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(doc.Database.CurrentSpaceId, OpenMode.ForWrite);
ms.AppendEntity(entJig.GetEntity());
tr.AddNewlyCreatedDBObject(entJig.GetEntity(), true);
// Start attrib/annot-scale support code
BlockTableRecord bd = (BlockTableRecord)tr.GetObject(idBlockDef, OpenMode.ForRead);
if (bd.Annotative == AnnotativeStates.True)
{
ObjectContextManager ocm = doc.Database.ObjectContextManager;
ObjectContextCollection occ = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");
ObjectContexts.AddContext(br, occ.CurrentContext);
}
// Add the attributes
foreach (ObjectId attId in bd)
{
Entity ent = (Entity)tr.GetObject(attId, OpenMode.ForRead);
if (ent is AttributeDefinition)
{
AttributeDefinition ad = (AttributeDefinition)ent;
AttributeReference ar = new AttributeReference();
ar.SetAttributeFromBlock(ad, br.BlockTransform);
br.AttributeCollection.AppendAttribute(ar);
tr.AddNewlyCreatedDBObject(ar, true);
}
} // End attrib/annot-scale support code
// Call a function to make the graphics display
// (otherwise it will only do so when we Commit)
doc.TransactionManager.QueueForGraphicsFlush();
// Create new Jig entity for next loop
br = new BlockReference(pt, idBlockDef);
if (idLayer != ObjectId.Null) br.SetLayerId(idLayer, false);
entJig = new BlockJig(br);
entJig.Rotation = dLastRot;
entJig.SetOffset(offset_x, offset_y);
}
else if (pr.Status == PromptStatus.Keyword)
{
// ask for rotation
PromptDoubleOptions rot_opt = new PromptDoubleOptions("Rotation");
rot_opt.DefaultValue = dLastRot / csMath.PI * 180;
rot_opt.AllowNone = true;
PromptDoubleResult pdr = doc.Editor.GetDouble(rot_opt);
if (pdr.Status == PromptStatus.OK)
{
entJig.Rotation = dLastRot = pdr.Value / 180 * csMath.PI;
}
}
}
while ((pr.Status == PromptStatus.OK) || (pr.Status == PromptStatus.Keyword));
}
public class BlockJig : EntityJig { Point3d mCenterPt, mActualPoint, mOffset; Double mRotation; public BlockJig(BlockReference br) : base(br) { mOffset = new Point3d(0, 0, 0); mCenterPt = br.Position; mRotation = 0.0; } protected override SamplerStatus Sampler(JigPrompts prompts) { JigPromptPointOptions jigOpts = new JigPromptPointOptions(); jigOpts.UserInputControls = ( UserInputControls.Accept3dCoordinates | UserInputControls.NullResponseAccepted | UserInputControls.AcceptOtherInputString | UserInputControls.NoNegativeResponseAccepted); jigOpts.SetMessageAndKeywords("\nInsertion point or [Rotation]: ", "Rotation"); PromptPointResult dres = prompts.AcquirePoint(jigOpts); if (dres.Status == PromptStatus.OK) { if (mActualPoint != dres.Value) { mActualPoint = dres.Value; return SamplerStatus.OK; } } return SamplerStatus.NoChange; } protected override bool Update() { mCenterPt = mActualPoint; try { BlockReference br = (BlockReference)Entity; // execute offset starting from the current UCS Matrix3d ucs = Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem; Matrix3d trans = Matrix3d.Rotation(br.Rotation, ucs.CoordinateSystem3d.Zaxis, new Point3d(0, 0, 0)); // rotate offset with current active rotation Point3d pOffset = mOffset.TransformBy(trans); // position jig mouse curson on requested offset ((BlockReference)Entity).Position = new Point3d(mCenterPt.X + pOffset.X, mCenterPt.Y + pOffset.Y, 0); } catch (System.Exception) { return false; } return true; } public Entity GetEntity() { return Entity; } public Double Rotation { get { return mRotation; } set { mRotation = value; BlockReference br = (BlockReference)Entity; Matrix3d mx = Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem; Matrix3d trans = Matrix3d.Rotation(mRotation, mx.CoordinateSystem3d.Zaxis, br.Position); br.BlockTransform = mx * trans; } } public Point3d Origin { get { return mActualPoint; } } public void SetOffset(Double x, Double y) { mOffset = new Point3d(-x, -y, 0); } }
But where is string value? I can get from user keyword, point3d, but if I type for example "aaaaaaaa", which isn't a point3d or keyword, then this string disappear. I can't find it anywhere. Which variable cantains my typed string text? Below my code:
class JPunktyPreta : EntityJig { //Zmienne public Point3d mEndPoint = new Point3d(); public Point3d mStartPoint = new Point3d(); public Point3d mPunkt1Biezacy = new Point3d(); public Point3d mPunkt2Biezacy = new Point3d(); public Point3d mPunktChwilowy = new Point3d(); public double mAngle = 0; public ObjectId oidPierwszy = new ObjectId(); public ObjectId oidDrugi = new ObjectId(); public int iEtap = 1; //Konstruktor public JPunktyPreta(Line ent) : base(ent) { } protected override bool Update() { switch(iEtap) { case 1: (Entity as Line).EndPoint = mEndPoint; break; case 2: { (Entity as Line).StartPoint = mStartPoint; (Entity as Line).EndPoint = mEndPoint; break; } default: break; } return true; } protected override SamplerStatus Sampler(JigPrompts prompts) { switch(iEtap) { case 1: { //Opis do pobrania punktu JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nPunkt:"); prOptions1.BasePoint = (Entity as Line).StartPoint; prOptions1.UseBasePoint = true; prOptions1.UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.AnyBlankTerminatesInput | UserInputControls.GovernedByOrthoMode | UserInputControls.GovernedByUCSDetect | UserInputControls.UseBasePointElevation | UserInputControls.InitialBlankTerminatesInput | UserInputControls.NullResponseAccepted; PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1); if (prResult1.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; if (prResult1.Value.Equals(mEndPoint)) { return SamplerStatus.NoChange; } else { mEndPoint = prResult1.Value; mStartPoint = (Entity as Line).StartPoint; mAngle = (Entity as Line).Angle; return SamplerStatus.OK; } } case 2: { JigPromptPointOptions prOptions2 = new JigPromptPointOptions("\nOdległość:"); prOptions2.Keywords.Add("Koniec"); prOptions2.Keywords.Add("Zamień"); prOptions2.Keywords.Default = "Zamień"; prOptions2.BasePoint = mStartPoint; prOptions2.UseBasePoint = true; prOptions2.UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.AcceptOtherInputString | UserInputControls.AnyBlankTerminatesInput | UserInputControls.GovernedByOrthoMode | UserInputControls.GovernedByUCSDetect | UserInputControls.UseBasePointElevation | UserInputControls.NullResponseAccepted | UserInputControls.NoNegativeResponseAccepted | UserInputControls.InitialBlankTerminatesInput; PromptPointResult prResult2 = prompts.AcquirePoint(prOptions2); if (prResult2.Status == PromptStatus.Other) { SWF.MessageBox.Show(prResult2.StringResult); } if (prResult2.Value.Equals(mEndPoint)) { return SamplerStatus.NoChange; } else { //Jeżeli naciśnięto Zamień zmień łapkę if (prResult2.StringResult == "Zamień") { if (mPunktChwilowy == mPunkt1Biezacy) { mStartPoint = mPunkt2Biezacy; mPunktChwilowy = mPunkt2Biezacy; } else { mStartPoint = mPunkt1Biezacy; mPunktChwilowy = mPunkt1Biezacy; } } if (prResult2.StringResult == "aa") { double dPrzesuniecie; SWF.MessageBox.Show("dupa"); try { dPrzesuniecie = Convert.ToDouble(prResult2.StringResult.ToString()); } catch (FormatException e) { //wprowadzony tekst nie jest sekwencją liczb return SamplerStatus.OK; } if (mPunktChwilowy == mPunkt1Biezacy) funEdit.bMove(oidPierwszy, mAngle - Math.PI, dPrzesuniecie); else funEdit.bMove(oidDrugi, mAngle, dPrzesuniecie); } mEndPoint = prResult2.Value; return SamplerStatus.OK; } } default: return SamplerStatus.Cancel; } } }
and main function:
public static bool Jig_PunktyPreta() { try { Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor; Database db = HostApplicationServices.WorkingDatabase; AS.Document acDoc = MgdAcApplication.DocumentManager.MdiActiveDocument; //Pobiera punkt startowy dla linii PromptPointResult ppr = ed.GetPoint("\nPunkt:"); //Jeżeli użytkownik zrobi coś innego niż wstawienie kliknięcie punktu to przerywamy funkcję if (ppr.Status != PromptStatus.OK) return false; //Jigujemy na etapie nr 1 Point3d pt = ppr.Value; Line ent = new Line(pt, pt); //Nie wiem po co ta transformacja ent.TransformBy(MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem); //Do konstruktora podana jest liniia która będzie zmieniana na bieżąco JPunktyPreta jigger = new JPunktyPreta(ent); PromptResult pr = ed.Drag(jigger); if (pr.Status == PromptStatus.OK) { jigger.oidPierwszy = funZbr.Wstaw_wskier(jigger.mStartPoint, jigger.mAngle + Math.PI); jigger.oidDrugi = funZbr.Wstaw_wskier(jigger.mEndPoint, jigger.mAngle); } else { ent.Dispose(); return false; } //aktualizacja ostatecznych punktów jigger.mPunkt1Biezacy = jigger.mStartPoint; jigger.mPunkt2Biezacy = jigger.mEndPoint; jigger.mPunktChwilowy = jigger.mStartPoint; //Jeżeli udało się wstawić łapki to przechodzimy do drugiego etapu (dokładniejsze manewrowanie łapkami) jigger.iEtap = 2; //Ponowne wywołanie jiggera tylko że na etapie 2 int i = 5; while (i-->0) { pr = ed.Drag(jigger); SWF.MessageBox.Show(pr.ToString()); } return true; } catch { return false; } }
If you supply a list of keywords, why do you allow user to enter anything else other than the keywords (that is, you set UserInputControls.AcceptOtherInputString flag in the PromptPointOptions)?
Since you allow other input string, besides the keywords, after user enteres "aaaaa" and hit enter, the jig will termintes and return PromptResult with its Status=PromptStatus.Other. However, enter entered string value ("aaaaa") is not returned with PromptResult. If this is what you wanted (i.e. allow user enter whatever he/she likes), then you need to test PromptResult for the status of PromptStatus.Other.
But most likely, since you supplied keyword list, you only want user to either pick point, or enter a keyword, nothing else. So, you need to remove UserInputControls.AcceptOtherInputString. This way, if user enter non-kwyword string ("aaaa", for example) and hit enter, nothing happens. That is, the Jig draging stays and still waiting for a point or a keyword (or, of course, Esc for cancelling).
Norman Yuan
I want to convert this string to double value, what give me a distance. Some blocks will be moved with this distance. Then the jig will ask again for keyword, string value or point, unless user enter keyword "K" what means end of jig. I need user can enter one of these three values. Perhaps there is another way to realize it. Maybe prompts.Getstring will give me a string, keyword or point :).
In that case, you need to use JigPromptDistanceOptions with keywords, which expects user to input a number, or keyword, instead of JigPromptPointOptions with keyword, which expectes user to pick a point or enter a keyword.
In your case, the distance can likely be obtained by picking a point, or enter a distance number, your keywords should have an option for user to pick point (when the jig is expecting distnace number), or an option to enter a number (when jig is expecting a point to be picked). Based on the keyword entered, you user either JigPromptPointOptions, or JigPromptDistanceOptions accordingly in conjunction with necessary keywords.
You cannot use Editor.GetString() because you r code is now inside the Jig,Sampler().
Norman Yuan
I don't believe I can't reach such effect (look attachment) with C#. I realy need solution exactly like this in the attachment made by Lisp.
To me seems possible, but maybe you shouldn't just try to mimic the lisp routine. Focus on what the user need and what the function must accomplish.
You have all the bricks: you can freely use the Autocad input system, asking for points, distances, objects, keywords, and you can use jig to show the 'hands' move dynamically while you move the mouse (while in lisp you see the effect only after clicking the destination point or distance).
If you need something more advanced you may override even grips functionality and show your owns, and what about using transient graphics to show levels and distances while you jig?
Don't give up! 😉
Can you give me some links, examples, which direct me. I can't find SDK for jigs anywhere.
I really need such form of getting data from user as on the movie. I don't want to get knowledge on jigs, beacuse it is single case. This jig in my program will be last.
I have an idea. Is it possible to retrieve last entered string during jig executing (not keyword)? I would like to use it after function Drag(). It would be the solution of my problem.
while (i-- > 0) { pr = ed.Drag(jigger); //in this place I would like to retrieve last entered string }