Replies: 12 comments 7 replies
|
Not currently, acedSSGet uses callbacks which are a bit difficult to wrap, so I skipped over it. To give you an idea, from a C++ perspective, it would be something like this: static struct resbuf* myKeywordCallback(const ACHAR* pcKey)
{
acutPrintf(L"\nKey='%s'", pcKey);
// manually create a selection set
return nullptr;
}
static void AcRxPyApp_idoit1(void)
{
ads_name sset = { 0,0 };
struct resbuf* (*pOldCallback)(const ACHAR*) = NULL;
LPCWSTR promptsKW[] = {
L"My select objects [Item/Element]: ",
L"My remove objects [Item/Element]: "
};
WCHAR KeyWords[256] = L"Item Element _ 1 2";
int stat = acedSSGetKwordCallbackPtr(&pOldCallback);
stat = acedSSSetKwordCallbackPtr(myKeywordCallback);
stat = acedSSGet(L":$:K", promptsKW, KeyWords, NULL, sset);
if (stat == RTNORM)
acedSSFree(sset);
stat = acedSSSetKwordCallbackPtr(pOldCallback);
}I can try to wrap it into the SelectionSet class, it would take some time |
|
The callback in the release will be different, I build the resbuf in C++, so just return the value import traceback
from pyrx import Ap, Db, Ed, Ge, Rx
# return objectids, an error message or none
# if callback is not called, it's Likely you hit a built in kw
def callback(key: str):
print("callback", key)
db = Db.curDb()
if key == "1":
model = db.modelSpace()
return model.objectIds(Db.Line.desc())
elif key == "2":
model = db.modelSpace()
return model.objectIdArray(Db.Circle.desc())
elif key == "3":
ps, ss = Ed.Editor.selectAll()
if ps != Ed.PromptStatus.eNormal:
return "ERROR of Oof:"
return ss.objectIds()
@Ap.Command()
def doit():
try:
keyWords = "LIne CIrcle GEt _ 1 2 3"
promptsKW = (
"Add objects [LIne/CIrcle/GEt]: ",
"Remove objects [LIne/CIrcle/GEt]: ",
)
ps, ss = Ed.Editor.ssgetkw(":$:K", promptsKW, keyWords, [], callback)
print(ps, ss.size())
except Exception:
print(traceback.format_exc()) |
|
added def callback(key: str):
print("callback", key)
db = Db.curDb()
if key == "1":
model = db.modelSpace()
return model.objectIds(Db.Line.desc())
elif key == "2":
model = db.modelSpace()
return model.objectIdArray(Db.Circle.desc())
elif key == "3":
ps, ss = Ed.Editor.selectAll()
if ps != Ed.PromptStatus.eNormal:
return "ERROR of Oof:"
return ss.objectIds()
def othercallback(key: str):
print("othercallback", key)
if key.casefold() == "FU".casefold():
ps, ss = Ed.Editor.selectAll()
if ps != Ed.PromptStatus.eNormal:
return "ERROR of Oof:"
return ss.objectIds()
@Ap.Command()
def pyssgetkwo():
try:
keyWords = "LIne CIrcle GEt _ 1 2 3"
promptsKW = (
"Add objects [LIne/CIrcle/GEt]: ",
"Remove objects [LIne/CIrcle/GEt]: ",
)
ps, ss = Ed.Editor.ssgetkw(":$:K:?", promptsKW, keyWords, [], callback, othercallback)
print(ps, ss.size())
except Exception:
print(traceback.format_exc()) |
|
Can I use it this way? from pyrx import Ed, command
@command
def doit():
prompts = ("Add objects or [Raise]: ", "Remove objects or [Raise]: ")
kwords = "Raise _ 1"
try:
status, sset = Ed.Editor.ssgetkw(":$:K", prompts, kwords, [], callback)
except MyException as e:
print("User exception caught in command:", e)
else:
print(status, sset.size())
def callback(key: str):
if key == "1":
print("Raising exception from callback")
raise MyException("This is a test exception raised from the callback")
class MyException(Exception):
pass |
|
The release build will catch exceptions, otherwise the internal selection set may leak. There’s a limited number of selection sets (256), so allowing exceptions to fall through could eventually cause a crash |
For example:
from pyrx import Db, Ed, command
@command
def doit():
Ed.Editor.initGet(0, "C _ 1")
status, obj_id, _ = Ed.Editor.entSel("\nSelect an entity or [Continue]: ")
if status == Ed.PromptStatus.eKeyword:
kword = Ed.Editor.getInput()
if kword == "1":
change_program_flow()
elif status != Ed.PromptStatus.eOk:
print(status)
else:
process_obj_id(obj_id)
@command
def doit1():
prompts = ("Select objects or [Continue]: ", "Remove objects or [Continue]: ")
def callback(key: str):
if key == "1":
change_program_flow()
status, sset = Ed.Editor.ssgetkw(":$:K", prompts, "C _ 1", [], callback)
if status != Ed.PromptStatus.eOk:
print(status)
else:
process_sset(sset)
def change_program_flow():
print("Changing program flow...")
def process_obj_id(obj_id: Db.ObjectId):
print(f"Processing object id: {obj_id.handle().toString()}")
def process_sset(sset: Ed.SelectionSet):
print(f"Processing selection set with {sset.size()} entities")
|
|
1, In AutoCAD you would use def change_program_flow():
print("Changing program flow...")
ctypes.windll.user32.PostMessageW(Ap.curDoc().docWnd(), 0x0102, 0x0D, 0)
#Ed.Core.postCommand("\x03\x03")2, I don't know, I use R keyword to let the user remove objects. |
|
A side note, [Continue] conflicts with Crossing, you’ll need to capitalize enough letters to break the conflict. prompts = ("Select objects or [COntinue]: ", "Remove objects or [COntinue]: ")
def callback(key: str):
if key == "1":
change_program_flow()
status, sset = Ed.Editor.ssgetkw(":$:K", prompts, "COntinue _ 1", [], callback)
... |
Where did these flags come from? I looked here |
|
I added this for convenience, mode @staticmethod
def selectKeyword(
promptsKW: tuple[str, str],
keyWords: str,
filter: Collection[tuple[int, Any]],
callback: Any,
otherCallback: Any = ...,
/,
) -> tuple[PyEd.PromptStatus, PyEd.SelectionSet]: |


Uh oh!
There was an error while loading. Please reload this page.
Is it possible to set keywords for the
Ed.Editor.select()method? Calling.initGet()before.select()has no effect - only standard keywords are available, as with theSELECTcommand. However, built-in tools have additional command-specific keywords - e.g.MATCHPROPhasSETTINGS.All reactions