I’m looking to have the user either pick a point in a viewport or simply key in a Z value. I have something that’s working 99%, however, it has one small problem. It’s necessary to specify a default value for the ZLevel with
I would like to return this default value if Enter is pressed. But I would also like to return None if Esc is pressed. BUt I don’t know how to do both. In the following, if I use return default, I will get the default whether the user presses Enter or Esc. If I use just return, I don’t get the default value with Enter… there must be a simple solution to this. I guess I could use an Esc key test in there, but isn’t there a better way with soe GetOption option that I missed?
Thx, --Mitch
import Rhino
import scriptcontext as sc
def GetPointOrValue(msg,prompt,default):
#default is float or integer - shown on command line
gp = Rhino.Input.Custom.GetPoint()
gp.SetCommandPrompt(msg)
dblOption = Rhino.Input.Custom.OptionDouble(default)
gp.AddOptionDouble(prompt, dblOption)
while True:
get_rc = gp.Get()
if gp.CommandResult() == Rhino.Commands.Result.Success:
if get_rc==Rhino.Input.GetResult.Point:
return gp.Point()
elif get_rc==Rhino.Input.GetResult.Option:
return dblOption.CurrentValue
return
#or,
#return default
msg="Pick point or key in value for Z level"
prompt="ZValue"
result=GetPointOrValue(msg,prompt,0.0)
if isinstance(result,Rhino.Geometry.Point3d):
sc.doc.Objects.AddPoint(result)
sc.doc.Views.Redraw()
elif isinstance(result,float) or isinstance(result,int):
print "Z value is {}".format(result)
else:
print "Error"
import Rhino
import scriptcontext as sc
def GetPointOrValue(msg,prompt,default):
#default is float or integer - shown on command line
gp = Rhino.Input.Custom.GetPoint()
gp.SetCommandPrompt(msg)
dblOption = Rhino.Input.Custom.OptionDouble(default)
gp.AddOptionDouble(prompt, dblOption)
gp.SetDefaultNumber(default)
while True:
get_rc = gp.Get()
if gp.CommandResult() == Rhino.Commands.Result.Success:
if get_rc==Rhino.Input.GetResult.Point:
return gp.Point()
elif get_rc==Rhino.Input.GetResult.Option:
return dblOption.CurrentValue
else: return
msg="Pick point or key in value for Z level"
prompt="ZValue"
result=GetPointOrValue(msg,prompt,0.0)
if isinstance(result,Rhino.Geometry.Point3d):
sc.doc.Objects.AddPoint(result)
sc.doc.Views.Redraw()
elif isinstance(result,float) or isinstance(result,int):
print "Z value is {}".format(result)
else:
print "Error"
It works correctly with Esc and Enter, but the problem here is I get a double prompt:
Pick point or key in value for Z level <0.000> ( ZValue=0 ):
And of course, I’m not finished yet… What I really want to do is also have a Boolean option on the command line as well. Something like:
import Rhino
import scriptcontext as sc
def GetPointOrZ():
gp = Rhino.Input.Custom.GetPoint()
gp.SetCommandPrompt("Pick point or key in Z value")
dblOption = Rhino.Input.Custom.OptionDouble(0.0)
boolOption = Rhino.Input.Custom.OptionToggle(True, "Individually", "AsGroup")
gp.AddOptionDouble("ZValue", dblOption)
gp.AddOptionToggle("TransformObjects", boolOption)
point=None
while True:
get_rc = gp.Get()
if get_rc==Rhino.Input.GetResult.Point:
point = gp.Point()
elif get_rc==Rhino.Input.GetResult.Option:
continue
break
return (point,dblOption.CurrentValue,boolOption.CurrentValue)
result=GetPointOrZ()
if result[0]:
strPt="({:.2f},{:.2f},{:.2f})".format(result[0].X,result[0].Y,result[0].Z)
else:
strPt="No point picked"
if result[2]: strTrans="AsGroup"
else: strTrans="Individually"
print "Point={}, Z={}, TransformObjects={}".format(strPt,result[1],strTrans)
The problem here again is how to differentiate between Esc and Enter. It’s not a really big deal, but I was just kind of hoping to have the finesse to be able to execute the command with its default values if Enter is pressed, and do nothing if Esc is pressed.
This had me cornered a while ago as well. You need to enable gp.AcceptNothing(true). Then Enter will return Nothing and Esc will return Cancel. Otherwise both return Cancel and you can’t distinguish.
Continuing in the same vein… Now trying to get objects plus have a Boolean toggle on the command line simultaneously… My problem is now if I select some objects and then click the toggle, the selection is lost… I must be structuring this wrong… Here’s what I have so far:
import rhinoscriptsyntax as rs
import Rhino
def GetObjsPlusBool(prompt,b_opts,def_bool):
#prompt==command line prompt
#b_opts==tuple of strings for Boolean choices - (Name,FalseValue,TrueValue)
#def_bool==default value for Boolean
#returns None if Esc is pressed or no objects are chosen
#otherwise, returns tuple of ([object ids], Boolean)
go = Rhino.Input.Custom.GetObject()
go.SetCommandPrompt(prompt)
boolOption = Rhino.Input.Custom.OptionToggle(def_bool,b_opts[1],b_opts[2])
go.AddOptionToggle(b_opts[0], boolOption)
go.AcceptNothing(True)
while True:
get_rc = go.GetMultiple(1,0)
if get_rc==Rhino.Input.GetResult.Option: continue
elif get_rc==Rhino.Input.GetResult.Cancel: return
elif get_rc==Rhino.Input.GetResult.Nothing: break
elif get_rc==Rhino.Input.GetResult.Object: break
ids=go.Objects()
return (ids,boolOption.CurrentValue)
def TestGetObjsPlusBool():
prompt="Pick some objects"
bool_opts=("BooleanChoice","ChooseFalse","ChooseTrue")
result=GetObjsPlusBool(prompt,bool_opts,True)
if result is None: print "Function cancelled" ; return
if result[0] is None: obj_count="No"
else: obj_count=len(result[0])
print "{} objects chosen, Boolean value={}".format(obj_count,result[1])
TestGetObjsPlusBool()
Do I have to go through something as elaborate as this to be able to keep the objects selected?
I think this is normal Rhino behavior. For example, try the Split command, select a surface to be split and a line to split it with. Then click the option Shrink. The line will be deselected.
Hmmm, not convinced on that one. For example with ExtrudeCrv, any of the command-line toggles such as Solid=Yes/No or BothSides can be hit without killing a preselection…
ids = []
while True:
gr = go.Get() #select one object
if gr == Rhino.Input.GetResult.Option: continue
if gr == Rhino.Input.GetResult.Cancel:
for id in ids:
id.Object().Highlight(False) #unhighlight before returning
return
if gr == Rhino.Input.GetResult.Nothing: break
if gr == Object:
id = go.Object(0) # get first object ref
ids.extend(id)
id.Object().Select(False) #unselect to prevent selecting it again
id.Object().Highlight(True) #highlight object to show it is selected
for id in ids:
id.Object.Highlight(False) #unhighlight before returning
return (ids, boolOption.CurrentValue)
Basically, you select objects one-at-a-time, then deselect and highlight them (the user will see this a being selected, but the object will not be in a selected state, it will be in a highlighted state).
Ideally you would also create a custom selection filter function that does not allow the selection of objects that have at one point been selected.
(as an aside: how do you get your code to format nicely? I can’t seem to get it right)
My apologies, I typed the python code without actually testing it and it contained a few errors. Below you find a revised version that I tested just now.
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
def getBoolAndObjects(prompt, b_opts,default):
ids = []
go = Rhino.Input.Custom.GetObject()
go.SetCommandPrompt(prompt)
boolOption = Rhino.Input.Custom.OptionToggle(default,b_opts[1],b_opts[2])
go.AddOptionToggle(b_opts[0], boolOption)
go.AcceptNothing(True)
while True:
gr = go.Get() #select one object
if gr == Rhino.Input.GetResult.Option: continue
if gr == Rhino.Input.GetResult.Cancel:
for gid in ids:
gid.Object().Highlight(False) #unhighlight before returning
return (None, boolOption.CurrentValue)
if gr == Rhino.Input.GetResult.Nothing: break
if gr == Rhino.Input.GetResult.Object:
id = go.Object(0) # get first object ref
ids.extend([id])
id.Object().Select(False) #unselect to prevent selecting it again
id.Object().Highlight(True) #highlight object to show it is selected
for gid in ids:
gid.Object().Highlight(False) #unhighlight before returning
return (ids, boolOption.CurrentValue)
if __name__ == '__main__':
(ids, opt) = getBoolAndObjects("prompt here", ("Choice", "No", "Yes"), False)
if ids is None:
Rhino.RhinoApp.WriteLine("canceled")
else:
Rhino.RhinoApp.WriteLine("{0} objects selected", len(ids))
Rhino.RhinoApp.WriteLine("bool option {0}", opt)
for gid in ids:
Rhino.RhinoApp.WriteLine("object id {0}", gid.Object().Id)