As you mention Visual Studio Code, ADP's Fake_poser3a.py may be a useful assistant. His site/page appears to have been unavailable for some months, and the Wayback Machine hasn't saved his .ZIP files (though some of the code insets still display). But here is his Fake_poser3a.py (latest version) for use with Visual Studio Code etc. I've added an expanded header.
# Fake_poser3a.py Class and Method headers to support editors while writing Python scripts.
# Works in Visual Studio Code
#
# Updated: 04/17/2020
#
# Updated: 08/25/2022
# More types for P12 version added
#
# Updated: 07/23/2022
# Some bugfixes for P12. Ready to go lib for Poser 12 included as "POSER_FAKE_12.py".
# Source: https://web.archive.org/web/20200805051440/https://adp.spdns.org/
# All possible Poser keywords should be covered.
# Contains a ready to go lib for Poser 11. Insert file "POSER_FAKE.py" into a path
# where your editor can find it. In your script insert the line:
#
# import POSER_FAKE as poser
#
# Or, as a better solution:
# try:
# import poser
# except ImportError:
# import POSER_FAKE as poser
#
# For use with other Poser versions than 11, run the script once inside your own Poser and copy the resulting file "POSER_FAKE.py" where you need it.
from __future__ import print_function
import inspect
import os
import re
import sys
import traceback
from collections import namedtuple
try:
import poser
except ImportError:
poser = None
if sys.version_info.major > 2:
basestring = str
xrange = range
else:
range = xrange
PARMS = namedtuple("PARMS", "Name args doc")
classnames = set()
sc = poser.Scene()
DONT_CALL_FILE = None
DONT_CALL = set()
def debug(*args):
print(*args, file=sys.stderr)
#def dont_call(funcstr):
# if DONT_CALL_FILE:
# print(funcstr, file=DONT_CALL_FILE)
def analyze(obj2analyze):
container = dict(
classes=list(),
builtins=list(),
consts=list()
)
members = inspect.getmembers(obj2analyze)
if members:
for name, obj in members:
if name.startswith("_"):
continue
doc = obj.__doc__.replace(" ", "\n").split("\n") if obj.__doc__ else None
if name.startswith("k"):
#if isinstance(obj, basestring):
# obj = "'{}'".format(obj)
container["consts"].append(PARMS(name, obj, ""))
elif inspect.isclass(obj):
container["classes"].append(PARMS(name, None, doc))
classnames.add(name.strip().lower())
elif inspect.isbuiltin(obj):
container["builtins"].append(PARMS(name, None, doc))
else:
t = getattr(poser, obj2analyze.__class__.__name__ + "Type")
if t:
for name in dir(t):
if name.startswith("_"):
continue
obj = getattr(obj2analyze, name)
doc = obj.__doc__.replace(" ", "\n").split("\n") if obj.__doc__ else None
container["builtins"].append(PARMS(name, None, doc))
return container
def print_obj(container, tabs=0):
if not container:
debug(">>>>>>>>>EMPTY")
return
t = "\t" * tabs
for _entry in sorted(container["consts"]):
if _entry.doc:
print(t + "# ".join(_entry.doc))
frmt = "{}{} = '{}'" if isinstance(_entry.args, basestring) \
else "{}{} = {}"
print(frmt.format(t, _entry.Name, _entry.args))
if tabs == 0:
print("#", "-" * 70)
for _entry in sorted(container["classes"]):
print("\n{}class {}:".format(t, _entry.Name))
if _entry.doc:
doc = ("\n" + t + "\t").join(_entry.doc)
print('{}"""\n{}\n{}"""'.format(t, doc, t))
if _entry.args is not None:
print("{}\tdef __init__({}):".format(t, _entry.args))
print("{}\t\tpass".format(t))
try:
if _entry.Name == "SceneType":
print_obj(analyze(poser.Scene()), tabs + 1)
elif _entry.Name == "CredManagerType":
print_obj(analyze(CredManager), tabs + 1)
elif _entry.Name == "ClothSimulatorType" and cloth_simulator:
print_obj(analyze(cloth_simulator), tabs + 1)
elif _entry.Name == "ActorType" and Actor:
print_obj(analyze(Actor), tabs + 1)
elif _entry.Name == "ParmType" and Parameter:
print_obj(analyze(Parameter), tabs + 1)
elif _entry.Name == "GeomType" and Geometry:
print_obj(analyze(Geometry), tabs + 1)
elif _entry.Name == "PolygonType" and Geometry:
print_obj(analyze(Geometry.Polygons()[0]), tabs + 1)
elif _entry.Name == "TexPolygonType" and Geometry:
print_obj(analyze(Geometry.TexPolygons()[0]), tabs + 1)
elif _entry.Name == "VertType" and Geometry:
print_obj(analyze(Geometry.Vertices()[0]), tabs + 1)
elif _entry.Name == "TexVertType" and Geometry:
print_obj(analyze(Geometry.TexVertices()[0]), tabs + 1)
elif _entry.Name == "FigureType" and Figure:
print_obj(analyze(Figure), tabs + 1)
elif _entry.Name == "MaterialType" and Material:
print_obj(analyze(Material), tabs + 1)
elif _entry.Name == "ShaderTreeType" and Shadertree:
print_obj(analyze(Shadertree), tabs + 1)
elif _entry.Name == "ShaderNodeType" and Node:
print_obj(analyze(Node), tabs + 1)
elif _entry.Name == "ShaderNodeInputType" and Node:
print_obj(analyze(Node.Inputs()[0]), tabs + 1)
elif _entry.Name == "ImExporterType" and Imexporter:
print_obj(analyze(Imexporter), tabs + 1)
elif _entry.Name == "MovieMakerType" and Moviemaker:
print_obj(analyze(Moviemaker), tabs + 1)
elif _entry.Name == "MotionNodeType" and Motionrig:
print_obj(analyze(Motionrig), tabs + 1)
elif _entry.Name == "SuperFlyOptionsType" and Superfly:
print_obj(analyze(Superfly), tabs + 1)
elif _entry.Name == "FireFlyOptionsType" and Firefly:
print_obj(analyze(Firefly), tabs + 1)
elif _entry.Name == "Dialog":
dlg = poser.Dialog()
print_obj(analyze(dlg), tabs + 1)
del dlg
elif _entry.Name == "DialogDirChooser":
dlg = poser.DialogDirChooser()
print_obj(analyze(dlg), tabs + 1)
del dlg
elif _entry.Name == "DialogFileChooser":
dlg = poser.DialogFileChooser(2)
print_obj(analyze(dlg), tabs + 1)
del dlg
elif _entry.Name == "DialogTextEntry":
dlg = poser.DialogTextEntry()
print_obj(analyze(dlg), tabs + 1)
del dlg
else:
print("{}\tpass".format(t))
except poser.error as err:
debug(err)
print("{}\tpass".format(t))
print()
for _entry in sorted(container["builtins"]):
args = _entry.args or "*args"
if tabs > 0:
args = "self, {}".format(_entry.args or "*args")
print("\n{}def {}({}):".format(t, _entry.Name, args))
if _entry.doc:
doc = ("\n" + t + "\t").join(_entry.doc)
print('{}\t"""\n{}\t{}\n{}\t"""'.format(t, t, doc, t))
is_list = False
return_str = None
last_line = _entry.doc[-1].strip()
res = re.match(r"[\(\[]\s*[\(\[].*?[\)\]]\s*[\]\)]", last_line)
if res:
# return type is tuple or list of tuples
res_str = res.string[res.regs[0][0] + 1:res.regs[0][1] - 1].strip()
res_str = [s for s in re.split(r"([\(\[][^\)]*[\)\[]),", res_str) if s.strip()]
for idx, _subentry in enumerate(res_str):
for _r in re.findall(r"<((\w+)\s*type)>", _subentry, flags=re.IGNORECASE):
if _r[1].lower() in "int float list tuple":
_subentry = re.sub("<"+_r[0]+">", _r[1].lower()+"(0)", _subentry, flags=re.IGNORECASE)
else:
_subentry = re.sub("<"+_r[0]+">", _r[0]+"()", _subentry, flags=re.IGNORECASE)
res_str[idx] = _subentry.strip()
return_str = "list({})" if last_line.startswith("[") else "tuple({})"
return_str = return_str.format(", ".join(res_str))
if return_str is None:
res = re.match(r"\(?<([^>]+)>", last_line)
if res:
return_type = res.groups(1)[0].strip()
is_list = False
if return_type.endswith("List") or return_type.endswith("list"):
return_type = return_type.split()[0]
is_list = True
if return_type.lower() in classnames:
return_str = return_type + "()"
elif return_str == "NoneType":
return_str = ""
elif return_type == "IntType":
return_str = "int(1)"
elif return_type == "FloatType":
return_str = "float(1.0)"
elif return_type == "StringType":
return_str = "str('{}()')".format(_entry.Name)
elif return_type == "DictType":
return_str = 'dict()'
elif return_type == "HairType":
return_str = "HairType()"
if not return_str.strip():
DONT_CALL.add(_entry.Name)
if return_str is None:
if "FloatType 4x4 Tuple" in last_line:
return_str = "(float(0), float(0), float(0), float(0))"
if _entry.Name == "WxAuiManager":
return_str = "wx.AuiManager()"
elif _entry.Name == "WxApp":
return_str = "poser.WxApp()"
if is_list:
return_str = "list({})".format(return_str)
if return_str is not None:
print("{}\treturn {}".format(t, return_str))
else:
print("{}\treturn".format(t))
else:
print("{}\tpass".format(t))
DONT_CALL.add(_entry.Name)
# temp_dir = poser.TempLocation()
temp_dir = os.path.dirname(sys.argv[0])
fname = os.path.join(temp_dir, "POSER_FAKE.py")
_stdout = sys.stdout
errmsg = None
Actor = poser.Scene().CurrentActor()
Figure = poser.Scene().CurrentFigure()
if Figure and Actor:
Geometry = Actor.Geometry()
Parameter = Actor.Parameters()[0]
Material = Actor.Materials()[0]
if Material:
Shadertree = Material.ShaderTree()
if Shadertree:
Node = Shadertree.Nodes()[0]
if sc.NumClothSimulators() == 0:
cloth_simulator = sc.CreateClothSimulator()
else:
cloth_simulator = sc.ClothSimulator(0)
Imexporter = sc.ImExporter()
Moviemaker = sc.MovieMaker()
CredManager = poser.CredManager()
Motionrig = poser.NewMotionRig()
Superfly = sc.CurrentSuperFlyOptions()
Firefly = sc.CurrentFireFlyOptions()
try:
Hair = Actor.HairGroup(0)
except:
Hair = None
try:
with open(fname, "w") as fh:
sys.stdout = fh
print_obj(analyze(poser))
if Hair:
print("\nclass HairType:")
print_obj(analyze(Hair), 1)
except Exception:
exc_type, exc_value, exc_traceback = sys.exc_info()
print(traceback.format_exception(exc_type, exc_value, exc_traceback), file=_stdout)
finally:
sys.stdout = _stdout
with open(os.path.join(temp_dir, "DONT_CALL.txt"), "w") as fh:
for entry in DONT_CALL:
print(entry, file=fh)
print(errmsg or "Written to: {}".format(fname))
else:
print("Can not work with an empty scene.")