diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/content_tools/anim_tool.py | 9 | ||||
-rw-r--r-- | scripts/content_tools/skel_tool.py | 17 | ||||
-rw-r--r-- | scripts/perf/perfbot_run.py | 204 |
3 files changed, 229 insertions, 1 deletions
diff --git a/scripts/content_tools/anim_tool.py b/scripts/content_tools/anim_tool.py index e7b86a88fa..4a0773951e 100644 --- a/scripts/content_tools/anim_tool.py +++ b/scripts/content_tools/anim_tool.py @@ -611,6 +611,7 @@ def main(*argv): parser = argparse.ArgumentParser(description="process SL animations") parser.add_argument("--verbose", help="verbose flag", action="store_true") parser.add_argument("--dump", help="dump to stdout", action="store_true") + parser.add_argument("--use_aliases", help="use alias names for bones", action="store_true") parser.add_argument("--rot", help="specify sequence of rotations", type=float_triple, nargs="+") parser.add_argument("--rand_pos", help="request NUM random positions (default %(default)s)", metavar="NUM", type=int, default=2) @@ -637,6 +638,7 @@ def main(*argv): parser.add_argument("--no_hud", help="omit hud joints from list of attachments", action="store_true") parser.add_argument("--base_priority", help="set base priority", type=int) parser.add_argument("--joint_priority", help="set joint priority for all joints", type=int) + parser.add_argument("--force_joints", help="don't check validity of joint names", action="store_true") parser.add_argument("infilename", help="name of a .anim file to input") parser.add_argument("outfilename", nargs="?", help="name of a .anim file to output") args = parser.parse_args(argv) @@ -661,7 +663,12 @@ def main(*argv): if lad_tree is None: raise Error("failed to parse " + args.lad) if args.joints: - joints = resolve_joints(args.joints, skel_tree, lad_tree, args.no_hud) + if args.force_joints: + joints = args.joints + else: + joints = resolve_joints(args.joints, skel_tree, lad_tree, args.no_hud) + if args.use_aliases: + joints = map(lambda name: "avatar_" + name, joints) if args.verbose: print("joints resolved to",joints) for name in joints: diff --git a/scripts/content_tools/skel_tool.py b/scripts/content_tools/skel_tool.py index 449ecd6a6c..696e4e2923 100644 --- a/scripts/content_tools/skel_tool.py +++ b/scripts/content_tools/skel_tool.py @@ -72,6 +72,22 @@ def check_symmetry(name, field, vec1, vec2): if vec1[2] != vec2[2]: print(name,field,"z match fail") +def enforce_alias_rules(tree, element, fix=False): + if element.tag != "bone": + return + alias_lis = [] + aliases = element.get("aliases") + if aliases: + alias_lis = aliases.split(" ") + name = element.get("name") + if name: + std_alias = "avatar_" + name + if not std_alias in alias_lis: + print "missing expected alias",name,std_alias + for alias in alias_lis: + if alias.startswith("avatar_") and alias != std_alias: + print "invalid avatar_ alias",name,alias + def enforce_symmetry(tree, element, field, fix=False): name = element.get("name") if not name: @@ -209,6 +225,7 @@ def validate_skel_tree(tree, ogtree, reftree, fix=False): unfixable += 1 fix_name(element) + enforce_alias_rules(tree, element, fix) enforce_precision_rules(element) for field in ["pos","pivot"]: enforce_symmetry(tree, element, field, fix) diff --git a/scripts/perf/perfbot_run.py b/scripts/perf/perfbot_run.py new file mode 100644 index 0000000000..55ea2fae66 --- /dev/null +++ b/scripts/perf/perfbot_run.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python3 +"""\ +@file perfbot_run.py +@brief Run a number of non interactive Viewers (PerfBots) with + a variety of options and settings. Pass --help for details. + +$LicenseInfo:firstyear=2007&license=viewerlgpl$ +Second Life Viewer Source Code +Copyright (C) 2021, Linden Research, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; +version 2.1 of the License only. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +$/LicenseInfo$ +""" + +import argparse +import subprocess +import os +import math +import time + +# Required parameters that are always passed in +# Specify noninteractive mode (SL-15999 for details) +PARAM_NON_INTERACTIVE = "--noninteractive" +# Run multiple Viewers at once +PARAM_MULTI = "--multiple" +# Specify username (first and last) and password +PARAM_LOGIN = "--login" +# SLURL to teleport to after login +PARAM_SLURL = "--slurl" + + +def gen_niv_script(args): + print(f"Reading creds from {(args.creds)} folder") + print(f"Using the non interactive Viewer from {(args.viewer)}") + print(f"Sleeping for {args.sleep}ms between Viewer launches") + + # Read the lines from the creds file. Typically this will be + # stored in the build-secrets-git private repository but you + # can point to any location with the --creds parameter + creds_lines = [] + with open(args.creds) as file: + creds_lines = file.readlines() + creds_lines = [line.rstrip() for line in creds_lines] + creds_lines = [line for line in creds_lines if not line.startswith("#") and len(line)] + # We cannot log in more users than we have credentials for + if args.num==0: + args.num = len(creds_lines) + if args.num > len(creds_lines): + print( + f"The number of agents specified ({(args.num)}) exceeds " + f"the number of valid entries ({(len(creds_lines))}) in " + f"the creds file " + ) + return + + print(f"Launching {(args.num)} instances of the Viewer") + + # The Viewer (in dev environments at least) needs a well specified + # working directory to function properly. We try to guess what it + # might be based on the full path to the Viewer executable but + # you can also specify it explicitly with the --cwd parameter + # (required for dev builds) + args.viewer = os.path.abspath(args.viewer) + if len(args.cwd) == 0: + working_dir = os.path.dirname(os.path.abspath(args.viewer)) + else: + working_dir = os.path.abspath(args.cwd) + print(f"Working directory is {working_dir}, cwd {args.cwd}") + os.chdir(working_dir) + + if args.dryrun: + print("Running in dry-run mode - no Viewers will be started") + print("") + + for inst in range(args.num): + + # Format of each cred line is username_first username_last password + # A space is used to separate each and a # at the start of a line + # removes it from the pool (useful if someone else is using a subset + # of the available ones) + creds = creds_lines[inst].split(" ") + username_first = creds[0] + username_last = creds[1] + password = creds[2] + + # The default layout is an evenly spaced circle in the + # center of the region. We may extend this to allow other + # patterns like a square/rectangle or a spiral. (Hint: it + # likely won't be needed :)) + center_x = 128 + center_y = 128 + if args.layout == "circle": + radius = 6 + angle = (2 * math.pi / args.num) * inst + region_x = int(math.sin(angle) * radius + center_x) + region_y = int(math.cos(angle) * radius + center_y) + region_z = 0 + elif args.layout == "square": + region_x = center_x + region_y = center_y + elif args.layout == "spiral": + region_x = center_x + region_y = center_y + slurl = f"secondlife://{args.region}/{region_x}/{region_y}/{region_z}" + + # Build the script line + script_cmd = [args.viewer] + script_cmd.append(PARAM_NON_INTERACTIVE) + script_cmd.append(PARAM_MULTI) + script_cmd.append(PARAM_LOGIN) + script_cmd.append(username_first) + script_cmd.append(username_last) + script_cmd.append(password) + script_cmd.append(PARAM_SLURL) + script_cmd.append(slurl) + + # Display the script we will execute. + cmd = "" + for p in script_cmd: + cmd = cmd + " " + p + print(cmd) + + # If --dry-run is specified, we do everything (including, most + # usefully, display the script lines) but do not start the Viewer + if args.dryrun == False: + print("opening viewer session with",script_cmd) + viewer_session = subprocess.Popen(script_cmd) + + # Sleeping a bit between launches seems to help avoid a CPU + # surge when N Viewers are started simulatanously. The default + # value can be changed with the --sleep parameter + time.sleep(args.sleep / 1000) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(allow_abbrev=False) + parser.add_argument( + "--num", + type=int, + default=0, + dest="num", + help="How many avatars to add to the script", + ) + parser.add_argument( + "--creds", + default="../../../build-secrets-git/perf/perfbot_creds.txt", + dest="creds", + help="Location of the text file containing user credentials", + ) + parser.add_argument( + "--viewer", + default="C:/Program Files/SecondLife/SecondLifeViewer.exe", + dest="viewer", + help="Location of the non interactive Viewer build", + ) + parser.add_argument( + "--cwd", + default="", + dest="cwd", + help="Location of the current working directory to use", + ) + parser.add_argument( + "--region", + default="Lag Me 5", + dest="region", + help="The SLURL for the Second Life region to visit", + ) + parser.add_argument( + "--layout", + default="circle", + dest="layout", + choices={"circle", "square", "spiral"}, + help="The geometric layout of the avatar destination locations", + ) + parser.add_argument( + "--sleep", + type=int, + default=1000, + dest="sleep", + help="Time to sleep between launches in milliseconds", + ) + parser.add_argument( + "--dry-run", + action="store_true", + dest="dryrun", + help="Dryrun mode - display parameters and script lines but do not start any Viewers", + ) + args = parser.parse_args() + + gen_niv_script(args) |