Browse Source

Merge branch 'master' into webgl-port

rdb 2 years ago
parent
commit
fcf3de60c2
100 changed files with 1821 additions and 1136 deletions
  1. 6 0
      .clang-tidy
  2. 8 8
      .github/workflows/ci.yml
  3. 39 0
      .github/workflows/lint.yml
  4. 77 0
      .github/workflows/review.yml
  5. 513 313
      .pylintrc
  6. 1 0
      BACKERS.md
  7. 3 3
      README.md
  8. 3 2
      contrib/src/ai/aiWorld.cxx
  9. 23 1
      direct/src/actor/Actor.py
  10. 26 26
      direct/src/cluster/ClusterClient.py
  11. 13 13
      direct/src/cluster/ClusterConfig.py
  12. 1 1
      direct/src/cluster/ClusterMsgs.py
  13. 35 19
      direct/src/cluster/ClusterServer.py
  14. 1 1
      direct/src/controls/BattleWalker.py
  15. 2 5
      direct/src/controls/ControlManager.py
  16. 1 1
      direct/src/controls/DevWalker.py
  17. 18 3
      direct/src/controls/GravityWalker.py
  18. 14 3
      direct/src/controls/InputState.py
  19. 14 1
      direct/src/controls/NonPhysicsWalker.py
  20. 7 1
      direct/src/controls/ObserverWalker.py
  21. 30 6
      direct/src/controls/PhysicsWalker.py
  22. 5 2
      direct/src/controls/TwoDWalker.py
  23. 1 1
      direct/src/dcparser/dcClassParameter.h
  24. 1 2
      direct/src/directbase/TestStart.py
  25. 1 2
      direct/src/directbase/ThreeUpStart.py
  26. 15 8
      direct/src/directdevices/DirectDeviceManager.py
  27. 2 1
      direct/src/directdevices/DirectFastrak.py
  28. 29 29
      direct/src/directdevices/DirectJoybox.py
  29. 1 2
      direct/src/directdevices/DirectRadamec.py
  30. 2 2
      direct/src/directnotify/DirectNotify.py
  31. 13 13
      direct/src/directnotify/Notifier.py
  32. 9 1
      direct/src/directscripts/eggcacher.py
  33. 8 3
      direct/src/directscripts/extract_docs.py
  34. 32 31
      direct/src/directtools/DirectCameraControl.py
  35. 28 5
      direct/src/directtools/DirectGeometry.py
  36. 4 4
      direct/src/directtools/DirectGlobals.py
  37. 4 4
      direct/src/directtools/DirectGrid.py
  38. 11 1
      direct/src/directtools/DirectLights.py
  39. 73 49
      direct/src/directtools/DirectManipulation.py
  40. 49 27
      direct/src/directtools/DirectSelection.py
  41. 53 36
      direct/src/directtools/DirectSession.py
  42. 0 2
      direct/src/directtools/DirectUtil.py
  43. 3 1
      direct/src/directutil/LargeBlobSenderConsts.py
  44. 22 11
      direct/src/directutil/Mopath.py
  45. 2 0
      direct/src/directutil/Verify.py
  46. 64 70
      direct/src/dist/FreezeTool.py
  47. 4 3
      direct/src/dist/_android.py
  48. 5 4
      direct/src/dist/commands.py
  49. 1 4
      direct/src/dist/icon.py
  50. 2 2
      direct/src/dist/installers.py
  51. 5 3
      direct/src/dist/pefile.py
  52. 3 2
      direct/src/distributed/AsyncRequest.py
  53. 13 1
      direct/src/distributed/ClientRepository.py
  54. 16 16
      direct/src/distributed/ClientRepositoryBase.py
  55. 8 6
      direct/src/distributed/ConnectionRepository.py
  56. 3 4
      direct/src/distributed/DistributedCamera.py
  57. 0 2
      direct/src/distributed/DistributedCameraOV.py
  58. 4 5
      direct/src/distributed/DistributedCartesianGrid.py
  59. 0 3
      direct/src/distributed/DistributedCartesianGridAI.py
  60. 3 5
      direct/src/distributed/DistributedObject.py
  61. 0 2
      direct/src/distributed/DistributedObjectAI.py
  62. 0 2
      direct/src/distributed/DistributedObjectUD.py
  63. 33 6
      direct/src/distributed/DistributedSmoothNode.py
  64. 5 2
      direct/src/distributed/DistributedSmoothNodeBase.py
  65. 13 6
      direct/src/distributed/DoInterestManager.py
  66. 1 1
      direct/src/distributed/GridChild.py
  67. 1 3
      direct/src/distributed/GridParent.py
  68. 2 2
      direct/src/distributed/MsgTypes.py
  69. 1 1
      direct/src/distributed/MsgTypesCMU.py
  70. 3 3
      direct/src/distributed/NetMessenger.py
  71. 23 3
      direct/src/distributed/PyDatagram.py
  72. 23 3
      direct/src/distributed/PyDatagramIterator.py
  73. 2 2
      direct/src/distributed/SampleObject.py
  74. 33 3
      direct/src/distributed/ServerRepository.py
  75. 2 2
      direct/src/distributed/TimeManager.py
  76. 2 2
      direct/src/distributed/TimeManagerAI.py
  77. 58 58
      direct/src/extensions_native/CInterval_extensions.py
  78. 21 21
      direct/src/extensions_native/HTTPChannel_extensions.py
  79. 147 146
      direct/src/extensions_native/NodePath_extensions.py
  80. 1 1
      direct/src/filter/CommonFilters.py
  81. 3 3
      direct/src/filter/FilterManager.py
  82. 4 8
      direct/src/fsm/ClassicFSM.py
  83. 2 3
      direct/src/fsm/FSM.py
  84. 1 1
      direct/src/fsm/FourState.py
  85. 4 1
      direct/src/fsm/FourStateAI.py
  86. 1 1
      direct/src/fsm/SampleFSM.py
  87. 12 12
      direct/src/fsm/StatePush.py
  88. 5 3
      direct/src/gui/DirectButton.py
  89. 4 4
      direct/src/gui/DirectCheckBox.py
  90. 6 5
      direct/src/gui/DirectCheckButton.py
  91. 15 10
      direct/src/gui/DirectDialog.py
  92. 10 8
      direct/src/gui/DirectEntry.py
  93. 4 7
      direct/src/gui/DirectEntryScroll.py
  94. 2 2
      direct/src/gui/DirectFrame.py
  95. 15 7
      direct/src/gui/DirectGuiBase.py
  96. 9 3
      direct/src/gui/DirectGuiGlobals.py
  97. 3 2
      direct/src/gui/DirectGuiTest.py
  98. 5 3
      direct/src/gui/DirectLabel.py
  99. 5 5
      direct/src/gui/DirectOptionMenu.py
  100. 6 5
      direct/src/gui/DirectRadioButton.py

+ 6 - 0
.clang-tidy

@@ -0,0 +1,6 @@
+---
+Checks: 'clang-diagnostic-*,clang-analyzer-*,performance-*,portability-*,modernize-use-nullptr'
+WarningsAsErrors: ''
+HeaderFilterRegex: ''
+FormatStyle: none
+...

+ 8 - 8
.github/workflows/ci.yml

@@ -92,10 +92,10 @@ jobs:
     - name: Install dependencies (macOS)
     - name: Install dependencies (macOS)
       if: runner.os == 'macOS'
       if: runner.os == 'macOS'
       run: |
       run: |
-        curl -O https://www.panda3d.org/download/panda3d-1.10.13/panda3d-1.10.13-tools-mac.tar.gz
-        tar -xf panda3d-1.10.13-tools-mac.tar.gz
-        mv panda3d-1.10.13/thirdparty thirdparty
-        rmdir panda3d-1.10.13
+        curl -O https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-mac.tar.gz
+        tar -xf panda3d-1.10.14-tools-mac.tar.gz
+        mv panda3d-1.10.14/thirdparty thirdparty
+        rmdir panda3d-1.10.14
 
 
         # Temporary hack so that pzip can run, since we are about to remove Cg anyway.
         # Temporary hack so that pzip can run, since we are about to remove Cg anyway.
         install_name_tool -id "$(pwd)/thirdparty/darwin-libs-a/nvidiacg/lib/libCg.dylib" thirdparty/darwin-libs-a/nvidiacg/lib/libCg.dylib
         install_name_tool -id "$(pwd)/thirdparty/darwin-libs-a/nvidiacg/lib/libCg.dylib" thirdparty/darwin-libs-a/nvidiacg/lib/libCg.dylib
@@ -381,10 +381,10 @@ jobs:
     - name: Get thirdparty packages (macOS)
     - name: Get thirdparty packages (macOS)
       if: runner.os == 'macOS'
       if: runner.os == 'macOS'
       run: |
       run: |
-        curl -O https://www.panda3d.org/download/panda3d-1.10.13/panda3d-1.10.13-tools-mac.tar.gz
-        tar -xf panda3d-1.10.13-tools-mac.tar.gz
-        mv panda3d-1.10.13/thirdparty thirdparty
-        rmdir panda3d-1.10.13
+        curl -O https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-mac.tar.gz
+        tar -xf panda3d-1.10.14-tools-mac.tar.gz
+        mv panda3d-1.10.14/thirdparty thirdparty
+        rmdir panda3d-1.10.14
         (cd thirdparty/darwin-libs-a && rm -rf rocket)
         (cd thirdparty/darwin-libs-a && rm -rf rocket)
 
 
     - name: Set up Python 3.11
     - name: Set up Python 3.11

+ 39 - 0
.github/workflows/lint.yml

@@ -0,0 +1,39 @@
+name: Lint
+on: [pull_request]
+
+jobs:
+  clang-tidy:
+    runs-on: ubuntu-20.04
+    steps:
+    - uses: actions/checkout@v3
+      with:
+        fetch-depth: 2
+    - name: Install clang-tidy
+      run: |
+        sudo apt-get update
+        sudo apt-get install -y clang-tidy build-essential pkg-config libpng-dev libjpeg-dev libtiff-dev zlib1g-dev libssl-dev libx11-dev libgl1-mesa-dev libxrandr-dev libxxf86dga-dev libxcursor-dev libfreetype6-dev libvorbis-dev libeigen3-dev libopenal-dev libode-dev libbullet-dev libgtk-3-dev libassimp-dev libopenexr-dev
+    - name: Prepare compile_commands.json
+      run: |
+        cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_UNITY_BUILD=OFF -DHAVE_PYTHON=OFF -DINTERROGATE_PYTHON_INTERFACE=OFF
+    - name: Copy prebuilt files
+      run: |
+        for fn in **/*.prebuilt; do
+          echo mkdir -p $(dirname "cmake/$fn");
+          echo cp "$fn" "cmake/${fn%.*}";
+        done
+    - name: Create results directory
+      run: |
+        mkdir clang-tidy-result
+    - name: Analyze
+      run: |
+        git diff -U0 HEAD^ | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml
+    - name: Save PR metadata
+      run: |
+        echo ${{ github.event.number }} > clang-tidy-result/pr-id.txt
+        echo ${{ github.event.pull_request.head.repo.full_name }} > clang-tidy-result/pr-head-repo.txt
+        echo ${{ github.event.pull_request.head.ref }} > clang-tidy-result/pr-head-ref.txt
+    - name: Upload results
+      uses: actions/upload-artifact@v2
+      with:
+        name: clang-tidy-result
+        path: clang-tidy-result/

+ 77 - 0
.github/workflows/review.yml

@@ -0,0 +1,77 @@
+name: Post PR Review
+
+on:
+  workflow_run:
+    workflows: ["Lint"]
+    types: [completed]
+
+jobs:
+  clang-tidy-results:
+    # Trigger the job only if the previous (insecure) workflow completed successfully
+    if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' }}
+    runs-on: ubuntu-20.04
+    steps:
+    - name: Download analysis results
+      uses: actions/[email protected]
+      with:
+        script: |
+          let artifacts = await github.actions.listWorkflowRunArtifacts({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              run_id: ${{ github.event.workflow_run.id }},
+          });
+          let matchArtifact = artifacts.data.artifacts.filter((artifact) => {
+              return artifact.name == "clang-tidy-result"
+          })[0];
+          let download = await github.actions.downloadArtifact({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              artifact_id: matchArtifact.id,
+              archive_format: "zip",
+          });
+          let fs = require("fs");
+          fs.writeFileSync("${{github.workspace}}/clang-tidy-result.zip", Buffer.from(download.data));
+    - name: Set environment variables
+      run: |
+        mkdir clang-tidy-result
+        unzip clang-tidy-result.zip -d clang-tidy-result
+        echo "pr_id=$(cat clang-tidy-result/pr-id.txt)" >> $GITHUB_ENV
+        echo "pr_head_repo=$(cat clang-tidy-result/pr-head-repo.txt)" >> $GITHUB_ENV
+        echo "pr_head_ref=$(cat clang-tidy-result/pr-head-ref.txt)" >> $GITHUB_ENV
+    - uses: actions/checkout@v2
+      with:
+        repository: ${{ env.pr_head_repo }}
+        ref: ${{ env.pr_head_ref }}
+        persist-credentials: false
+    - name: Redownload analysis results
+      uses: actions/[email protected]
+      with:
+        script: |
+          let artifacts = await github.actions.listWorkflowRunArtifacts({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              run_id: ${{github.event.workflow_run.id}},
+          });
+          let matchArtifact = artifacts.data.artifacts.filter((artifact) => {
+              return artifact.name == "clang-tidy-result"
+          })[0];
+          let download = await github.actions.downloadArtifact({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              artifact_id: matchArtifact.id,
+              archive_format: "zip",
+          });
+          let fs = require("fs");
+          fs.writeFileSync("${{github.workspace}}/clang-tidy-result.zip", Buffer.from(download.data));
+    - name: Extract analysis results
+      run: |
+        mkdir clang-tidy-result
+        unzip clang-tidy-result.zip -d clang-tidy-result
+    - name: Run clang-tidy-pr-comments action
+      uses: platisd/clang-tidy-pr-comments@master
+      with:
+        github_token: ${{ github.token }}
+        clang_tidy_fixes: clang-tidy-result/fixes.yml
+        pull_request_id: ${{ env.pr_id }}
+        request_changes: true
+        suggestions_per_comment: 10

+ 513 - 313
.pylintrc

@@ -1,27 +1,73 @@
-[MASTER]
+[MAIN]
+
+# Analyse import fallback blocks. This can be used to support both Python 2 and
+# 3 compatible code, which means that the block might have code that exists
+# only in one or another interpreter, leading to false positives when analysed.
+analyse-fallback-blocks=no
+
+# Load and enable all available extensions. Use --list-extensions to see a list
+# all available extensions.
+#enable-all-extensions=
+
+# In error mode, messages with a category besides ERROR or FATAL are
+# suppressed, and no reports are done by default. Error mode is compatible with
+# disabling specific errors.
+#errors-only=
+
+# Always return a 0 (non-error) status code, even if lint errors are found.
+# This is primarily useful in continuous integration scripts.
+#exit-zero=
 
 
 # A comma-separated list of package or module names from where C extensions may
 # A comma-separated list of package or module names from where C extensions may
 # be loaded. Extensions are loading into the active Python interpreter and may
 # be loaded. Extensions are loading into the active Python interpreter and may
 # run arbitrary code.
 # run arbitrary code.
-extension-pkg-whitelist=panda3d
+extension-pkg-allow-list=panda3d,wx
 
 
-# Specify a score threshold to be exceeded before program exits with error.
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
+# for backward compatibility.)
+extension-pkg-whitelist=panda3d,wx
+
+# Return non-zero exit code if any of these messages/categories are detected,
+# even if score is above --fail-under value. Syntax same as enable. Messages
+# specified are enabled, while categories only check already-enabled messages.
+fail-on=
+
+# Specify a score threshold under which the program will exit with error.
 fail-under=10.0
 fail-under=10.0
 
 
-# Add files or directories to the blacklist. They should be base names, not
-# paths.
+# Interpret the stdin as a python script, whose filename needs to be passed as
+# the module_or_package argument.
+#from-stdin=
+
+# Files or directories to be skipped. They should be base names, not paths.
 ignore=thirdparty
 ignore=thirdparty
 
 
-# Add files or directories matching the regex patterns to the blacklist. The
-# regex matches against base names, not paths.
+# Add files or directories matching the regular expressions patterns to the
+# ignore-list. The regex matches against paths and can be in Posix or Windows
+# format. Because '\\' represents the directory delimiter on Windows systems,
+# it can't be used as an escape character.
+ignore-paths=
+
+# Files or directories matching the regular expression patterns are skipped.
+# The regex matches against base names, not paths. The default value ignores
+# Emacs file locks
 ignore-patterns=
 ignore-patterns=
 
 
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis). It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=
+
 # Python code to execute, usually for sys.path manipulation such as
 # Python code to execute, usually for sys.path manipulation such as
 # pygtk.require().
 # pygtk.require().
 #init-hook=
 #init-hook=
 
 
 # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
 # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
-# number of processors available to use.
+# number of processors available to use, and will cap the count on Windows to
+# avoid hangs.
 jobs=1
 jobs=1
 
 
 # Control the amount of potential inferred values when inferring a single
 # Control the amount of potential inferred values when inferring a single
@@ -36,259 +82,23 @@ load-plugins=
 # Pickle collected data for later comparisons.
 # Pickle collected data for later comparisons.
 persistent=yes
 persistent=yes
 
 
+# Minimum Python version to use for version dependent checks. Will default to
+# the version used to run pylint.
+py-version=3.6
+
+# Discover python modules and packages in the file system subtree.
+recursive=no
+
 # When enabled, pylint would attempt to guess common misconfiguration and emit
 # When enabled, pylint would attempt to guess common misconfiguration and emit
 # user-friendly hints instead of false-positive error messages.
 # user-friendly hints instead of false-positive error messages.
 suggestion-mode=yes
 suggestion-mode=yes
 
 
 # Allow loading of arbitrary C extensions. Extensions are imported into the
 # Allow loading of arbitrary C extensions. Extensions are imported into the
 # active Python interpreter and may run arbitrary code.
 # active Python interpreter and may run arbitrary code.
-unsafe-load-any-extension=no
-
-
-[MESSAGES CONTROL]
-
-# Only show warnings with the listed confidence levels. Leave empty to show
-# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
-confidence=
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifiers separated by comma (,) or put this
-# option multiple times (only on the command line, not in the configuration
-# file where it should appear only once). You can also use "--disable=all" to
-# disable everything first and then reenable specific checks. For example, if
-# you want to run only the similarities checker, you can use "--disable=all
-# --enable=similarities". If you want to run only the classes checker, but have
-# no Warning level messages displayed, use "--disable=all --enable=classes
-# --disable=W".
-disable=attribute-defined-outside-init,
-        broad-except,
-        comparison-with-callable,
-        dangerous-default-value,
-        global-statement,
-        import-outside-toplevel,
-        invalid-name,
-        line-too-long,
-        misplaced-comparison-constant,
-        missing-class-docstring,
-        missing-function-docstring,
-        missing-module-docstring,
-        protected-access,
-        r,
-        raise-missing-from,
-        redefined-builtin,
-        redefined-outer-name,
-        too-many-lines,
-        unused-argument,
-        unused-variable,
-        unused-wildcard-import,
-        using-constant-test,
-        wildcard-import,
-        wrong-import-order,
-        wrong-import-position
-
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time (only on the command line, not in the configuration file where
-# it should appear only once). See also the "--disable" option for examples.
-enable=c-extension-no-member
-
-
-[REPORTS]
-
-# Python expression which should return a score less than or equal to 10. You
-# have access to the variables 'error', 'warning', 'refactor', and 'convention'
-# which contain the number of messages in each category, as well as 'statement'
-# which is the total number of statements analyzed. This score is used by the
-# global evaluation report (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Template used to display messages. This is a python new-style format string
-# used to format the message information. See doc for all details.
-#msg-template=
-
-# Set the output format. Available formats are text, parseable, colorized, json
-# and msvs (visual studio). You can also give a reporter class, e.g.
-# mypackage.mymodule.MyReporterClass.
-output-format=text
-
-# Tells whether to display a full report or only the messages.
-reports=no
-
-# Activate the evaluation score.
-score=yes
-
-
-[REFACTORING]
-
-# Maximum number of nested blocks for function / method body
-max-nested-blocks=5
-
-# Complete name of functions that never returns. When checking for
-# inconsistent-return-statements if a never returning function is called then
-# it will be considered as an explicit return statement and no message will be
-# printed.
-never-returning-functions=sys.exit
-
-
-[FORMAT]
-
-# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
-expected-line-ending-format=LF
-
-# Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=^\s*(# )?<?https?://\S+>?$
-
-# Number of spaces of indent required inside a hanging or continued line.
-indent-after-paren=4
-
-# String used as indentation unit. This is usually "    " (4 spaces) or "\t" (1
-# tab).
-indent-string='    '
-
-# Maximum number of characters on a single line.
-max-line-length=100
-
-# Maximum number of lines in a module.
-max-module-lines=1000
-
-# Allow the body of a class to be on the same line as the declaration if body
-# contains single statement.
-single-line-class-stmt=no
-
-# Allow the body of an if to be on the same line as the test if there is no
-# else.
-single-line-if-stmt=no
-
-
-[SPELLING]
-
-# Limits count of emitted suggestions for spelling mistakes.
-max-spelling-suggestions=4
-
-# Spelling dictionary name. Available dictionaries: none. To make it work,
-# install the python-enchant package.
-spelling-dict=
-
-# List of comma separated words that should not be checked.
-spelling-ignore-words=
-
-# A path to a file that contains the private dictionary; one word per line.
-spelling-private-dict-file=
-
-# Tells whether to store unknown words to the private dictionary (see the
-# --spelling-private-dict-file option) instead of raising a message.
-spelling-store-unknown-words=no
-
-
-[TYPECHECK]
-
-# List of decorators that produce context managers, such as
-# contextlib.contextmanager. Add to this list to register other decorators that
-# produce valid context managers.
-contextmanager-decorators=contextlib.contextmanager
-
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E1101 when accessed. Python regular
-# expressions are accepted.
-generated-members=
-
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# Tells whether to warn about missing members when the owner of the attribute
-# is inferred to be None.
-ignore-none=yes
-
-# This flag controls whether pylint should warn about no-member and similar
-# checks whenever an opaque object is returned when inferring. The inference
-# can return multiple potential results while evaluating a Python object, but
-# some branches might not be evaluated, which results in partial inference. In
-# that case, it might be useful to still emit no-member and other checks for
-# the rest of the inferred objects.
-ignore-on-opaque-inference=yes
-
-# List of class names for which member attributes should not be checked (useful
-# for classes with dynamically set attributes). This supports the use of
-# qualified names.
-ignored-classes=optparse.Values,thread._local,_thread._local,direct.showbase.PythonUtil.ScratchPad
-
-# List of module names for which member attributes should not be checked
-# (useful for modules/projects where namespaces are manipulated during runtime
-# and thus existing member attributes cannot be deduced by static analysis). It
-# supports qualified module names, as well as Unix pattern matching.
-ignored-modules=
-
-# Show a hint with possible names when a member name was not found. The aspect
-# of finding the hint is based on edit distance.
-missing-member-hint=yes
-
-# The minimum edit distance a name should have in order to be considered a
-# similar match for a missing member name.
-missing-member-hint-distance=1
-
-# The total number of similar names that should be taken in consideration when
-# showing a hint for a missing member.
-missing-member-max-choices=1
-
-# List of decorators that change the signature of a decorated function.
-signature-mutators=
-
+#unsafe-load-any-extension=no
 
 
-[SIMILARITIES]
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-# Ignore imports when computing similarities.
-ignore-imports=no
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
-
-
-[VARIABLES]
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid defining new builtins when possible.
-additional-builtins=base,simbase,__dev__,onScreenDebug,globalClock,render,hidden,cluster
-
-# Tells whether unused global variables should be treated as a violation.
-allow-global-unused-variables=yes
-
-# List of strings which can identify a callback function by name. A callback
-# name must start or end with one of those strings.
-callbacks=cb_,
-          _cb
-
-# A regular expression matching the name of dummy variables (i.e. expected to
-# not be used).
-dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
-
-# Argument names that match this expression will be ignored. Default to name
-# with leading underscore.
-ignored-argument-names=_.*|^ignored_|^unused_
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# List of qualified module names which can have objects that can redefine
-# builtins.
-redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
-
-
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,
-      XXX,
-      TODO
-
-# Regular expression of note tags to take in consideration.
-#notes-rgx=
+# In verbose mode, extra non-checker-related info will be displayed.
+#verbose=
 
 
 
 
 [BASIC]
 [BASIC]
@@ -297,13 +107,15 @@ notes=FIXME,
 argument-naming-style=snake_case
 argument-naming-style=snake_case
 
 
 # Regular expression matching correct argument names. Overrides argument-
 # Regular expression matching correct argument names. Overrides argument-
-# naming-style.
+# naming-style. If left empty, argument names will be checked with the set
+# naming style.
 #argument-rgx=
 #argument-rgx=
 
 
 # Naming style matching correct attribute names.
 # Naming style matching correct attribute names.
 attr-naming-style=snake_case
 attr-naming-style=snake_case
 
 
 # Regular expression matching correct attribute names. Overrides attr-naming-
 # Regular expression matching correct attribute names. Overrides attr-naming-
+# style. If left empty, attribute names will be checked with the set naming
 # style.
 # style.
 #attr-rgx=
 #attr-rgx=
 
 
@@ -323,20 +135,30 @@ bad-names-rgxs=
 class-attribute-naming-style=any
 class-attribute-naming-style=any
 
 
 # Regular expression matching correct class attribute names. Overrides class-
 # Regular expression matching correct class attribute names. Overrides class-
-# attribute-naming-style.
+# attribute-naming-style. If left empty, class attribute names will be checked
+# with the set naming style.
 #class-attribute-rgx=
 #class-attribute-rgx=
 
 
+# Naming style matching correct class constant names.
+class-const-naming-style=UPPER_CASE
+
+# Regular expression matching correct class constant names. Overrides class-
+# const-naming-style. If left empty, class constant names will be checked with
+# the set naming style.
+#class-const-rgx=
+
 # Naming style matching correct class names.
 # Naming style matching correct class names.
 class-naming-style=PascalCase
 class-naming-style=PascalCase
 
 
 # Regular expression matching correct class names. Overrides class-naming-
 # Regular expression matching correct class names. Overrides class-naming-
-# style.
+# style. If left empty, class names will be checked with the set naming style.
 #class-rgx=
 #class-rgx=
 
 
 # Naming style matching correct constant names.
 # Naming style matching correct constant names.
 const-naming-style=UPPER_CASE
 const-naming-style=UPPER_CASE
 
 
 # Regular expression matching correct constant names. Overrides const-naming-
 # Regular expression matching correct constant names. Overrides const-naming-
+# style. If left empty, constant names will be checked with the set naming
 # style.
 # style.
 #const-rgx=
 #const-rgx=
 
 
@@ -348,7 +170,8 @@ docstring-min-length=-1
 function-naming-style=snake_case
 function-naming-style=snake_case
 
 
 # Regular expression matching correct function names. Overrides function-
 # Regular expression matching correct function names. Overrides function-
-# naming-style.
+# naming-style. If left empty, function names will be checked with the set
+# naming style.
 #function-rgx=
 #function-rgx=
 
 
 # Good variable names which should always be accepted, separated by a comma.
 # Good variable names which should always be accepted, separated by a comma.
@@ -370,21 +193,22 @@ include-naming-hint=no
 inlinevar-naming-style=any
 inlinevar-naming-style=any
 
 
 # Regular expression matching correct inline iteration names. Overrides
 # Regular expression matching correct inline iteration names. Overrides
-# inlinevar-naming-style.
+# inlinevar-naming-style. If left empty, inline iteration names will be checked
+# with the set naming style.
 #inlinevar-rgx=
 #inlinevar-rgx=
 
 
 # Naming style matching correct method names.
 # Naming style matching correct method names.
 method-naming-style=snake_case
 method-naming-style=snake_case
 
 
 # Regular expression matching correct method names. Overrides method-naming-
 # Regular expression matching correct method names. Overrides method-naming-
-# style.
+# style. If left empty, method names will be checked with the set naming style.
 #method-rgx=
 #method-rgx=
 
 
 # Naming style matching correct module names.
 # Naming style matching correct module names.
 module-naming-style=snake_case
 module-naming-style=snake_case
 
 
 # Regular expression matching correct module names. Overrides module-naming-
 # Regular expression matching correct module names. Overrides module-naming-
-# style.
+# style. If left empty, module names will be checked with the set naming style.
 #module-rgx=
 #module-rgx=
 
 
 # Colon-delimited sets of names that determine each other's naming style when
 # Colon-delimited sets of names that determine each other's naming style when
@@ -400,38 +224,55 @@ no-docstring-rgx=^_
 # These decorators are taken in consideration only for invalid-name.
 # These decorators are taken in consideration only for invalid-name.
 property-classes=abc.abstractproperty
 property-classes=abc.abstractproperty
 
 
+# Regular expression matching correct type variable names. If left empty, type
+# variable names will be checked with the set naming style.
+#typevar-rgx=
+
 # Naming style matching correct variable names.
 # Naming style matching correct variable names.
 variable-naming-style=snake_case
 variable-naming-style=snake_case
 
 
 # Regular expression matching correct variable names. Overrides variable-
 # Regular expression matching correct variable names. Overrides variable-
-# naming-style.
+# naming-style. If left empty, variable names will be checked with the set
+# naming style.
 #variable-rgx=
 #variable-rgx=
 
 
 
 
-[LOGGING]
-
-# The type of string formatting that logging methods do. `old` means using %
-# formatting, `new` is for `{}` formatting.
-logging-format-style=old
-
-# Logging modules to check that the string format arguments are in logging
-# function parameter format.
-logging-modules=logging
-
+[CLASSES]
 
 
-[STRING]
+# Warn about protected attribute access inside special methods
+check-protected-access-in-special-methods=no
 
 
-# This flag controls whether inconsistent-quotes generates a warning when the
-# character used as a quote delimiter is used inconsistently within a module.
-check-quote-consistency=no
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,
+                      __new__,
+                      setUp,
+                      __post_init__
 
 
-# This flag controls whether the implicit-str-concat should generate a warning
-# on implicit string concatenation in sequences defined over several lines.
-check-str-concat-over-line-jumps=no
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,
+                  _fields,
+                  _replace,
+                  _source,
+                  _make
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=cls
 
 
 
 
 [DESIGN]
 [DESIGN]
 
 
+# List of regular expressions of class ancestor names to ignore when counting
+# public methods (see R0903)
+exclude-too-few-public-methods=
+
+# List of qualified class names to ignore when counting class parents (see
+# R0901)
+ignored-parents=
+
 # Maximum number of arguments for function / method.
 # Maximum number of arguments for function / method.
 max-args=5
 max-args=5
 
 
@@ -463,6 +304,42 @@ max-statements=50
 min-public-methods=2
 min-public-methods=2
 
 
 
 
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when caught.
+overgeneral-exceptions=builtins.BaseException,builtins.Exception
+
+
+[FORMAT]
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=LF
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+# String used as indentation unit. This is usually "    " (4 spaces) or "\t" (1
+# tab).
+indent-string='    '
+
+# Maximum number of characters on a single line.
+max-line-length=100
+
+# Maximum number of lines in a module.
+max-module-lines=1000
+
+# Allow the body of a class to be on the same line as the declaration if body
+# contains single statement.
+single-line-class-stmt=no
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+
 [IMPORTS]
 [IMPORTS]
 
 
 # List of modules that can be imported at any level, not just the top level
 # List of modules that can be imported at any level, not just the top level
@@ -472,24 +349,20 @@ allow-any-import-level=
 # Allow wildcard imports from modules that define __all__.
 # Allow wildcard imports from modules that define __all__.
 allow-wildcard-with-all=no
 allow-wildcard-with-all=no
 
 
-# Analyse import fallback blocks. This can be used to support both Python 2 and
-# 3 compatible code, which means that the block might have code that exists
-# only in one or another interpreter, leading to false positives when analysed.
-analyse-fallback-blocks=no
-
 # Deprecated modules which should not be used, separated by a comma.
 # Deprecated modules which should not be used, separated by a comma.
-deprecated-modules=optparse,tkinter.tix
+deprecated-modules=optparse,tkinter.tix,pandac.PandaModules,direct.directbase.DirectStart
 
 
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled).
+# Output a graph (.gv or any supported image format) of external dependencies
+# to the given file (report RP0402 must not be disabled).
 ext-import-graph=
 ext-import-graph=
 
 
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled).
+# Output a graph (.gv or any supported image format) of all (i.e. internal and
+# external) dependencies to the given file (report RP0402 must not be
+# disabled).
 import-graph=
 import-graph=
 
 
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled).
+# Output a graph (.gv or any supported image format) of internal dependencies
+# to the given file (report RP0402 must not be disabled).
 int-import-graph=
 int-import-graph=
 
 
 # Force import order to recognize a module as part of the standard
 # Force import order to recognize a module as part of the standard
@@ -503,32 +376,359 @@ known-third-party=enchant
 preferred-modules=
 preferred-modules=
 
 
 
 
-[CLASSES]
+[LOGGING]
 
 
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,
-                      __new__,
-                      setUp,
-                      __post_init__
+# The type of string formatting that logging methods do. `old` means using %
+# formatting, `new` is for `{}` formatting.
+logging-format-style=old
 
 
-# List of member names, which should be excluded from the protected access
-# warning.
-exclude-protected=_asdict,
-                  _fields,
-                  _replace,
-                  _source,
-                  _make
+# Logging modules to check that the string format arguments are in logging
+# function parameter format.
+logging-modules=logging
 
 
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls
 
 
-# List of valid names for the first argument in a metaclass class method.
-valid-metaclass-classmethod-first-arg=cls
+[MESSAGES CONTROL]
 
 
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
+# UNDEFINED.
+confidence=HIGH,
+           CONTROL_FLOW,
+           INFERENCE,
+           INFERENCE_FAILURE,
+           UNDEFINED
 
 
-[EXCEPTIONS]
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once). You can also use "--disable=all" to
+# disable everything first and then re-enable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use "--disable=all --enable=classes
+# --disable=W".
+disable=raw-checker-failed,
+        bad-inline-option,
+        locally-disabled,
+        file-ignored,
+        suppressed-message,
+        useless-suppression,
+        deprecated-pragma,
+        use-symbolic-message-instead,
+        consider-using-f-string,
+        attribute-defined-outside-init,
+        comparison-with-callable,
+        dangerous-default-value,
+        global-statement,
+        import-outside-toplevel,
+        invalid-name,
+        line-too-long,
+        missing-class-docstring,
+        missing-function-docstring,
+        missing-module-docstring,
+        protected-access,
+        no-classmethod-decorator,
+        no-staticmethod-decorator,
+        useless-object-inheritance,
+        property-with-parameters,
+        too-many-ancestors,
+        too-many-instance-attributes,
+        too-few-public-methods,
+        too-many-public-methods,
+        too-many-return-statements,
+        too-many-branches,
+        too-many-arguments,
+        too-many-locals,
+        too-many-statements,
+        too-many-boolean-expressions,
+        consider-merging-isinstance,
+        too-many-nested-blocks,
+        simplifiable-if-statement,
+        redefined-argument-from-local,
+        no-else-return,
+        consider-using-ternary,
+        trailing-comma-tuple,
+        stop-iteration-return,
+        simplify-boolean-expression,
+        inconsistent-return-statements,
+        useless-return,
+        consider-swap-variables,
+        consider-using-join,
+        consider-using-in,
+        consider-using-get,
+        chained-comparison,
+        consider-using-dict-comprehension,
+        consider-using-set-comprehension,
+        simplifiable-if-expression,
+        no-else-raise,
+        unnecessary-comprehension,
+        consider-using-sys-exit,
+        no-else-break,
+        no-else-continue,
+        super-with-arguments,
+        simplifiable-condition,
+        condition-evals-to-constant,
+        consider-using-generator,
+        use-a-generator,
+        consider-using-min-builtin,
+        consider-using-max-builtin,
+        consider-using-with,
+        unnecessary-dict-index-lookup,
+        use-list-literal,
+        use-dict-literal,
+        unnecessary-list-index-lookup,
+        literal-comparison,
+        comparison-with-itself,
+        comparison-of-constants,
+        cyclic-import,
+        consider-using-from-import,
+        duplicate-code,
+        raise-missing-from,
+        redefined-builtin,
+        redefined-outer-name,
+        too-many-lines,
+        unused-argument,
+        unused-variable,
+        unused-wildcard-import,
+        using-constant-test,
+        wrong-import-order,
+        wrong-import-position,
+        not-callable,
+        wildcard-import
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once). See also the "--disable" option for examples.
+#enable=c-extension-no-member
 
 
-# Exceptions that will emit a warning when being caught. Defaults to
-# "BaseException, Exception".
-overgeneral-exceptions=BaseException,
-                       Exception
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,
+      XXX,
+      TODO
+
+# Regular expression of note tags to take in consideration.
+notes-rgx=
+
+
+[REFACTORING]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+# Complete name of functions that never returns. When checking for
+# inconsistent-return-statements if a never returning function is called then
+# it will be considered as an explicit return statement and no message will be
+# printed.
+never-returning-functions=sys.exit
+
+
+[REPORTS]
+
+# Python expression which should return a score less than or equal to 10. You
+# have access to the variables 'fatal', 'error', 'warning', 'refactor',
+# 'convention', and 'info' which contain the number of messages in each
+# category, as well as 'statement' which is the total number of statements
+# analyzed. This score is used by the global evaluation report (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details.
+msg-template=
+
+# Set the output format. Available formats are text, parseable, colorized, json
+# and msvs (visual studio). You can also give a reporter class, e.g.
+# mypackage.mymodule.MyReporterClass.
+#output-format=
+
+# Tells whether to display a full report or only the messages.
+reports=no
+
+# Activate the evaluation score.
+score=yes
+
+
+[SIMILARITIES]
+
+# Comments are removed from the similarity computation
+ignore-comments=yes
+
+# Docstrings are removed from the similarity computation
+ignore-docstrings=yes
+
+# Imports are removed from the similarity computation
+ignore-imports=no
+
+# Signatures are removed from the similarity computation
+ignore-signatures=yes
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+
+[SPELLING]
+
+# Limits count of emitted suggestions for spelling mistakes.
+max-spelling-suggestions=4
+
+# Spelling dictionary name. Available dictionaries: none. To make it work,
+# install the 'python-enchant' package.
+spelling-dict=
+
+# List of comma separated words that should be considered directives if they
+# appear at the beginning of a comment and should not be checked.
+spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains the private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to the private dictionary (see the
+# --spelling-private-dict-file option) instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[STRING]
+
+# This flag controls whether inconsistent-quotes generates a warning when the
+# character used as a quote delimiter is used inconsistently within a module.
+check-quote-consistency=no
+
+# This flag controls whether the implicit-str-concat should generate a warning
+# on implicit string concatenation in sequences defined over several lines.
+check-str-concat-over-line-jumps=no
+
+
+[TYPECHECK]
+
+# List of decorators that produce context managers, such as
+# contextlib.contextmanager. Add to this list to register other decorators that
+# produce valid context managers.
+contextmanager-decorators=contextlib.contextmanager
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=base.cr,
+                  base.le,
+                  base.localAvatar,
+                  Pmw.AboutDialog,
+                  Pmw.Balloon,
+                  Pmw.ButtonBox,
+                  Pmw.Color,
+                  Pmw.ComboBox,
+                  Pmw.EntryField,
+                  Pmw.Group,
+                  Pmw.INITOPT,
+                  Pmw.MegaArchetype,
+                  Pmw.MegaToplevel,
+                  Pmw.MegaWidget,
+                  Pmw.MenuBar,
+                  Pmw.MessageBar,
+                  Pmw.NoteBook,
+                  Pmw.OK,
+                  Pmw.OptionMenu,
+                  Pmw.OptionMenu,
+                  Pmw.PARTIAL,
+                  Pmw.PanedWidget,
+                  Pmw.ScrolledCanvas,
+                  Pmw.ScrolledFrame,
+                  Pmw.ScrolledListBox,
+                  Pmw.ScrolledText,
+                  Pmw.aboutcontact,
+                  Pmw.aboutcopyright,
+                  Pmw.aboutversion,
+                  Pmw.forwardmethods,
+                  Pmw.integervalidator,
+                  Pmw.popgrab,
+                  Pmw.pushgrab,
+                  Pmw.realvalidator,
+                  Pmw.setgeometryanddeiconify
+
+# Tells whether to warn about missing members when the owner of the attribute
+# is inferred to be None.
+ignore-none=yes
+
+# This flag controls whether pylint should warn about no-member and similar
+# checks whenever an opaque object is returned when inferring. The inference
+# can return multiple potential results while evaluating a Python object, but
+# some branches might not be evaluated, which results in partial inference. In
+# that case, it might be useful to still emit no-member and other checks for
+# the rest of the inferred objects.
+ignore-on-opaque-inference=yes
+
+# List of symbolic message names to ignore for Mixin members.
+ignored-checks-for-mixins=no-member,
+                          not-async-context-manager,
+                          not-context-manager,
+                          attribute-defined-outside-init
+
+# List of class names for which member attributes should not be checked (useful
+# for classes with dynamically set attributes). This supports the use of
+# qualified names.
+ignored-classes=optparse.Values,thread._local,_thread._local,direct.showbase.PythonUtil.ScratchPad
+
+# Show a hint with possible names when a member name was not found. The aspect
+# of finding the hint is based on edit distance.
+missing-member-hint=yes
+
+# The minimum edit distance a name should have in order to be considered a
+# similar match for a missing member name.
+missing-member-hint-distance=1
+
+# The total number of similar names that should be taken in consideration when
+# showing a hint for a missing member.
+missing-member-max-choices=1
+
+# Regex pattern to define which classes are considered mixins.
+mixin-class-rgx=.*[Mm]ixin
+
+# List of decorators that change the signature of a decorated function.
+signature-mutators=
+
+
+[VARIABLES]
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid defining new builtins when possible.
+additional-builtins=base,
+                    simbase,
+                    __dev__,
+                    onScreenDebug,
+                    render,
+                    hidden,
+                    cluster,
+                    launcher,
+                    taskMgr,
+                    localAvatar,
+                    game
+
+# Tells whether unused global variables should be treated as a violation.
+allow-global-unused-variables=yes
+
+# List of names allowed to shadow builtins
+allowed-redefined-builtins=
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,
+          _cb
+
+# A regular expression matching the name of dummy variables (i.e. expected to
+# not be used).
+dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
+
+# Argument names that match this expression will be ignored.
+ignored-argument-names=_.*|^ignored_|^unused_
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# List of qualified module names which can have objects that can redefine
+# builtins.
+redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io,direct.showbase.ShowBase,direct.showbase.PythonUtil

+ 1 - 0
BACKERS.md

@@ -27,6 +27,7 @@ This is a list of all the people who are contributing financially to Panda3D.  I
 * Maxwell Dreytser
 * Maxwell Dreytser
 * SureBet
 * SureBet
 * Gyedo Jeon
 * Gyedo Jeon
+* GameDev JONI
 
 
 ## Backers
 ## Backers
 
 

+ 3 - 3
README.md

@@ -106,14 +106,14 @@ python3 makepanda/makepanda.py --everything --installer --no-egl --no-gles --no-
 You will probably see some warnings saying that it's unable to find several
 You will probably see some warnings saying that it's unable to find several
 dependency packages.  You should determine which ones you want to include in
 dependency packages.  You should determine which ones you want to include in
 your build and install the respective development packages.  You may visit
 your build and install the respective development packages.  You may visit
-[this manual page](https://www.panda3d.org/manual/?title=Third-party_dependencies_and_license_info)
+[this manual page](https://docs.panda3d.org/1.11/python/distribution/thirdparty-licenses)
 for an overview of the various dependencies.
 for an overview of the various dependencies.
 
 
 If you are on Ubuntu, this command should cover the most frequently
 If you are on Ubuntu, this command should cover the most frequently
 used third-party packages:
 used third-party packages:
 
 
 ```bash
 ```bash
-sudo apt-get install build-essential pkg-config fakeroot python3-dev libpng-dev libjpeg-dev libtiff-dev zlib1g-dev libssl-dev libx11-dev libgl1-mesa-dev libxrandr-dev libxxf86dga-dev libxcursor-dev bison flex libfreetype6-dev libvorbis-dev libeigen3-dev libopenal-dev libode-dev libbullet-dev nvidia-cg-toolkit libgtk2.0-dev libassimp-dev libopenexr-dev
+sudo apt-get install build-essential pkg-config fakeroot python3-dev libpng-dev libjpeg-dev libtiff-dev zlib1g-dev libssl-dev libx11-dev libgl1-mesa-dev libxrandr-dev libxxf86dga-dev libxcursor-dev bison flex libfreetype6-dev libvorbis-dev libeigen3-dev libopenal-dev libode-dev libbullet-dev nvidia-cg-toolkit libgtk-3-dev libassimp-dev libopenexr-dev
 ```
 ```
 
 
 Once Panda3D has built, you can either install the .deb or .rpm package that
 Once Panda3D has built, you can either install the .deb or .rpm package that
@@ -136,7 +136,7 @@ macOS
 -----
 -----
 
 
 On macOS, you will need to download a set of precompiled thirdparty packages in order to
 On macOS, you will need to download a set of precompiled thirdparty packages in order to
-compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.13/panda3d-1.10.13-tools-mac.tar.gz).
+compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-mac.tar.gz).
 
 
 After placing the thirdparty directory inside the panda3d source directory,
 After placing the thirdparty directory inside the panda3d source directory,
 you may build Panda3D using a command like the following:
 you may build Panda3D using a command like the following:

+ 3 - 2
contrib/src/ai/aiWorld.cxx

@@ -99,8 +99,9 @@ Flock AIWorld::get_flock(unsigned int flock_id) {
       return *_flock_pool[i];
       return *_flock_pool[i];
     }
     }
   }
   }
-  Flock *null_flock = nullptr;
-  return *null_flock;
+  static Flock null_flock(0, 0.0, 0.0, 0, 0, 0);
+  nassertr(false, null_flock);
+  return null_flock;
 }
 }
 
 
 /**
 /**

+ 23 - 1
direct/src/actor/Actor.py

@@ -6,7 +6,29 @@ to learn more about loading animated models.
 
 
 __all__ = ['Actor']
 __all__ = ['Actor']
 
 
-from panda3d.core import *
+from panda3d.core import (
+    AnimBundleNode,
+    AnimControlCollection,
+    Character,
+    ConfigVariableBool,
+    DecalEffect,
+    Filename,
+    GlobPattern,
+    LineStream,
+    LoaderOptions,
+    LODNode,
+    ModelNode,
+    MovingPartBase,
+    MovingPartMatrix,
+    NodePath,
+    PandaNode,
+    PartBundle,
+    PartSubset,
+    Point3,
+    TransformState,
+    Vec3,
+    autoBind,
+)
 from panda3d.core import Loader as PandaLoader
 from panda3d.core import Loader as PandaLoader
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.Loader import Loader
 from direct.showbase.Loader import Loader

+ 26 - 26
direct/src/cluster/ClusterClient.py

@@ -1,8 +1,26 @@
 """ClusterClient: Master for multi-piping or PC clusters."""
 """ClusterClient: Master for multi-piping or PC clusters."""
 
 
-from panda3d.core import *
-from .ClusterMsgs import *
-from .ClusterConfig import *
+from panda3d.core import (
+    ClockObject,
+    ConnectionWriter,
+    Point3,
+    QueuedConnectionManager,
+    QueuedConnectionReader,
+    VBase3,
+    Vec3,
+    decomposeMatrix,
+)
+from .ClusterMsgs import (
+    CLUSTER_DAEMON_PORT,
+    CLUSTER_NAMED_MOVEMENT_DONE,
+    CLUSTER_NAMED_OBJECT_MOVEMENT,
+    CLUSTER_NONE,
+    CLUSTER_SERVER_PORT,
+    CLUSTER_SWAP_READY,
+    SERVER_STARTUP_STRING,
+    ClusterMsgHandler,
+)
+from .ClusterConfig import ClientConfigs
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 from direct.showbase import DirectObject
 from direct.showbase import DirectObject
 from direct.task import Task
 from direct.task import Task
@@ -95,7 +113,6 @@ class ClusterClient(DirectObject.DirectObject):
         self.notify.debug('post startMoveCam')
         self.notify.debug('post startMoveCam')
         self.startMoveSelectedTask()
         self.startMoveSelectedTask()
 
 
-
     def startReaderPollTask(self):
     def startReaderPollTask(self):
         """ Task to handle datagrams from server """
         """ Task to handle datagrams from server """
         # Run this task just after the listener poll task
         # Run this task just after the listener poll task
@@ -112,7 +129,6 @@ class ClusterClient(DirectObject.DirectObject):
 
 
         return Task.cont
         return Task.cont
 
 
-
     def startControlObjectTask(self):
     def startControlObjectTask(self):
         self.notify.debug("moving control objects")
         self.notify.debug("moving control objects")
         taskMgr.add(self.controlObjectTask,"controlObjectTask",50)
         taskMgr.add(self.controlObjectTask,"controlObjectTask",50)
@@ -134,7 +150,6 @@ class ClusterClient(DirectObject.DirectObject):
         self.notify.debug('adding move cam')
         self.notify.debug('adding move cam')
         taskMgr.add(self.moveCameraTask, "moveCamTask", 49)
         taskMgr.add(self.moveCameraTask, "moveCamTask", 49)
 
 
-
     def controlObjectTask(self, task):
     def controlObjectTask(self, task):
         for pair in self.sortedControlMappings:
         for pair in self.sortedControlMappings:
             object     = pair[1]
             object     = pair[1]
@@ -153,8 +168,6 @@ class ClusterClient(DirectObject.DirectObject):
         for server in serverList:
         for server in serverList:
             self.serverList[server].sendNamedMovementDone()
             self.serverList[server].sendNamedMovementDone()
 
 
-
-
     def redoSortedPriorities(self):
     def redoSortedPriorities(self):
         self.sortedControlMappings = []
         self.sortedControlMappings = []
         for key in self.controlMappings:
         for key in self.controlMappings:
@@ -176,7 +189,6 @@ class ClusterClient(DirectObject.DirectObject):
         for server in serverList:
         for server in serverList:
             self.serverList[server].sendMoveNamedObject(xyz,hpr,scale,color,hidden,object)
             self.serverList[server].sendMoveNamedObject(xyz,hpr,scale,color,hidden,object)
 
 
-
     def moveCameraTask(self, task):
     def moveCameraTask(self, task):
         self.moveCamera(
         self.moveCamera(
             base.camera.getPos(render),
             base.camera.getPos(render),
@@ -203,7 +215,6 @@ class ClusterClient(DirectObject.DirectObject):
                 server.sendMoveSelected(xyz, hpr, scale)
                 server.sendMoveSelected(xyz, hpr, scale)
         return Task.cont
         return Task.cont
 
 
-
     def addNamedObjectMapping(self, object, name, hasColor = True):
     def addNamedObjectMapping(self, object, name, hasColor = True):
         if name not in self.objectMappings:
         if name not in self.objectMappings:
             self.objectMappings[name] = object
             self.objectMappings[name] = object
@@ -215,7 +226,6 @@ class ClusterClient(DirectObject.DirectObject):
         if name in self.objectMappings:
         if name in self.objectMappings:
             self.objectMappings.pop(name)
             self.objectMappings.pop(name)
 
 
-
     def addControlMapping(self, objectName, controlledName, serverList = None,
     def addControlMapping(self, objectName, controlledName, serverList = None,
                           offset = None, priority = 0):
                           offset = None, priority = 0):
         if objectName not in self.controlMappings:
         if objectName not in self.controlMappings:
@@ -260,7 +270,6 @@ class ClusterClient(DirectObject.DirectObject):
                     self.controlPriorities.pop(name)
                     self.controlPriorities.pop(name)
         self.redoSortedPriorities()
         self.redoSortedPriorities()
 
 
-
     def getNodePathFindCmd(self, nodePath):
     def getNodePathFindCmd(self, nodePath):
         pathString = repr(nodePath)
         pathString = repr(nodePath)
         index = pathString.find('/')
         index = pathString.find('/')
@@ -280,7 +289,6 @@ class ClusterClient(DirectObject.DirectObject):
         else:
         else:
             return pathString
             return pathString
 
 
-
     def addObjectTag(self,object,selectFunction,deselectFunction,selectArgs,deselectArgs):
     def addObjectTag(self,object,selectFunction,deselectFunction,selectArgs,deselectArgs):
         newTag = {}
         newTag = {}
         newTag["selectFunction"] = selectFunction
         newTag["selectFunction"] = selectFunction
@@ -289,12 +297,10 @@ class ClusterClient(DirectObject.DirectObject):
         newTag["deselectArgs"]     = deselectArgs
         newTag["deselectArgs"]     = deselectArgs
         self.taggedObjects[object] = newTag
         self.taggedObjects[object] = newTag
 
 
-
     def removeObjectTag(self,object):
     def removeObjectTag(self,object):
 
 
         self.taggedObjects.pop(object)
         self.taggedObjects.pop(object)
 
 
-
     def selectNodePath(self, nodePath):
     def selectNodePath(self, nodePath):
         name = self.getNodePathName(nodePath)
         name = self.getNodePathName(nodePath)
         if name in self.taggedObjects:
         if name in self.taggedObjects:
@@ -307,7 +313,6 @@ class ClusterClient(DirectObject.DirectObject):
         else:
         else:
             self(self.getNodePathFindCmd(nodePath) + '.select()', 0)
             self(self.getNodePathFindCmd(nodePath) + '.select()', 0)
 
 
-
     def deselectNodePath(self, nodePath):
     def deselectNodePath(self, nodePath):
         name = self.getNodePathName(nodePath)
         name = self.getNodePathName(nodePath)
         if name in self.taggedObjects:
         if name in self.taggedObjects:
@@ -345,7 +350,6 @@ class ClusterClient(DirectObject.DirectObject):
             # Execute locally
             # Execute locally
             exec(commandString, __builtins__)
             exec(commandString, __builtins__)
 
 
-
     def handleDatagram(self,dgi,type,server):
     def handleDatagram(self,dgi,type,server):
         if type == CLUSTER_NONE:
         if type == CLUSTER_NONE:
             pass
             pass
@@ -370,7 +374,6 @@ class ClusterClient(DirectObject.DirectObject):
         # clear the queue
         # clear the queue
         self.serverQueues[server] = []
         self.serverQueues[server] = []
 
 
-
     def handleNamedMovement(self, data):
     def handleNamedMovement(self, data):
         """ Update cameraJig position to reflect latest position """
         """ Update cameraJig position to reflect latest position """
 
 
@@ -390,7 +393,6 @@ class ClusterClient(DirectObject.DirectObject):
         else:
         else:
             self.notify.debug("recieved unknown named object command: "+name)
             self.notify.debug("recieved unknown named object command: "+name)
 
 
-
     def exit(self):
     def exit(self):
         # Execute remotely
         # Execute remotely
         for server in self.serverList:
         for server in self.serverList:
@@ -457,8 +459,6 @@ class DisplayConnection:
             self.qcr.addConnection(self.tcpConn)
             self.qcr.addConnection(self.tcpConn)
             self.cw=ConnectionWriter(qcm, 0)
             self.cw=ConnectionWriter(qcm, 0)
 
 
-
-
     def poll(self):
     def poll(self):
         """ Non blocking task to read all available datagrams """
         """ Non blocking task to read all available datagrams """
         dataGrams = []
         dataGrams = []
@@ -473,9 +473,6 @@ class DisplayConnection:
 
 
         return dataGrams
         return dataGrams
 
 
-
-
-
     def sendCamOffset(self, xyz, hpr):
     def sendCamOffset(self, xyz, hpr):
         ClusterClient.notify.debug("send cam offset...")
         ClusterClient.notify.debug("send cam offset...")
         ClusterClient.notify.debug(("packet %d xyz, hpr=%f %f %f %f %f %f" %
         ClusterClient.notify.debug(("packet %d xyz, hpr=%f %f %f %f %f %f" %
@@ -491,12 +488,11 @@ class DisplayConnection:
              (" fl, fs, fo=%0.3f, (%0.3f, %0.3f), (%0.3f, %0.3f)" %
              (" fl, fs, fo=%0.3f, (%0.3f, %0.3f), (%0.3f, %0.3f)" %
               (focalLength, filmSize[0], filmSize[1],
               (focalLength, filmSize[0], filmSize[1],
                filmOffset[0], filmOffset[1])))
                filmOffset[0], filmOffset[1])))
-            )
+        )
         datagram = self.msgHandler.makeCamFrustumDatagram(
         datagram = self.msgHandler.makeCamFrustumDatagram(
             focalLength, filmSize, filmOffset)
             focalLength, filmSize, filmOffset)
         self.cw.send(datagram, self.tcpConn)
         self.cw.send(datagram, self.tcpConn)
 
 
-
     def sendNamedMovementDone(self):
     def sendNamedMovementDone(self):
 
 
         datagram = self.msgHandler.makeNamedMovementDone()
         datagram = self.msgHandler.makeNamedMovementDone()
@@ -566,6 +562,7 @@ class DisplayConnection:
             frameCount, frameTime, dt)
             frameCount, frameTime, dt)
         self.cw.send(datagram, self.tcpConn)
         self.cw.send(datagram, self.tcpConn)
 
 
+
 class ClusterConfigItem:
 class ClusterConfigItem:
     def __init__(self, serverConfigName, serverName,
     def __init__(self, serverConfigName, serverName,
                  serverDaemonPort, serverMsgPort):
                  serverDaemonPort, serverMsgPort):
@@ -581,9 +578,11 @@ class ClusterConfigItem:
         self.focalLength = None
         self.focalLength = None
         self.filmSize = None
         self.filmSize = None
         self.filmOffset = None
         self.filmOffset = None
+
     def setCamOffset(self, xyz, hpr):
     def setCamOffset(self, xyz, hpr):
         self.xyz = xyz
         self.xyz = xyz
         self.hpr = hpr
         self.hpr = hpr
+
     def setCamFrustum(self, focalLength, filmSize, filmOffset):
     def setCamFrustum(self, focalLength, filmSize, filmOffset):
         self.fFrustum = 1
         self.fFrustum = 1
         self.focalLength = focalLength
         self.focalLength = focalLength
@@ -671,6 +670,7 @@ def createClusterClient():
 class DummyClusterClient(DirectObject.DirectObject):
 class DummyClusterClient(DirectObject.DirectObject):
     """ Dummy class to handle command strings when not in cluster mode """
     """ Dummy class to handle command strings when not in cluster mode """
     notify = DirectNotifyGlobal.directNotify.newCategory("DummyClusterClient")
     notify = DirectNotifyGlobal.directNotify.newCategory("DummyClusterClient")
+
     def __init__(self):
     def __init__(self):
         pass
         pass
 
 

+ 13 - 13
direct/src/cluster/ClusterConfig.py

@@ -1,5 +1,5 @@
 
 
-from .ClusterClient import *
+from panda3d.core import Vec3
 
 
 #: A dictionary of information for various cluster configurations.
 #: A dictionary of information for various cluster configurations.
 #: Dictionary is keyed on cluster-config string
 #: Dictionary is keyed on cluster-config string
@@ -26,7 +26,7 @@ ClientConfigs = {
                               'display mode': 'client',
                               'display mode': 'client',
                               'pos': Vec3(0),
                               'pos': Vec3(0),
                               'hpr': Vec3(0)}
                               'hpr': Vec3(0)}
-                             ],
+                            ],
     'two-server':          [{'display name': 'master',
     'two-server':          [{'display name': 'master',
                               'display mode': 'client',
                               'display mode': 'client',
                               'pos': Vec3(0),
                               'pos': Vec3(0),
@@ -35,7 +35,7 @@ ClientConfigs = {
                               'pos': Vec3(0),
                               'pos': Vec3(0),
                               'hpr': Vec3(0)
                               'hpr': Vec3(0)
                               }
                               }
-                             ],
+                            ],
     'three-server':          [{'display name': 'master',
     'three-server':          [{'display name': 'master',
                               'display mode': 'client',
                               'display mode': 'client',
                               'pos': Vec3(0),
                               'pos': Vec3(0),
@@ -48,14 +48,14 @@ ClientConfigs = {
                               'pos': Vec3(0),
                               'pos': Vec3(0),
                               'hpr': Vec3(0)
                               'hpr': Vec3(0)
                               }
                               }
-                             ],
+                              ],
     'mono-cave':   [{'display name': 'la',
     'mono-cave':   [{'display name': 'la',
                       'pos': Vec3(-0.105, -0.020, 5.000),
                       'pos': Vec3(-0.105, -0.020, 5.000),
                       'hpr': Vec3(51.213, 0.000, 0.000),
                       'hpr': Vec3(51.213, 0.000, 0.000),
                       'focal length': 0.809,
                       'focal length': 0.809,
                       'film size': (1.000, 0.831),
                       'film size': (1.000, 0.831),
                       'film offset': (0.000, 0.173),
                       'film offset': (0.000, 0.173),
-                      },
+                     },
                      {'display name': 'lb',
                      {'display name': 'lb',
                       'display mode': 'client',
                       'display mode': 'client',
                       'pos': Vec3(-0.105, -0.020, 5.000),
                       'pos': Vec3(-0.105, -0.020, 5.000),
@@ -71,7 +71,7 @@ ClientConfigs = {
                       'film size': (1.000, 0.830),
                       'film size': (1.000, 0.830),
                       'film offset': (-0.000, 0.173),
                       'film offset': (-0.000, 0.173),
                       },
                       },
-                     ],
+                    ],
     'seamless-cave':   [{'display name': 'master',
     'seamless-cave':   [{'display name': 'master',
                           'display mode': 'client',
                           'display mode': 'client',
                           'pos': Vec3(-0.105, -0.020, 5.000),
                           'pos': Vec3(-0.105, -0.020, 5.000),
@@ -79,7 +79,7 @@ ClientConfigs = {
                           'focal length': 0.815,
                           'focal length': 0.815,
                           'film size': (1.000, 0.831),
                           'film size': (1.000, 0.831),
                           'film offset': (0.000, 0.173),
                           'film offset': (0.000, 0.173),
-                          },
+                         },
                          {'display name': 'la',
                          {'display name': 'la',
                           'pos': Vec3(-0.105, -0.020, 5.000),
                           'pos': Vec3(-0.105, -0.020, 5.000),
                           'hpr': Vec3(51.213, 0.000, 0.000),
                           'hpr': Vec3(51.213, 0.000, 0.000),
@@ -122,12 +122,12 @@ ClientConfigs = {
                           'film size': (1.000, 0.831),
                           'film size': (1.000, 0.831),
                           'film offset': (-0.000, 0.173),
                           'film offset': (-0.000, 0.173),
                           },
                           },
-                         ],
+                        ],
     'ursula':              [{'display name': 'master',
     'ursula':              [{'display name': 'master',
                               'display mode': 'client',
                               'display mode': 'client',
                               'pos': Vec3(0),
                               'pos': Vec3(0),
                               'hpr': Vec3(0),
                               'hpr': Vec3(0),
-                              },
+                             },
                              {'display name': 'l',
                              {'display name': 'l',
                               'pos': Vec3(-.105, 0, 0),
                               'pos': Vec3(-.105, 0, 0),
                               'hpr': Vec3(0, 0, 0),
                               'hpr': Vec3(0, 0, 0),
@@ -144,11 +144,11 @@ ClientConfigs = {
                               #'film offset': (-0.105, -2),
                               #'film offset': (-0.105, -2),
                               'film offset': (-0.105, -1),
                               'film offset': (-0.105, -1),
                               }
                               }
-                             ],
+                            ],
     'composite':           [{'display name': 'master',
     'composite':           [{'display name': 'master',
                               'display mode': 'client',
                               'display mode': 'client',
                               'pos': Vec3(0),
                               'pos': Vec3(0),
-                              },
+                             },
                              {'display name': 'left',
                              {'display name': 'left',
                               'pos': Vec3(-0.105, -0.020, 5.000),
                               'pos': Vec3(-0.105, -0.020, 5.000),
                               'hpr': Vec3(-0.370, 0.000, 0.000),
                               'hpr': Vec3(-0.370, 0.000, 0.000),
@@ -163,5 +163,5 @@ ClientConfigs = {
                               'film size': (1.000, 0.831),
                               'film size': (1.000, 0.831),
                               'film offset': (0.000, 0.173),
                               'film offset': (0.000, 0.173),
                               }
                               }
-                             ],
-    }
+                            ],
+}

+ 1 - 1
direct/src/cluster/ClusterMsgs.py

@@ -3,7 +3,7 @@
 # This module is intended to supply routines and dataformats common to
 # This module is intended to supply routines and dataformats common to
 # both ClusterClient and ClusterServer.
 # both ClusterClient and ClusterServer.
 
 
-from panda3d.core import *
+from panda3d.core import NetDatagram
 from direct.distributed.PyDatagram import PyDatagram
 from direct.distributed.PyDatagram import PyDatagram
 from direct.distributed.PyDatagramIterator import PyDatagramIterator
 from direct.distributed.PyDatagramIterator import PyDatagramIterator
 import time
 import time

+ 35 - 19
direct/src/cluster/ClusterServer.py

@@ -1,10 +1,35 @@
-from panda3d.core import *
-from .ClusterMsgs import *
-from direct.distributed.MsgTypes import *
+from panda3d.core import (
+    ClockObject,
+    ConnectionWriter,
+    NetAddress,
+    PointerToConnection,
+    QueuedConnectionListener,
+    QueuedConnectionManager,
+    QueuedConnectionReader,
+    Vec3,
+)
+from .ClusterMsgs import (
+    CLUSTER_CAM_FRUSTUM,
+    CLUSTER_CAM_MOVEMENT,
+    CLUSTER_CAM_OFFSET,
+    CLUSTER_COMMAND_STRING,
+    CLUSTER_DAEMON_PORT,
+    CLUSTER_EXIT,
+    CLUSTER_NAMED_MOVEMENT_DONE,
+    CLUSTER_NAMED_OBJECT_MOVEMENT,
+    CLUSTER_NONE,
+    CLUSTER_SELECTED_MOVEMENT,
+    CLUSTER_SERVER_PORT,
+    CLUSTER_SWAP_NOW,
+    CLUSTER_SWAP_READY,
+    CLUSTER_TIME_DATA,
+    ClusterMsgHandler,
+)
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 from direct.showbase import DirectObject
 from direct.showbase import DirectObject
 from direct.task import Task
 from direct.task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
+import builtins
 
 
 # NOTE: This assumes the following variables are set via bootstrap command line
 # NOTE: This assumes the following variables are set via bootstrap command line
 # arguments on server startup:
 # arguments on server startup:
@@ -15,6 +40,7 @@ from direct.task.TaskManagerGlobal import taskMgr
 # Also, I'm not sure multiple camera-group configurations are working for the
 # Also, I'm not sure multiple camera-group configurations are working for the
 # cluster system.
 # cluster system.
 
 
+
 class ClusterServer(DirectObject.DirectObject):
 class ClusterServer(DirectObject.DirectObject):
     notify = DirectNotifyGlobal.directNotify.newCategory("ClusterServer")
     notify = DirectNotifyGlobal.directNotify.newCategory("ClusterServer")
     MSG_NUM = 2000000
     MSG_NUM = 2000000
@@ -76,8 +102,6 @@ class ClusterServer(DirectObject.DirectObject):
             clusterDaemonPort = CLUSTER_DAEMON_PORT
             clusterDaemonPort = CLUSTER_DAEMON_PORT
         self.daemon.serverReady(clusterDaemonClient, clusterDaemonPort)
         self.daemon.serverReady(clusterDaemonClient, clusterDaemonPort)
 
 
-
-
     def startListenerPollTask(self):
     def startListenerPollTask(self):
         # Run this task near the start of frame, sometime after the dataLoop
         # Run this task near the start of frame, sometime after the dataLoop
         taskMgr.add(self.listenerPollTask, "serverListenerPollTask", -40)
         taskMgr.add(self.listenerPollTask, "serverListenerPollTask", -40)
@@ -100,7 +124,6 @@ class ClusterServer(DirectObject.DirectObject):
                 self.notify.warning("getNewConnection returned false")
                 self.notify.warning("getNewConnection returned false")
         return Task.cont
         return Task.cont
 
 
-
     def addNamedObjectMapping(self, object, name, hasColor = True,
     def addNamedObjectMapping(self, object, name, hasColor = True,
                               priority = 0):
                               priority = 0):
         if name not in self.objectMappings:
         if name not in self.objectMappings:
@@ -113,7 +136,6 @@ class ClusterServer(DirectObject.DirectObject):
         if name in self.objectMappings:
         if name in self.objectMappings:
             self.objectMappings.pop(name)
             self.objectMappings.pop(name)
 
 
-
     def redoSortedPriorities(self):
     def redoSortedPriorities(self):
 
 
         self.sortedControlMappings = []
         self.sortedControlMappings = []
@@ -123,7 +145,6 @@ class ClusterServer(DirectObject.DirectObject):
 
 
         self.sortedControlMappings.sort()
         self.sortedControlMappings.sort()
 
 
-
     def addControlMapping(self, objectName, controlledName, offset = None,
     def addControlMapping(self, objectName, controlledName, offset = None,
                           priority = 0):
                           priority = 0):
         if objectName not in self.controlMappings:
         if objectName not in self.controlMappings:
@@ -134,20 +155,18 @@ class ClusterServer(DirectObject.DirectObject):
             self.controlPriorities[objectName] = priority
             self.controlPriorities[objectName] = priority
             self.redoSortedPriorities()
             self.redoSortedPriorities()
         else:
         else:
-            self.notify.debug('attempt to add duplicate controlled object: '+name)
+            self.notify.debug('attempt to add duplicate controlled object: ' + objectName)
 
 
     def setControlMappingOffset(self, objectName, offset):
     def setControlMappingOffset(self, objectName, offset):
         if objectName in self.controlMappings:
         if objectName in self.controlMappings:
             self.controlOffsets[objectName] = offset
             self.controlOffsets[objectName] = offset
 
 
-
     def removeControlMapping(self, name):
     def removeControlMapping(self, name):
         if name in self.controlMappings:
         if name in self.controlMappings:
             self.controlMappings.pop(name)
             self.controlMappings.pop(name)
             self.controlPriorities.pop(name)
             self.controlPriorities.pop(name)
         self.redoSortedPriorities()
         self.redoSortedPriorities()
 
 
-
     def startControlObjectTask(self):
     def startControlObjectTask(self):
         self.notify.debug("moving control objects")
         self.notify.debug("moving control objects")
         taskMgr.add(self.controlObjectTask,"controlObjectTask",50)
         taskMgr.add(self.controlObjectTask,"controlObjectTask",50)
@@ -164,7 +183,6 @@ class ClusterServer(DirectObject.DirectObject):
         self.sendNamedMovementDone()
         self.sendNamedMovementDone()
         return Task.cont
         return Task.cont
 
 
-
     def sendNamedMovementDone(self):
     def sendNamedMovementDone(self):
         self.notify.debug("named movement done")
         self.notify.debug("named movement done")
         datagram = self.msgHandler.makeNamedMovementDone()
         datagram = self.msgHandler.makeNamedMovementDone()
@@ -308,12 +326,10 @@ class ClusterServer(DirectObject.DirectObject):
         else:
         else:
             self.notify.debug("recieved unknown named object command: "+name)
             self.notify.debug("recieved unknown named object command: "+name)
 
 
-
     def handleMessageQueue(self):
     def handleMessageQueue(self):
-
-        #print self.messageQueue
+        #print(self.messageQueue)
         for data in self.messageQueue:
         for data in self.messageQueue:
-            #print "in queue",dgi
+            #print("in queue", dgi)
             self.handleNamedMovement(data)
             self.handleNamedMovement(data)
 
 
         self.messageQueue = []
         self.messageQueue = []
@@ -328,8 +344,8 @@ class ClusterServer(DirectObject.DirectObject):
         """ Update cameraJig position to reflect latest position """
         """ Update cameraJig position to reflect latest position """
         (x, y, z, h, p, r, sx, sy, sz) = self.msgHandler.parseSelectedMovementDatagram(
         (x, y, z, h, p, r, sx, sy, sz) = self.msgHandler.parseSelectedMovementDatagram(
             dgi)
             dgi)
-        if last:
-            last.setPosHprScale(x, y, z, h, p, r, sx, sy, sz)
+        if getattr(builtins, 'last', None):
+            builtins.last.setPosHprScale(x, y, z, h, p, r, sx, sy, sz)
 
 
     def handleTimeData(self, dgi):
     def handleTimeData(self, dgi):
         """ Update cameraJig position to reflect latest position """
         """ Update cameraJig position to reflect latest position """
@@ -345,5 +361,5 @@ class ClusterServer(DirectObject.DirectObject):
         command = self.msgHandler.parseCommandStringDatagram(dgi)
         command = self.msgHandler.parseCommandStringDatagram(dgi)
         try:
         try:
             exec(command, __builtins__)
             exec(command, __builtins__)
-        except:
+        except Exception:
             pass
             pass

+ 1 - 1
direct/src/controls/BattleWalker.py

@@ -2,7 +2,7 @@
 from direct.showbase.InputStateGlobal import inputState
 from direct.showbase.InputStateGlobal import inputState
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 from direct.task.Task import Task
 from direct.task.Task import Task
-from panda3d.core import *
+from panda3d.core import ClockObject, Mat3, Point3, Vec3
 from . import GravityWalker
 from . import GravityWalker
 
 
 BattleStrafe = 0
 BattleStrafe = 0

+ 2 - 5
direct/src/controls/ControlManager.py

@@ -41,8 +41,6 @@ class ControlManager:
         #self.monitorTask = taskMgr.add(self.monitor, "ControlManager-%s"%(id(self)), priority=-1)
         #self.monitorTask = taskMgr.add(self.monitor, "ControlManager-%s"%(id(self)), priority=-1)
         self.forceAvJumpToken = None
         self.forceAvJumpToken = None
 
 
-
-
         if self.passMessagesThrough: # for not breaking toontown
         if self.passMessagesThrough: # for not breaking toontown
             ist=self.inputStateTokens
             ist=self.inputStateTokens
             ist.append(inputState.watchWithModifiers("forward", "arrow_up", inputSource=inputState.ArrowKeys))
             ist.append(inputState.watchWithModifiers("forward", "arrow_up", inputSource=inputState.ArrowKeys))
@@ -50,7 +48,6 @@ class ControlManager:
             ist.append(inputState.watchWithModifiers("turnLeft", "arrow_left", inputSource=inputState.ArrowKeys))
             ist.append(inputState.watchWithModifiers("turnLeft", "arrow_left", inputSource=inputState.ArrowKeys))
             ist.append(inputState.watchWithModifiers("turnRight", "arrow_right", inputSource=inputState.ArrowKeys))
             ist.append(inputState.watchWithModifiers("turnRight", "arrow_right", inputSource=inputState.ArrowKeys))
 
 
-
     def __str__(self):
     def __str__(self):
         return 'ControlManager: using \'%s\'' % self.currentControlsName
         return 'ControlManager: using \'%s\'' % self.currentControlsName
 
 
@@ -325,7 +322,7 @@ class ControlManager:
             self.WASDTurnTokens = (
             self.WASDTurnTokens = (
                 inputState.watchWithModifiers("turnLeft", "a", inputSource=inputState.WASD),
                 inputState.watchWithModifiers("turnLeft", "a", inputSource=inputState.WASD),
                 inputState.watchWithModifiers("turnRight", "d", inputSource=inputState.WASD),
                 inputState.watchWithModifiers("turnRight", "d", inputSource=inputState.WASD),
-                )
+            )
 
 
             inputState.set("turnLeft", slideLeftWASDSet, inputSource=inputState.WASD)
             inputState.set("turnLeft", slideLeftWASDSet, inputSource=inputState.WASD)
             inputState.set("turnRight", slideRightWASDSet, inputSource=inputState.WASD)
             inputState.set("turnRight", slideRightWASDSet, inputSource=inputState.WASD)
@@ -337,7 +334,7 @@ class ControlManager:
             self.WASDTurnTokens = (
             self.WASDTurnTokens = (
                 inputState.watchWithModifiers("slideLeft", "a", inputSource=inputState.WASD),
                 inputState.watchWithModifiers("slideLeft", "a", inputSource=inputState.WASD),
                 inputState.watchWithModifiers("slideRight", "d", inputSource=inputState.WASD),
                 inputState.watchWithModifiers("slideRight", "d", inputSource=inputState.WASD),
-                )
+            )
 
 
             inputState.set("slideLeft", turnLeftWASDSet, inputSource=inputState.WASD)
             inputState.set("slideLeft", turnLeftWASDSet, inputSource=inputState.WASD)
             inputState.set("slideRight", turnRightWASDSet, inputSource=inputState.WASD)
             inputState.set("slideRight", turnRightWASDSet, inputSource=inputState.WASD)

+ 1 - 1
direct/src/controls/DevWalker.py

@@ -22,7 +22,7 @@ from direct.showbase import DirectObject
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 from direct.task.Task import Task
 from direct.task.Task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
-from panda3d.core import *
+from panda3d.core import ClockObject, ConfigVariableBool, ConfigVariableDouble, Mat3, Point3, Vec3
 
 
 
 
 class DevWalker(DirectObject.DirectObject):
 class DevWalker(DirectObject.DirectObject):

+ 18 - 3
direct/src/controls/GravityWalker.py

@@ -22,9 +22,24 @@ from direct.showbase.InputStateGlobal import inputState
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 from direct.task.Task import Task
 from direct.task.Task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
-from direct.extensions_native import VBase3_extensions
-from direct.extensions_native import VBase4_extensions
-from panda3d.core import *
+from direct.extensions_native import VBase3_extensions # pylint: disable=unused-import
+from direct.extensions_native import VBase4_extensions # pylint: disable=unused-import
+from panda3d.core import (
+    BitMask32,
+    ClockObject,
+    CollisionHandlerEvent,
+    CollisionHandlerFluidPusher,
+    CollisionHandlerGravity,
+    CollisionHandlerPusher,
+    CollisionNode,
+    CollisionRay,
+    CollisionSphere,
+    CollisionTraverser,
+    ConfigVariableBool,
+    Mat3,
+    Point3,
+    Vec3,
+)
 import math
 import math
 
 
 
 

+ 14 - 3
direct/src/controls/InputState.py

@@ -8,36 +8,47 @@ from direct.showbase.MessengerGlobal import messenger
 class InputStateToken:
 class InputStateToken:
     _SerialGen = SerialNumGen()
     _SerialGen = SerialNumGen()
     Inval = 'invalidatedToken'
     Inval = 'invalidatedToken'
+
     def __init__(self, inputState):
     def __init__(self, inputState):
         self._id = InputStateToken._SerialGen.next()
         self._id = InputStateToken._SerialGen.next()
         self._hash = self._id
         self._hash = self._id
         self._inputState = inputState
         self._inputState = inputState
+
     def release(self):
     def release(self):
         # subclasses will override
         # subclasses will override
         assert False
         assert False
+
     def isValid(self):
     def isValid(self):
         return self._id != InputStateToken.Inval
         return self._id != InputStateToken.Inval
+
     def invalidate(self):
     def invalidate(self):
         self._id = InputStateToken.Inval
         self._id = InputStateToken.Inval
+
     def __hash__(self):
     def __hash__(self):
         return self._hash
         return self._hash
 
 
     #snake_case alias:
     #snake_case alias:
     is_valid = isValid
     is_valid = isValid
 
 
+
 class InputStateWatchToken(InputStateToken, DirectObject.DirectObject):
 class InputStateWatchToken(InputStateToken, DirectObject.DirectObject):
     def release(self):
     def release(self):
         self._inputState._ignore(self)
         self._inputState._ignore(self)
         self.ignoreAll()
         self.ignoreAll()
+
+
 class InputStateForceToken(InputStateToken):
 class InputStateForceToken(InputStateToken):
     def release(self):
     def release(self):
         self._inputState._unforce(self)
         self._inputState._unforce(self)
 
 
+
 class InputStateTokenGroup:
 class InputStateTokenGroup:
     def __init__(self):
     def __init__(self):
         self._tokens = []
         self._tokens = []
+
     def addToken(self, token):
     def addToken(self, token):
         self._tokens.append(token)
         self._tokens.append(token)
+
     def release(self):
     def release(self):
         for token in self._tokens:
         for token in self._tokens:
             token.release()
             token.release()
@@ -46,6 +57,7 @@ class InputStateTokenGroup:
     #snake_case alias:
     #snake_case alias:
     add_token = addToken
     add_token = addToken
 
 
+
 class InputState(DirectObject.DirectObject):
 class InputState(DirectObject.DirectObject):
     """
     """
     InputState is for tracking the on/off state of some events.
     InputState is for tracking the on/off state of some events.
@@ -190,7 +202,6 @@ class InputState(DirectObject.DirectObject):
         # input state simply because we're not looking at it anymore.
         # input state simply because we're not looking at it anymore.
         # self.set(name, False, inputSource)
         # self.set(name, False, inputSource)
 
 
-
     def force(self, name, value, inputSource):
     def force(self, name, value, inputSource):
         """
         """
         Force isSet(name) to return 'value'.
         Force isSet(name) to return 'value'.
@@ -213,7 +224,7 @@ class InputState(DirectObject.DirectObject):
                 self.notify.error(
                 self.notify.error(
                     "%s is trying to force '%s' to ON, but '%s' is already being forced OFF by %s" %
                     "%s is trying to force '%s' to ON, but '%s' is already being forced OFF by %s" %
                     (inputSource, name, name, self._forcingOff[name])
                     (inputSource, name, name, self._forcingOff[name])
-                    )
+                )
             self._forcingOn.setdefault(name, set())
             self._forcingOn.setdefault(name, set())
             self._forcingOn[name].add(inputSource)
             self._forcingOn[name].add(inputSource)
         else:
         else:
@@ -221,7 +232,7 @@ class InputState(DirectObject.DirectObject):
                 self.notify.error(
                 self.notify.error(
                     "%s is trying to force '%s' to OFF, but '%s' is already being forced ON by %s" %
                     "%s is trying to force '%s' to OFF, but '%s' is already being forced ON by %s" %
                     (inputSource, name, name, self._forcingOn[name])
                     (inputSource, name, name, self._forcingOn[name])
-                    )
+                )
             self._forcingOff.setdefault(name, set())
             self._forcingOff.setdefault(name, set())
             self._forcingOff[name].add(inputSource)
             self._forcingOff[name].add(inputSource)
         return token
         return token

+ 14 - 1
direct/src/controls/NonPhysicsWalker.py

@@ -23,7 +23,20 @@ from direct.showbase.InputStateGlobal import inputState
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 from direct.task.Task import Task
 from direct.task.Task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
-from panda3d.core import *
+from panda3d.core import (
+    BitMask32,
+    ClockObject,
+    CollisionHandlerFloor,
+    CollisionHandlerPusher,
+    CollisionNode,
+    CollisionRay,
+    CollisionSphere,
+    CollisionTraverser,
+    ConfigVariableBool,
+    Mat3,
+    Point3,
+    Vec3,
+)
 
 
 class NonPhysicsWalker(DirectObject.DirectObject):
 class NonPhysicsWalker(DirectObject.DirectObject):
     notify = DirectNotifyGlobal.directNotify.newCategory("NonPhysicsWalker")
     notify = DirectNotifyGlobal.directNotify.newCategory("NonPhysicsWalker")

+ 7 - 1
direct/src/controls/ObserverWalker.py

@@ -16,7 +16,13 @@ although it does send messages that allow a listener to play sounds or
 animations based on walker events.
 animations based on walker events.
 """
 """
 
 
-from panda3d.core import *
+from panda3d.core import (
+    BitMask32,
+    CollisionHandlerPusher,
+    CollisionNode,
+    CollisionSphere,
+    CollisionTraverser,
+)
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 from . import NonPhysicsWalker
 from . import NonPhysicsWalker
 
 

+ 30 - 6
direct/src/controls/PhysicsWalker.py

@@ -23,15 +23,39 @@ from direct.showbase.InputStateGlobal import inputState
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 from direct.task.Task import Task
 from direct.task.Task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
-from direct.extensions_native import Mat3_extensions
-from direct.extensions_native import VBase3_extensions
-from direct.extensions_native import VBase4_extensions
-from panda3d.core import *
-from panda3d.physics import *
+from direct.extensions_native import Mat3_extensions # pylint: disable=unused-import
+from direct.extensions_native import VBase3_extensions # pylint: disable=unused-import
+from direct.extensions_native import VBase4_extensions # pylint: disable=unused-import
+from panda3d.core import (
+    BitMask32,
+    ClockObject,
+    CollisionHandlerFloor,
+    CollisionHandlerQueue,
+    CollisionNode,
+    CollisionRay,
+    CollisionSphere,
+    CollisionTraverser,
+    ConfigVariableBool,
+    LRotationf,
+    Mat3,
+    NodePath,
+    Point3,
+    Vec3,
+)
+from panda3d.physics import (
+    ActorNode,
+    ForceNode,
+    LinearEulerIntegrator,
+    LinearFrictionForce,
+    LinearVectorForce,
+    PhysicsCollisionHandler,
+    PhysicsManager,
+)
 import math
 import math
 
 
 #import LineStream
 #import LineStream
 
 
+
 class PhysicsWalker(DirectObject.DirectObject):
 class PhysicsWalker(DirectObject.DirectObject):
 
 
     notify = DirectNotifyGlobal.directNotify.newCategory("PhysicsWalker")
     notify = DirectNotifyGlobal.directNotify.newCategory("PhysicsWalker")
@@ -523,7 +547,7 @@ class PhysicsWalker(DirectObject.DirectObject):
                 onScreenDebug.add("highMark", "% 10.4f"%(self.highMark,))
                 onScreenDebug.add("highMark", "% 10.4f"%(self.highMark,))
         #if airborneHeight < 0.1: #contact!=Vec3.zero():
         #if airborneHeight < 0.1: #contact!=Vec3.zero():
         if (airborneHeight > self.avatarRadius*0.5
         if (airborneHeight > self.avatarRadius*0.5
-                or physObject.getVelocity().getZ() > 0.0
+                    or physObject.getVelocity().getZ() > 0.0
                 ): # Check stair angles before changing this.
                 ): # Check stair angles before changing this.
             # ...the avatar is airborne (maybe a lot or a tiny amount).
             # ...the avatar is airborne (maybe a lot or a tiny amount).
             self.isAirborne = 1
             self.isAirborne = 1

+ 5 - 2
direct/src/controls/TwoDWalker.py

@@ -2,9 +2,12 @@
 TwoDWalker.py is for controlling the avatars in a 2D scroller game environment.
 TwoDWalker.py is for controlling the avatars in a 2D scroller game environment.
 """
 """
 
 
-from .GravityWalker import *
+from .GravityWalker import GravityWalker
+from direct.directnotify.DirectNotifyGlobal import directNotify
+from direct.showbase.InputStateGlobal import inputState
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
-from panda3d.core import ConfigVariableBool
+from direct.task.Task import Task
+from panda3d.core import ConfigVariableBool, Vec3
 
 
 
 
 class TwoDWalker(GravityWalker):
 class TwoDWalker(GravityWalker):

+ 1 - 1
direct/src/dcparser/dcClassParameter.h

@@ -37,7 +37,7 @@ PUBLISHED:
   const DCClass *get_class() const;
   const DCClass *get_class() const;
 
 
 public:
 public:
-  virtual DCPackerInterface *get_nested_field(int n) const;
+  virtual DCPackerInterface *get_nested_field(int n) const final;
 
 
   virtual void output_instance(std::ostream &out, bool brief, const std::string &prename,
   virtual void output_instance(std::ostream &out, bool brief, const std::string &prename,
                                const std::string &name, const std::string &postname) const;
                                const std::string &name, const std::string &postname) const;

+ 1 - 2
direct/src/directbase/TestStart.py

@@ -1,8 +1,7 @@
 print('TestStart: Starting up test environment.')
 print('TestStart: Starting up test environment.')
 
 
-from panda3d.core import *
+import direct.showbase.PythonUtil  # pylint: disable=unused-import
 
 
-from direct.showbase.PythonUtil import *
 from direct.showbase import ShowBase
 from direct.showbase import ShowBase
 base = ShowBase.ShowBase()
 base = ShowBase.ShowBase()
 
 

+ 1 - 2
direct/src/directbase/ThreeUpStart.py

@@ -1,9 +1,8 @@
 
 
 print('ThreeUpStart: Starting up environment.')
 print('ThreeUpStart: Starting up environment.')
 
 
-from panda3d.core import *
+import direct.showbase.PythonUtil  # pylint: disable=unused-import
 
 
-from direct.showbase.PythonUtil import *
 from direct.showbase import ThreeUpShow
 from direct.showbase import ThreeUpShow
 
 
 base = ThreeUpShow.ThreeUpShow()
 base = ThreeUpShow.ThreeUpShow()

+ 15 - 8
direct/src/directdevices/DirectDeviceManager.py

@@ -1,8 +1,15 @@
 """Class used to create and control VRPN devices."""
 """Class used to create and control VRPN devices."""
 
 
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
-from panda3d.core import *
-from panda3d.vrpn import *
+from panda3d.core import (
+    AnalogNode,
+    ButtonNode,
+    ConfigVariableDouble,
+    ConfigVariableString,
+    DialNode,
+    TrackerNode,
+)
+from panda3d.vrpn import VrpnClient
 
 
 ANALOG_MIN = -0.95
 ANALOG_MIN = -0.95
 ANALOG_MAX = 0.95
 ANALOG_MAX = 0.95
@@ -52,7 +59,7 @@ class DirectButtons(ButtonNode, DirectObject):
         # Attach node to data graph
         # Attach node to data graph
         try:
         try:
             self._base = base
             self._base = base
-        except:
+        except NameError:
             self._base = simbase
             self._base = simbase
         self.nodePath = self._base.dataRoot.attachNewNode(self)
         self.nodePath = self._base.dataRoot.attachNewNode(self)
 
 
@@ -101,7 +108,7 @@ class DirectAnalogs(AnalogNode, DirectObject):
         # Attach node to data graph
         # Attach node to data graph
         try:
         try:
             self._base = base
             self._base = base
-        except:
+        except NameError:
             self._base = simbase
             self._base = simbase
         self.nodePath = self._base.dataRoot.attachNewNode(self)
         self.nodePath = self._base.dataRoot.attachNewNode(self)
 
 
@@ -169,7 +176,7 @@ class DirectAnalogs(AnalogNode, DirectObject):
 
 
     def normalizeChannel(self, chan, minVal = -1, maxVal = 1, sf = 1.0):
     def normalizeChannel(self, chan, minVal = -1, maxVal = 1, sf = 1.0):
         try:
         try:
-            return self.normalize(self[chan], minVal, maxVal, sfx)
+            return self.normalize(self[chan], minVal, maxVal, sf)
         except IndexError:
         except IndexError:
             return 0.0
             return 0.0
 
 
@@ -199,7 +206,7 @@ class DirectTracker(TrackerNode, DirectObject):
         # Attach node to data graph
         # Attach node to data graph
         try:
         try:
             self._base = base
             self._base = base
-        except:
+        except NameError:
             self._base = simbase
             self._base = simbase
         self.nodePath = self._base.dataRoot.attachNewNode(self)
         self.nodePath = self._base.dataRoot.attachNewNode(self)
 
 
@@ -231,7 +238,7 @@ class DirectDials(DialNode, DirectObject):
         # Attach node to data graph
         # Attach node to data graph
         try:
         try:
             self._base = base
             self._base = base
-        except:
+        except NameError:
             self._base = simbase
             self._base = simbase
         self.nodePath = self._base.dataRoot.attachNewNode(self)
         self.nodePath = self._base.dataRoot.attachNewNode(self)
 
 
@@ -282,7 +289,7 @@ class DirectTimecodeReader(AnalogNode, DirectObject):
         # Attach node to data graph
         # Attach node to data graph
         try:
         try:
             self._base = base
             self._base = base
-        except:
+        except NameError:
             self._base = simbase
             self._base = simbase
         self.nodePath = self._base.dataRoot.attachNewNode(self)
         self.nodePath = self._base.dataRoot.attachNewNode(self)
 
 

+ 2 - 1
direct/src/directdevices/DirectFastrak.py

@@ -1,8 +1,9 @@
 """ Class used to create and control radamec device """
 """ Class used to create and control radamec device """
+from panda3d.core import Vec3
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 from direct.task.Task import Task
 from direct.task.Task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
-from .DirectDeviceManager import *
+from .DirectDeviceManager import DirectDeviceManager
 
 
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 
 

+ 29 - 29
direct/src/directdevices/DirectJoybox.py

@@ -1,11 +1,11 @@
 """ Class used to create and control joybox device """
 """ Class used to create and control joybox device """
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
-from .DirectDeviceManager import *
-from direct.directtools.DirectUtil import *
+from .DirectDeviceManager import ANALOG_DEADBAND, ANALOG_MAX, ANALOG_MIN, DirectDeviceManager
+from direct.directtools.DirectUtil import CLAMP
 from direct.gui import OnscreenText
 from direct.gui import OnscreenText
 from direct.task import Task
 from direct.task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
-from panda3d.core import ClockObject
+from panda3d.core import ButtonRegistry, ButtonThrower, ClockObject, NodePath, VBase3, Vec3
 
 
 import math
 import math
 
 
@@ -35,6 +35,7 @@ JOYBOX_RANGE = JOYBOX_MAX - JOYBOX_MIN
 
 
 JOYBOX_TREAD_SEPERATION = 1.0
 JOYBOX_TREAD_SEPERATION = 1.0
 
 
+
 class DirectJoybox(DirectObject):
 class DirectJoybox(DirectObject):
     joyboxCount = 0
     joyboxCount = 0
     xyzMultiplier = 1.0
     xyzMultiplier = 1.0
@@ -87,12 +88,10 @@ class DirectJoybox(DirectObject):
         # Spawn update task
         # Spawn update task
         self.enable()
         self.enable()
 
 
-
     def setHeadingNodePath(self,np):
     def setHeadingNodePath(self,np):
 
 
         self.headingNP = np
         self.headingNP = np
 
 
-
     def enable(self):
     def enable(self):
         # Kill existing task
         # Kill existing task
         self.disable()
         self.disable()
@@ -126,18 +125,25 @@ class DirectJoybox(DirectObject):
 
 
     def getNodePath(self):
     def getNodePath(self):
         return self.nodePath
         return self.nodePath
+
     def setRefCS(self, refCS):
     def setRefCS(self, refCS):
         self.refCS = refCS
         self.refCS = refCS
+
     def getRefCS(self):
     def getRefCS(self):
         return self.refCS
         return self.refCS
+
     def getEventName(self, index):
     def getEventName(self, index):
         return self.name + '-button-' + repr(index)
         return self.name + '-button-' + repr(index)
+
     def setXyzMultiplier(self, multiplier):
     def setXyzMultiplier(self, multiplier):
         DirectJoybox.xyzMultiplier = multiplier
         DirectJoybox.xyzMultiplier = multiplier
+
     def getXyzMultiplier(self):
     def getXyzMultiplier(self):
         return DirectJoybox.xyzMultiplier
         return DirectJoybox.xyzMultiplier
+
     def setHprMultiplier(self, multiplier):
     def setHprMultiplier(self, multiplier):
         DirectJoybox.hprMultiplier = multiplier
         DirectJoybox.hprMultiplier = multiplier
+
     def getHprMultiplier(self):
     def getHprMultiplier(self):
         return DirectJoybox.hprMultiplier
         return DirectJoybox.hprMultiplier
 
 
@@ -193,6 +199,7 @@ class DirectJoybox(DirectObject):
 
 
     def acceptSwitchModeEvent(self, button = R_UPPER):
     def acceptSwitchModeEvent(self, button = R_UPPER):
         self.accept(self.getEventName(button), self.switchMode)
         self.accept(self.getEventName(button), self.switchMode)
+
     def ignoreSwitchModeEvent(self, button = R_UPPER):
     def ignoreSwitchModeEvent(self, button = R_UPPER):
         self.ignore(self.getEventName(button))
         self.ignore(self.getEventName(button))
 
 
@@ -208,7 +215,7 @@ class DirectJoybox(DirectObject):
             pass
             pass
 
 
     def showMode(self, modeText):
     def showMode(self, modeText):
-        def hideText(state, s = self):
+        def hideText(state, s=self):
             s.readout.setText('')
             s.readout.setText('')
             return Task.done
             return Task.done
         taskMgr.remove(self.name + '-showMode')
         taskMgr.remove(self.name + '-showMode')
@@ -220,6 +227,7 @@ class DirectJoybox(DirectObject):
     def acceptUprightCameraEvent(self, button = L_UPPER):
     def acceptUprightCameraEvent(self, button = L_UPPER):
         self.accept(self.getEventName(button),
         self.accept(self.getEventName(button),
                     base.direct.cameraControl.orbitUprightCam)
                     base.direct.cameraControl.orbitUprightCam)
+
     def ignoreUprightCameraEvent(self, button = L_UPPER):
     def ignoreUprightCameraEvent(self, button = L_UPPER):
         self.ignore(self.getEventName(button))
         self.ignore(self.getEventName(button))
 
 
@@ -230,29 +238,29 @@ class DirectJoybox(DirectObject):
         self.showMode(self.modeName)
         self.showMode(self.modeName)
         self.enable()
         self.enable()
 
 
-
-    def setUseHeadingNP(self,enabled):
-
+    def setUseHeadingNP(self, enabled):
         self.useHeadingNP = enabled
         self.useHeadingNP = enabled
 
 
-    def setRotateInPlace(self,enabled):
-
+    def setRotateInPlace(self, enabled):
         self.rotateInPlace = enabled
         self.rotateInPlace = enabled
 
 
     def joyboxFly(self):
     def joyboxFly(self):
         # Do nothing if no nodePath selected
         # Do nothing if no nodePath selected
         if self.nodePath is None:
         if self.nodePath is None:
             return
             return
+
         hprScale = ((self.aList[L_SLIDE] + 1.0) *
         hprScale = ((self.aList[L_SLIDE] + 1.0) *
                     50.0 * DirectJoybox.hprMultiplier)
                     50.0 * DirectJoybox.hprMultiplier)
         posScale = ((self.aList[R_SLIDE] + 1.0) *
         posScale = ((self.aList[R_SLIDE] + 1.0) *
                     50.0 * DirectJoybox.xyzMultiplier)
                     50.0 * DirectJoybox.xyzMultiplier)
-        def getAxisVal(index, s = self):
+
+        def getAxisVal(index, s=self):
             try:
             try:
                 return s.aList[s.mapping[index]]
                 return s.aList[s.mapping[index]]
             except IndexError:
             except IndexError:
                 # If it is a null axis return 0
                 # If it is a null axis return 0
                 return 0.0
                 return 0.0
+
         x = getAxisVal(0) * self.modifier[0]
         x = getAxisVal(0) * self.modifier[0]
         y = getAxisVal(1) * self.modifier[1]
         y = getAxisVal(1) * self.modifier[1]
         z = getAxisVal(2) * self.modifier[2]
         z = getAxisVal(2) * self.modifier[2]
@@ -262,13 +270,13 @@ class DirectJoybox(DirectObject):
         p = getAxisVal(4) * self.modifier[4]
         p = getAxisVal(4) * self.modifier[4]
         r = getAxisVal(5) * self.modifier[5]
         r = getAxisVal(5) * self.modifier[5]
         hpr = Vec3(h, p, r) * (hprScale * self.deltaTime)
         hpr = Vec3(h, p, r) * (hprScale * self.deltaTime)
+
         # if we are using a heading nodepath, we want
         # if we are using a heading nodepath, we want
         # to drive in the direction we are facing,
         # to drive in the direction we are facing,
         # however, we don't want the z component to change
         # however, we don't want the z component to change
         if self.useHeadingNP and self.headingNP is not None:
         if self.useHeadingNP and self.headingNP is not None:
             oldZ = pos.getZ()
             oldZ = pos.getZ()
-            pos = self.nodePath.getRelativeVector(self.headingNP,
-                                                  pos)
+            pos = self.nodePath.getRelativeVector(self.headingNP, pos)
             pos.setZ(oldZ)
             pos.setZ(oldZ)
             # if we are using a heading NP we might want to rotate
             # if we are using a heading NP we might want to rotate
             # in place around that NP
             # in place around that NP
@@ -282,7 +290,6 @@ class DirectJoybox(DirectObject):
                 self.nodePath.wrtReparentTo(parent)
                 self.nodePath.wrtReparentTo(parent)
                 hpr = Vec3(0,0,0)
                 hpr = Vec3(0,0,0)
 
 
-
         self.nodePath.setPosHpr(self.nodePath, pos, hpr)
         self.nodePath.setPosHpr(self.nodePath, pos, hpr)
 
 
     def joeMode(self):
     def joeMode(self):
@@ -291,25 +298,23 @@ class DirectJoybox(DirectObject):
         self.modifier = [1, 1, 1, -1, -1, 0]
         self.modifier = [1, 1, 1, -1, -1, 0]
         self.setMode(self.joyboxFly, 'Joe Mode')
         self.setMode(self.joyboxFly, 'Joe Mode')
 
 
-
     def basicMode(self):
     def basicMode(self):
         self.mapping = [NULL_AXIS, R_FWD_BACK, NULL_AXIS,
         self.mapping = [NULL_AXIS, R_FWD_BACK, NULL_AXIS,
                         R_LEFT_RIGHT, NULL_AXIS, NULL_AXIS]
                         R_LEFT_RIGHT, NULL_AXIS, NULL_AXIS]
-        self.modifier = [0,1,0,-1,0,0]
-        self.setMode(self.joyboxFly,'Basic Mode')
+        self.modifier = [0, 1, 0, -1, 0, 0]
+        self.setMode(self.joyboxFly, 'Basic Mode')
 
 
     def fpsMode(self):
     def fpsMode(self):
         self.mapping = [L_LEFT_RIGHT,R_FWD_BACK,L_FWD_BACK,
         self.mapping = [L_LEFT_RIGHT,R_FWD_BACK,L_FWD_BACK,
                         R_LEFT_RIGHT, NULL_AXIS, NULL_AXIS]
                         R_LEFT_RIGHT, NULL_AXIS, NULL_AXIS]
-        self.modifier = [1,1,1,-1,0,0]
-        self.setMode(self.joyboxFly,'FPS Mode')
+        self.modifier = [1, 1, 1, -1, 0, 0]
+        self.setMode(self.joyboxFly, 'FPS Mode')
 
 
     def tankMode(self):
     def tankMode(self):
-        self.setMode(self.tankFly,'Tank Mode')
+        self.setMode(self.tankFly, 'Tank Mode')
 
 
     def nullMode(self):
     def nullMode(self):
-        self.setMode(self.nullFly,'Null Mode')
-
+        self.setMode(self.nullFly, 'Null Mode')
 
 
     def lucMode(self):
     def lucMode(self):
         self.mapping = [R_LEFT_RIGHT, R_FWD_BACK, L_FWD_BACK,
         self.mapping = [R_LEFT_RIGHT, R_FWD_BACK, L_FWD_BACK,
@@ -362,7 +367,6 @@ class DirectJoybox(DirectObject):
     def spaceMode(self):
     def spaceMode(self):
         self.setMode(self.spaceFly, 'Space Mode')
         self.setMode(self.spaceFly, 'Space Mode')
 
 
-
     def nullFly(self):
     def nullFly(self):
         return
         return
 
 
@@ -384,10 +388,6 @@ class DirectJoybox(DirectObject):
         self.nodePath.setH(self.nodePath,dh)
         self.nodePath.setH(self.nodePath,dh)
         self.nodePath.setY(self.nodePath,dy)
         self.nodePath.setY(self.nodePath,dy)
 
 
-
-
-
-
     def spaceFly(self):
     def spaceFly(self):
         # Do nothing if no nodePath selected
         # Do nothing if no nodePath selected
         if self.nodePath is None:
         if self.nodePath is None:
@@ -498,9 +498,9 @@ class DirectJoybox(DirectObject):
         # Restore the original hpr of the orbiter
         # Restore the original hpr of the orbiter
         self.nodePath.setHpr(self.tempCS, 0, 0, 0)
         self.nodePath.setHpr(self.tempCS, 0, 0, 0)
 
 
-
     # We need to override the DirectAnalog normalizeChannel to
     # We need to override the DirectAnalog normalizeChannel to
     # correct the ranges of the two twist axes of the joybox.
     # correct the ranges of the two twist axes of the joybox.
+
     def normalizeChannel(self, chan, minVal = -1, maxVal = 1):
     def normalizeChannel(self, chan, minVal = -1, maxVal = 1):
         try:
         try:
             if chan == L_TWIST or chan == R_TWIST:
             if chan == L_TWIST or chan == R_TWIST:

+ 1 - 2
direct/src/directdevices/DirectRadamec.py

@@ -1,9 +1,8 @@
 """ Class used to create and control radamec device """
 """ Class used to create and control radamec device """
-from math import *
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 from direct.task.Task import Task
 from direct.task.Task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
-from .DirectDeviceManager import *
+from .DirectDeviceManager import DirectDeviceManager
 
 
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 
 

+ 2 - 2
direct/src/directnotify/DirectNotify.py

@@ -5,6 +5,7 @@ DirectNotify module: this module contains the DirectNotify class
 from . import Notifier
 from . import Notifier
 from . import Logger
 from . import Logger
 
 
+
 class DirectNotify:
 class DirectNotify:
     """
     """
     DirectNotify class: this class contains methods for creating
     DirectNotify class: this class contains methods for creating
@@ -15,7 +16,7 @@ class DirectNotify:
         """
         """
         DirectNotify class keeps a dictionary of Notfiers
         DirectNotify class keeps a dictionary of Notfiers
         """
         """
-        self.__categories = { }
+        self.__categories = {}
         # create a default log file
         # create a default log file
         self.logger = Logger.Logger()
         self.logger = Logger.Logger()
 
 
@@ -100,7 +101,6 @@ class DirectNotify:
             print("DirectNotify: unknown notify level: " + str(level)
             print("DirectNotify: unknown notify level: " + str(level)
                    + " for category: " + str(categoryName))
                    + " for category: " + str(categoryName))
 
 
-
     def setDconfigLevels(self):
     def setDconfigLevels(self):
         for categoryName in self.getCategories():
         for categoryName in self.getCategories():
             self.setDconfigLevel(categoryName)
             self.setDconfigLevel(categoryName)

+ 13 - 13
direct/src/directnotify/Notifier.py

@@ -126,10 +126,10 @@ class Notifier:
         Exception: error
         Exception: error
         """
         """
         message = str(errorString)
         message = str(errorString)
-        if Notifier.showTime.getValue():
-            string = (self.getTime() + str(exception) + ": " + self.__name + "(error): " + message)
+        if Notifier.showTime:
+            string = f'{self.getTime()}{exception!s}: {self.__name}(error): {message}'
         else:
         else:
-            string = (str(exception) + ": " + self.__name + "(error): " + message)
+            string = f'{exception!s}: {self.__name}(error): {message}'
         self.__log(string)
         self.__log(string)
         raise exception(errorString)
         raise exception(errorString)
 
 
@@ -140,10 +140,10 @@ class Notifier:
         """
         """
         if self.__warning:
         if self.__warning:
             message = str(warningString)
             message = str(warningString)
-            if Notifier.showTime.getValue():
-                string = (self.getTime() + self.__name + '(warning): ' + message)
+            if Notifier.showTime:
+                string = f'{self.getTime()}{self.__name}(warning): {message}'
             else:
             else:
-                string = (":" + self.__name + '(warning): ' + message)
+                string = f':{self.__name}(warning): {message}'
             self.__log(string)
             self.__log(string)
             self.__print(string)
             self.__print(string)
         return 1 # to allow assert myNotify.warning("blah")
         return 1 # to allow assert myNotify.warning("blah")
@@ -167,10 +167,10 @@ class Notifier:
         """
         """
         if self.__debug:
         if self.__debug:
             message = str(debugString)
             message = str(debugString)
-            if Notifier.showTime.getValue():
-                string = (self.getTime() + self.__name + '(debug): ' + message)
+            if Notifier.showTime:
+                string = f'{self.getTime()}{self.__name}(debug): {message}'
             else:
             else:
-                string = (':' + self.__name + '(debug): ' + message)
+                string = f':{self.__name}(debug): {message}'
             self.__log(string)
             self.__log(string)
             self.__print(string)
             self.__print(string)
         return 1 # to allow assert myNotify.debug("blah")
         return 1 # to allow assert myNotify.debug("blah")
@@ -194,10 +194,10 @@ class Notifier:
         """
         """
         if self.__info:
         if self.__info:
             message = str(infoString)
             message = str(infoString)
-            if Notifier.showTime.getValue():
-                string = (self.getTime() + self.__name + ': ' + message)
+            if Notifier.showTime:
+                string = f'{self.getTime()}{self.__name}: {message}'
             else:
             else:
-                string = (':' + self.__name + ': ' + message)
+                string = f':{self.__name}: {message}'
             self.__log(string)
             self.__log(string)
             self.__print(string)
             self.__print(string)
         return 1 # to allow assert myNotify.info("blah")
         return 1 # to allow assert myNotify.info("blah")
@@ -271,7 +271,7 @@ class Notifier:
                         state = "%s, %s"%(state, stateObj.getName())
                         state = "%s, %s"%(state, stateObj.getName())
 
 
                 if hasattr(obj, 'doId'):
                 if hasattr(obj, 'doId'):
-                    doId = " doId:%s"%(obj.doId,)
+                    doId = f" doId:{obj.doId}"
             #if type(obj) == types.ClassType:
             #if type(obj) == types.ClassType:
             #    name = "%s."%(obj.__class__.__name__,)
             #    name = "%s."%(obj.__class__.__name__,)
             string = ":%s:%s [%-7s] id(%s)%s %s"%(
             string = ":%s:%s [%-7s] id(%s)%s %s"%(

+ 9 - 1
direct/src/directscripts/eggcacher.py

@@ -11,7 +11,15 @@
 import os
 import os
 import sys
 import sys
 import gc
 import gc
-from panda3d.core import *
+from panda3d.core import (
+    BamCache,
+    ExecutionEnvironment,
+    Filename,
+    Loader,
+    LoaderOptions,
+    ModelPool,
+    TexturePool,
+)
 
 
 class EggCacher:
 class EggCacher:
     def __init__(self, args):
     def __init__(self, args):

+ 8 - 3
direct/src/directscripts/extract_docs.py

@@ -16,11 +16,11 @@ from panda3d.interrogatedb import *
 
 
 
 
 if 'interrogate_element_is_sequence' not in globals():
 if 'interrogate_element_is_sequence' not in globals():
-    def interrogate_element_is_sequence(element):
+    def interrogate_element_is_sequence(element): # pylint: disable=function-redefined
         return False
         return False
 
 
 if 'interrogate_element_is_mapping' not in globals():
 if 'interrogate_element_is_mapping' not in globals():
-    def interrogate_element_is_mapping(element):
+    def interrogate_element_is_mapping(element): # pylint: disable=function-redefined
         return False
         return False
 
 
 
 
@@ -65,6 +65,7 @@ def comment(code):
     else:
     else:
         return ''
         return ''
 
 
+
 def block_comment(code):
 def block_comment(code):
     code = code.strip()
     code = code.strip()
 
 
@@ -77,6 +78,7 @@ def block_comment(code):
 
 
     return code
     return code
 
 
+
 def translateFunctionName(name):
 def translateFunctionName(name):
     if name.startswith("__"):
     if name.startswith("__"):
         return name
         return name
@@ -93,6 +95,7 @@ def translateFunctionName(name):
             new += i[0].upper() + i[1:]
             new += i[0].upper() + i[1:]
     return new
     return new
 
 
+
 def translateTypeName(name, mangle=True):
 def translateTypeName(name, mangle=True):
     # Equivalent to C++ classNameFromCppName
     # Equivalent to C++ classNameFromCppName
     class_name = ""
     class_name = ""
@@ -115,6 +118,7 @@ def translateTypeName(name, mangle=True):
 
 
     return class_name
     return class_name
 
 
+
 def translated_type_name(type, scoped=True):
 def translated_type_name(type, scoped=True):
     while interrogate_type_is_wrapped(type):
     while interrogate_type_is_wrapped(type):
         if interrogate_type_is_const(type):
         if interrogate_type_is_const(type):
@@ -205,7 +209,7 @@ def processFunction(handle, function, isConstructor = False):
 
 
 def processType(handle, type):
 def processType(handle, type):
     typename = translated_type_name(type, scoped=False)
     typename = translated_type_name(type, scoped=False)
-    derivations = [ translated_type_name(interrogate_type_get_derivation(type, n)) for n in range(interrogate_type_number_of_derivations(type)) ]
+    derivations = [translated_type_name(interrogate_type_get_derivation(type, n)) for n in range(interrogate_type_number_of_derivations(type))]
 
 
     if interrogate_type_has_comment(type):
     if interrogate_type_has_comment(type):
         print(block_comment(interrogate_type_comment(type)), file=handle)
         print(block_comment(interrogate_type_comment(type)), file=handle)
@@ -258,6 +262,7 @@ def processType(handle, type):
 
 
     print("};", file=handle)
     print("};", file=handle)
 
 
+
 def processModule(handle, package):
 def processModule(handle, package):
     print("Processing module %s" % (package))
     print("Processing module %s" % (package))
     print("namespace %s {" % package, file=handle)
     print("namespace %s {" % package, file=handle)

+ 32 - 31
direct/src/directtools/DirectCameraControl.py

@@ -1,7 +1,9 @@
+import math
+from panda3d.core import BitMask32, Mat4, NodePath, Point3, VBase3, Vec3, Vec4, rad2Deg
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
-from .DirectUtil import *
-from .DirectGeometry import *
-from .DirectGlobals import *
+from .DirectUtil import CLAMP, useDirectRenderStyle
+from .DirectGeometry import getCrankAngle, getScreenXY
+from . import DirectGlobals as DG
 from .DirectSelection import SelectionRay
 from .DirectSelection import SelectionRay
 from direct.interval.IntervalGlobal import Sequence, Func
 from direct.interval.IntervalGlobal import Sequence, Func
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
@@ -12,6 +14,7 @@ CAM_MOVE_DURATION = 1.2
 COA_MARKER_SF = 0.0075
 COA_MARKER_SF = 0.0075
 Y_AXIS = Vec3(0, 1, 0)
 Y_AXIS = Vec3(0, 1, 0)
 
 
+
 class DirectCameraControl(DirectObject):
 class DirectCameraControl(DirectObject):
 
 
     notify = DirectNotifyGlobal.directNotify.newCategory('DirectCameraControl')
     notify = DirectNotifyGlobal.directNotify.newCategory('DirectCameraControl')
@@ -48,7 +51,7 @@ class DirectCameraControl(DirectObject):
             ['DIRECT-mouse2Up', self.mouseFlyStop],
             ['DIRECT-mouse2Up', self.mouseFlyStop],
             ['DIRECT-mouse3', self.mouseDollyStart],
             ['DIRECT-mouse3', self.mouseDollyStart],
             ['DIRECT-mouse3Up', self.mouseDollyStop],
             ['DIRECT-mouse3Up', self.mouseDollyStop],
-            ]
+        ]
 
 
         # [gjeon] moved all of the hotkeys to single place for easy remapping
         # [gjeon] moved all of the hotkeys to single place for easy remapping
 ##         self.keyEvents = [
 ##         self.keyEvents = [
@@ -99,7 +102,7 @@ class DirectCameraControl(DirectObject):
             ['DIRECT-removeManipulateCameraTask', self.removeManipulateCameraTask],
             ['DIRECT-removeManipulateCameraTask', self.removeManipulateCameraTask],
             ['DIRECT-zoomInCam', self.zoomCam, 0.5, t],
             ['DIRECT-zoomInCam', self.zoomCam, 0.5, t],
             ['DIRECT-zoomOutCam', self.zoomCam, -2.0, t],
             ['DIRECT-zoomOutCam', self.zoomCam, -2.0, t],
-            ]
+        ]
         # set this to true to prevent the camera from rolling
         # set this to true to prevent the camera from rolling
         self.lockRoll = False
         self.lockRoll = False
         # NIK - flag to determine whether to use maya camera controls
         # NIK - flag to determine whether to use maya camera controls
@@ -218,9 +221,9 @@ class DirectCameraControl(DirectObject):
             # Allow intersection with unpickable objects
             # Allow intersection with unpickable objects
             # And then spawn task to determine mouse mode
             # And then spawn task to determine mouse mode
             # Don't intersect with hidden or backfacing objects
             # Don't intersect with hidden or backfacing objects
-            skipFlags = SKIP_HIDDEN | SKIP_BACKFACE
+            skipFlags = DG.SKIP_HIDDEN | DG.SKIP_BACKFACE
             # Skip camera (and its children), unless control key is pressed
             # Skip camera (and its children), unless control key is pressed
-            skipFlags |= SKIP_CAMERA * (1 - base.getControl())
+            skipFlags |= DG.SKIP_CAMERA * (1 - base.getControl())
             self.computeCOA(base.direct.iRay.pickGeom(skipFlags = skipFlags))
             self.computeCOA(base.direct.iRay.pickGeom(skipFlags = skipFlags))
             # Record reference point
             # Record reference point
             self.coaMarkerRef.setPosHprScale(base.cam, 0, 0, 0, 0, 0, 0, 1, 1, 1)
             self.coaMarkerRef.setPosHprScale(base.cam, 0, 0, 0, 0, 0, 0, 1, 1, 1)
@@ -306,7 +309,7 @@ class DirectCameraControl(DirectObject):
 
 
     def XZTranslateTask(self, state):
     def XZTranslateTask(self, state):
         coaDist = Vec3(self.coaMarker.getPos(base.direct.camera)).length()
         coaDist = Vec3(self.coaMarker.getPos(base.direct.camera)).length()
-        xlateSF = (coaDist / base.direct.dr.near)
+        xlateSF = coaDist / base.direct.dr.near
         base.direct.camera.setPos(base.direct.camera,
         base.direct.camera.setPos(base.direct.camera,
                              (-0.5 * base.direct.dr.mouseDeltaX *
                              (-0.5 * base.direct.dr.mouseDeltaX *
                               base.direct.dr.nearWidth *
                               base.direct.dr.nearWidth *
@@ -349,7 +352,7 @@ class DirectCameraControl(DirectObject):
         else:
         else:
             moveDir = Vec3(Y_AXIS)
             moveDir = Vec3(Y_AXIS)
 
 
-        if self.useMayaCamControls : # use maya controls
+        if self.useMayaCamControls: # use maya controls
             moveDir.assign(moveDir * ((base.direct.dr.mouseDeltaX -1.0 * base.direct.dr.mouseDeltaY)
             moveDir.assign(moveDir * ((base.direct.dr.mouseDeltaX -1.0 * base.direct.dr.mouseDeltaY)
                                     * state.zoomSF))
                                     * state.zoomSF))
             hVal = 0.0
             hVal = 0.0
@@ -422,7 +425,7 @@ class DirectCameraControl(DirectObject):
 
 
         # Set at markers position in render coordinates
         # Set at markers position in render coordinates
         self.camManipRef.setPos(self.coaMarkerPos)
         self.camManipRef.setPos(self.coaMarkerPos)
-        self.camManipRef.setHpr(base.direct.camera, ZERO_POINT)
+        self.camManipRef.setHpr(base.direct.camera, DG.ZERO_POINT)
         t = Task.Task(self.mouseRotateTask)
         t = Task.Task(self.mouseRotateTask)
         if abs(base.direct.dr.mouseX) > 0.9:
         if abs(base.direct.dr.mouseX) > 0.9:
             t.constrainedDir = 'y'
             t.constrainedDir = 'y'
@@ -454,7 +457,7 @@ class DirectCameraControl(DirectObject):
                 # flatten roll
                 # flatten roll
                 base.direct.camera.setR(0)
                 base.direct.camera.setR(0)
             self.camManipRef.setPos(self.coaMarkerPos)
             self.camManipRef.setPos(self.coaMarkerPos)
-            self.camManipRef.setHpr(base.direct.camera, ZERO_POINT)
+            self.camManipRef.setHpr(base.direct.camera, DG.ZERO_POINT)
         else:
         else:
             if base.direct.camera.getPos().getZ() >=0 or not self.switchDirBelowZero:
             if base.direct.camera.getPos().getZ() >=0 or not self.switchDirBelowZero:
                 dirX = -1
                 dirX = -1
@@ -478,7 +481,7 @@ class DirectCameraControl(DirectObject):
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
         # Set at markers position in render coordinates
         # Set at markers position in render coordinates
         self.camManipRef.setPos(self.coaMarkerPos)
         self.camManipRef.setPos(self.coaMarkerPos)
-        self.camManipRef.setHpr(base.direct.camera, ZERO_POINT)
+        self.camManipRef.setHpr(base.direct.camera, DG.ZERO_POINT)
         t = Task.Task(self.mouseRollTask)
         t = Task.Task(self.mouseRollTask)
         t.coaCenter = getScreenXY(self.coaMarker)
         t.coaCenter = getScreenXY(self.coaMarker)
         t.lastAngle = getCrankAngle(t.coaCenter)
         t.lastAngle = getCrankAngle(t.coaCenter)
@@ -565,7 +568,7 @@ class DirectCameraControl(DirectObject):
             base.direct.message('COA Distance: ' + repr(dist))
             base.direct.message('COA Distance: ' + repr(dist))
             coa.set(0, dist, 0)
             coa.set(0, dist, 0)
         # Compute COA Dist
         # Compute COA Dist
-        coaDist = Vec3(coa - ZERO_POINT).length()
+        coaDist = Vec3(coa - DG.ZERO_POINT).length()
         if coaDist < (1.1 * dr.near):
         if coaDist < (1.1 * dr.near):
             coa.set(0, 100, 0)
             coa.set(0, 100, 0)
             coaDist = 100
             coaDist = 100
@@ -575,7 +578,7 @@ class DirectCameraControl(DirectObject):
     def updateCoa(self, ref2point, coaDist = None, ref = None):
     def updateCoa(self, ref2point, coaDist = None, ref = None):
         self.coa.set(ref2point[0], ref2point[1], ref2point[2])
         self.coa.set(ref2point[0], ref2point[1], ref2point[2])
         if not coaDist:
         if not coaDist:
-            coaDist = Vec3(self.coa - ZERO_POINT).length()
+            coaDist = Vec3(self.coa - DG.ZERO_POINT).length()
         # Place the marker in render space
         # Place the marker in render space
         if ref is None:
         if ref is None:
             # KEH: use the current display region
             # KEH: use the current display region
@@ -611,7 +614,7 @@ class DirectCameraControl(DirectObject):
                                          startColor = Vec4(1, 0, 0, 1),
                                          startColor = Vec4(1, 0, 0, 1),
                                          blendType = 'easeInOut'),
                                          blendType = 'easeInOut'),
             Func(self.coaMarker.stash)
             Func(self.coaMarker.stash)
-            )
+        )
         self.coaMarkerColorIval.start()
         self.coaMarkerColorIval.start()
 
 
     def homeCam(self):
     def homeCam(self):
@@ -642,19 +645,19 @@ class DirectCameraControl(DirectObject):
         # Transform camera z axis to render space
         # Transform camera z axis to render space
         mCam2Render = Mat4(Mat4.identMat()) # [gjeon] fixed to give required argument
         mCam2Render = Mat4(Mat4.identMat()) # [gjeon] fixed to give required argument
         mCam2Render.assign(base.direct.camera.getMat(render))
         mCam2Render.assign(base.direct.camera.getMat(render))
-        zAxis = Vec3(mCam2Render.xformVec(Z_AXIS))
+        zAxis = Vec3(mCam2Render.xformVec(DG.Z_AXIS))
         zAxis.normalize()
         zAxis.normalize()
         # Compute rotation angle needed to upright cam
         # Compute rotation angle needed to upright cam
-        orbitAngle = rad2Deg(math.acos(CLAMP(zAxis.dot(Z_AXIS), -1, 1)))
+        orbitAngle = rad2Deg(math.acos(CLAMP(zAxis.dot(DG.Z_AXIS), -1, 1)))
         # Check angle
         # Check angle
         if orbitAngle < 0.1:
         if orbitAngle < 0.1:
             # Already upright
             # Already upright
             return
             return
         # Compute orthogonal axis of rotation
         # Compute orthogonal axis of rotation
-        rotAxis = Vec3(zAxis.cross(Z_AXIS))
+        rotAxis = Vec3(zAxis.cross(DG.Z_AXIS))
         rotAxis.normalize()
         rotAxis.normalize()
         # Find angle between rot Axis and render X_AXIS
         # Find angle between rot Axis and render X_AXIS
-        rotAngle = rad2Deg(math.acos(CLAMP(rotAxis.dot(X_AXIS), -1, 1)))
+        rotAngle = rad2Deg(math.acos(CLAMP(rotAxis.dot(DG.X_AXIS), -1, 1)))
         # Determine sign or rotation angle
         # Determine sign or rotation angle
         if rotAxis[1] < 0:
         if rotAxis[1] < 0:
             rotAngle *= -1
             rotAngle *= -1
@@ -685,7 +688,7 @@ class DirectCameraControl(DirectObject):
         base.direct.pushUndo([base.direct.camera])
         base.direct.pushUndo([base.direct.camera])
         # Determine marker location
         # Determine marker location
         markerToCam = self.coaMarker.getPos(base.direct.camera)
         markerToCam = self.coaMarker.getPos(base.direct.camera)
-        dist = Vec3(markerToCam - ZERO_POINT).length()
+        dist = Vec3(markerToCam - DG.ZERO_POINT).length()
         scaledCenterVec = Y_AXIS * dist
         scaledCenterVec = Y_AXIS * dist
         delta = markerToCam - scaledCenterVec
         delta = markerToCam - scaledCenterVec
         self.camManipRef.setPosHpr(base.direct.camera, Point3(0), Point3(0))
         self.camManipRef.setPosHpr(base.direct.camera, Point3(0), Point3(0))
@@ -697,7 +700,6 @@ class DirectCameraControl(DirectObject):
                         name = 'manipulateCamera')
                         name = 'manipulateCamera')
         self.__startManipulateCamera(ival = ival)
         self.__startManipulateCamera(ival = ival)
 
 
-
     def zoomCam(self, zoomFactor, t):
     def zoomCam(self, zoomFactor, t):
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
         # Record undo point
         # Record undo point
@@ -709,7 +711,7 @@ class DirectCameraControl(DirectObject):
         self.camManipRef.setPos(base.direct.camera, zoomPtToCam)
         self.camManipRef.setPos(base.direct.camera, zoomPtToCam)
         # Move to that point
         # Move to that point
         ival = base.direct.camera.posInterval(CAM_MOVE_DURATION,
         ival = base.direct.camera.posInterval(CAM_MOVE_DURATION,
-                                              ZERO_POINT,
+                                              DG.ZERO_POINT,
                                               other = self.camManipRef,
                                               other = self.camManipRef,
                                               blendType = 'easeInOut')
                                               blendType = 'easeInOut')
         ival = Sequence(ival, Func(self.updateCoaMarkerSizeOnDeath),
         ival = Sequence(ival, Func(self.updateCoaMarkerSizeOnDeath),
@@ -746,20 +748,20 @@ class DirectCameraControl(DirectObject):
         elif view == 7:
         elif view == 7:
             hprOffset.set(135., -35.264, 0.)
             hprOffset.set(135., -35.264, 0.)
         # Position target
         # Position target
-        self.camManipRef.setPosHpr(self.coaMarker, ZERO_VEC,
+        self.camManipRef.setPosHpr(self.coaMarker, DG.ZERO_VEC,
                                    hprOffset)
                                    hprOffset)
         # Scale center vec by current distance to target
         # Scale center vec by current distance to target
         offsetDistance = Vec3(base.direct.camera.getPos(self.camManipRef) -
         offsetDistance = Vec3(base.direct.camera.getPos(self.camManipRef) -
-                              ZERO_POINT).length()
+                              DG.ZERO_POINT).length()
         scaledCenterVec = Y_AXIS * (-1.0 * offsetDistance)
         scaledCenterVec = Y_AXIS * (-1.0 * offsetDistance)
         # Now put the camManipRef at that point
         # Now put the camManipRef at that point
         self.camManipRef.setPosHpr(self.camManipRef,
         self.camManipRef.setPosHpr(self.camManipRef,
                                    scaledCenterVec,
                                    scaledCenterVec,
-                                   ZERO_VEC)
+                                   DG.ZERO_VEC)
         # Record view for next time around
         # Record view for next time around
         self.lastView = view
         self.lastView = view
         ival = base.direct.camera.posHprInterval(CAM_MOVE_DURATION,
         ival = base.direct.camera.posHprInterval(CAM_MOVE_DURATION,
-                                                 pos = ZERO_POINT,
+                                                 pos = DG.ZERO_POINT,
                                                  hpr = VBase3(0, 0, self.orthoViewRoll),
                                                  hpr = VBase3(0, 0, self.orthoViewRoll),
                                                  other = self.camManipRef,
                                                  other = self.camManipRef,
                                                  blendType = 'easeInOut')
                                                  blendType = 'easeInOut')
@@ -767,7 +769,6 @@ class DirectCameraControl(DirectObject):
                         name = 'manipulateCamera')
                         name = 'manipulateCamera')
         self.__startManipulateCamera(ival = ival)
         self.__startManipulateCamera(ival = ival)
 
 
-
     def swingCamAboutWidget(self, degrees, t):
     def swingCamAboutWidget(self, degrees, t):
         # Remove existing camera manipulation task
         # Remove existing camera manipulation task
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
@@ -776,9 +777,9 @@ class DirectCameraControl(DirectObject):
         base.direct.pushUndo([base.direct.camera])
         base.direct.pushUndo([base.direct.camera])
 
 
         # Coincident with widget
         # Coincident with widget
-        self.camManipRef.setPos(self.coaMarker, ZERO_POINT)
+        self.camManipRef.setPos(self.coaMarker, DG.ZERO_POINT)
         # But aligned with render space
         # But aligned with render space
-        self.camManipRef.setHpr(ZERO_POINT)
+        self.camManipRef.setHpr(DG.ZERO_POINT)
 
 
         parent = base.direct.camera.getParent()
         parent = base.direct.camera.getParent()
         base.direct.camera.wrtReparentTo(self.camManipRef)
         base.direct.camera.wrtReparentTo(self.camManipRef)
@@ -820,7 +821,8 @@ class DirectCameraControl(DirectObject):
         try:
         try:
             self.camManipRef.setPos(base.direct.camera, deltaMove)
             self.camManipRef.setPos(base.direct.camera, deltaMove)
         except Exception:
         except Exception:
-            self.notify.debug
+            #self.notify.debug
+            pass
 
 
         parent = base.direct.camera.getParent()
         parent = base.direct.camera.getParent()
         base.direct.camera.wrtReparentTo(self.camManipRef)
         base.direct.camera.wrtReparentTo(self.camManipRef)
@@ -831,7 +833,6 @@ class DirectCameraControl(DirectObject):
                         name = 'manipulateCamera')
                         name = 'manipulateCamera')
         self.__startManipulateCamera(ival = ival)
         self.__startManipulateCamera(ival = ival)
 
 
-
     def moveToFit(self):
     def moveToFit(self):
         # How big is the active widget?
         # How big is the active widget?
         widgetScale = base.direct.widget.scalingNode.getScale(render)
         widgetScale = base.direct.widget.scalingNode.getScale(render)

+ 28 - 5
direct/src/directtools/DirectGeometry.py

@@ -1,9 +1,24 @@
-
-from panda3d.core import *
-from .DirectGlobals import *
-from .DirectUtil import *
+from panda3d.core import (
+    CSDefault,
+    GeomNode,
+    LineSegs,
+    Mat4,
+    NodePath,
+    Point3,
+    Quat,
+    VBase3,
+    VBase4,
+    Vec3,
+    composeMatrix,
+    decomposeMatrix,
+    deg2Rad,
+    rad2Deg,
+)
+from .DirectGlobals import Q_EPSILON, UNIT_VEC, ZERO_VEC
+from .DirectUtil import CLAMP
 import math
 import math
 
 
+
 class LineNodePath(NodePath):
 class LineNodePath(NodePath):
     def __init__(self, parent = None, name = None,
     def __init__(self, parent = None, name = None,
                  thickness = 1.0, colorVec = VBase4(1)):
                  thickness = 1.0, colorVec = VBase4(1)):
@@ -126,13 +141,16 @@ class LineNodePath(NodePath):
 ##
 ##
 ## Given a point in space, and a direction, find the point of intersection
 ## Given a point in space, and a direction, find the point of intersection
 ## of that ray with a plane at the specified origin, with the specified normal
 ## of that ray with a plane at the specified origin, with the specified normal
-def planeIntersect (lineOrigin, lineDir, planeOrigin, normal):
+
+
+def planeIntersect(lineOrigin, lineDir, planeOrigin, normal):
     t = 0
     t = 0
     offset = planeOrigin - lineOrigin
     offset = planeOrigin - lineOrigin
     t = offset.dot(normal) / lineDir.dot(normal)
     t = offset.dot(normal) / lineDir.dot(normal)
     hitPt = lineDir * t
     hitPt = lineDir * t
     return hitPt + lineOrigin
     return hitPt + lineOrigin
 
 
+
 def getNearProjectionPoint(nodePath):
 def getNearProjectionPoint(nodePath):
     # Find the position of the projection of the specified node path
     # Find the position of the projection of the specified node path
     # on the near plane
     # on the near plane
@@ -144,6 +162,7 @@ def getNearProjectionPoint(nodePath):
         # Object is coplaner with camera, just return something reasonable
         # Object is coplaner with camera, just return something reasonable
         return Point3(0, base.direct.dr.near, 0)
         return Point3(0, base.direct.dr.near, 0)
 
 
+
 def getScreenXY(nodePath):
 def getScreenXY(nodePath):
     # Where does the node path's projection fall on the near plane
     # Where does the node path's projection fall on the near plane
     nearVec = getNearProjectionPoint(nodePath)
     nearVec = getNearProjectionPoint(nodePath)
@@ -158,6 +177,7 @@ def getScreenXY(nodePath):
     # Return the resulting value
     # Return the resulting value
     return screenXY
     return screenXY
 
 
+
 def getCrankAngle(center):
 def getCrankAngle(center):
     # Used to compute current angle of mouse (relative to the coa's
     # Used to compute current angle of mouse (relative to the coa's
     # origin) in screen space
     # origin) in screen space
@@ -165,6 +185,7 @@ def getCrankAngle(center):
     y = base.direct.dr.mouseY - center[2]
     y = base.direct.dr.mouseY - center[2]
     return 180 + rad2Deg(math.atan2(y, x))
     return 180 + rad2Deg(math.atan2(y, x))
 
 
+
 def relHpr(nodePath, base, h, p, r):
 def relHpr(nodePath, base, h, p, r):
     # Compute nodePath2newNodePath relative to base coordinate system
     # Compute nodePath2newNodePath relative to base coordinate system
     # nodePath2base
     # nodePath2base
@@ -188,6 +209,8 @@ def relHpr(nodePath, base, h, p, r):
     nodePath.setHpr(hpr)
     nodePath.setHpr(hpr)
 
 
 # Quaternion interpolation
 # Quaternion interpolation
+
+
 def qSlerp(startQuat, endQuat, t):
 def qSlerp(startQuat, endQuat, t):
     startQ = Quat(startQuat)
     startQ = Quat(startQuat)
     destQuat = Quat(Quat.identQuat())
     destQuat = Quat(Quat.identQuat())

+ 4 - 4
direct/src/directtools/DirectGlobals.py

@@ -51,11 +51,11 @@ LE_CAM_MASKS = {'persp':LE_PERSP_CAM_MASK,
                  'top':LE_TOP_CAM_MASK}
                  'top':LE_TOP_CAM_MASK}
 
 
 def LE_showInAllCam(nodePath):
 def LE_showInAllCam(nodePath):
-    for camName in LE_CAM_MASKS:
-        nodePath.show(LE_CAM_MASKS[camName])
+    for camName, mask in LE_CAM_MASKS.items():
+        nodePath.show(mask)
 
 
 def LE_showInOneCam(nodePath, thisCamName):
 def LE_showInOneCam(nodePath, thisCamName):
     LE_showInAllCam(nodePath)
     LE_showInAllCam(nodePath)
-    for camName in LE_CAM_MASKS:
+    for camName, mask in LE_CAM_MASKS.items():
         if camName != thisCamName:
         if camName != thisCamName:
-            nodePath.hide(LE_CAM_MASKS[camName])
+            nodePath.hide(mask)

+ 4 - 4
direct/src/directtools/DirectGrid.py

@@ -1,8 +1,8 @@
-
-from panda3d.core import *
+import math
+from panda3d.core import NodePath, Point3, VBase4
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
-from .DirectUtil import *
-from .DirectGeometry import *
+from .DirectUtil import ROUND_TO, useDirectRenderStyle
+from .DirectGeometry import LineNodePath
 
 
 
 
 class DirectGrid(NodePath, DirectObject):
 class DirectGrid(NodePath, DirectObject):

+ 11 - 1
direct/src/directtools/DirectLights.py

@@ -1,5 +1,15 @@
 
 
-from panda3d.core import *
+from panda3d.core import (
+    AmbientLight,
+    DirectionalLight,
+    LightAttrib,
+    Material,
+    NodePath,
+    PerspectiveLens,
+    PointLight,
+    Spotlight,
+    VBase4,
+)
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 
 
 
 

+ 73 - 49
direct/src/directtools/DirectManipulation.py

@@ -1,10 +1,32 @@
+import math
+from panda3d.core import (
+    BitMask32,
+    BoundingHexahedron,
+    CSDefault,
+    Mat4,
+    NodePath,
+    Point3,
+    VBase3,
+    VBase4,
+    Vec3,
+    decomposeMatrix,
+    deg2Rad,
+)
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
-from .DirectGlobals import *
-from .DirectUtil import *
-from .DirectGeometry import *
+from . import DirectGlobals as DG
+from .DirectUtil import useDirectRenderStyle
+from .DirectGeometry import (
+    LineNodePath,
+    getCrankAngle,
+    getNearProjectionPoint,
+    getScreenXY,
+    planeIntersect,
+    relHpr,
+)
 from .DirectSelection import SelectionRay
 from .DirectSelection import SelectionRay
 from direct.task import Task
 from direct.task import Task
+from direct.task.TaskManagerGlobal import taskMgr
 from copy import deepcopy
 from copy import deepcopy
 
 
 
 
@@ -50,8 +72,8 @@ class DirectManipulationControl(DirectObject):
             ['DIRECT-widgetScaleDown', self.scaleWidget, 0.5],
             ['DIRECT-widgetScaleDown', self.scaleWidget, 0.5],
             ['shift-f', self.objectHandles.growToFit],
             ['shift-f', self.objectHandles.growToFit],
             ['i', self.plantSelectedNodePath],
             ['i', self.plantSelectedNodePath],
-            ]
-        self.defaultSkipFlags = SKIP_HIDDEN | SKIP_BACKFACE
+        ]
+        self.defaultSkipFlags = DG.SKIP_HIDDEN | DG.SKIP_BACKFACE
         self.optionalSkipFlags = 0
         self.optionalSkipFlags = 0
         self.unmovableTagList = []
         self.unmovableTagList = []
 
 
@@ -115,7 +137,7 @@ class DirectManipulationControl(DirectObject):
            self.fScaling3D == 0:
            self.fScaling3D == 0:
 
 
             # Check for a widget hit point
             # Check for a widget hit point
-            entry = base.direct.iRay.pickWidget(skipFlags = SKIP_WIDGET)
+            entry = base.direct.iRay.pickWidget(skipFlags = DG.SKIP_WIDGET)
             # Did we hit a widget?
             # Did we hit a widget?
             if entry:
             if entry:
                 # Yes!
                 # Yes!
@@ -137,7 +159,7 @@ class DirectManipulationControl(DirectObject):
             if entry:
             if entry:
                 # Check to see if we are moving the object
                 # Check to see if we are moving the object
                 # We are moving the object if we either wait long enough
                 # We are moving the object if we either wait long enough
-                taskMgr.doMethodLater(MANIPULATION_MOVE_DELAY,
+                taskMgr.doMethodLater(DG.MANIPULATION_MOVE_DELAY,
                                       self.switchToMoveMode,
                                       self.switchToMoveMode,
                                       'manip-move-wait')
                                       'manip-move-wait')
                 # Or we move far enough
                 # Or we move far enough
@@ -170,8 +192,8 @@ class DirectManipulationControl(DirectObject):
         return Task.done
         return Task.done
 
 
     def watchMouseTask(self, state):
     def watchMouseTask(self, state):
-        if (((abs (state.initX - base.direct.dr.mouseX)) > 0.01) or
-            ((abs (state.initY - base.direct.dr.mouseY)) > 0.01)):
+        if (abs(state.initX - base.direct.dr.mouseX) > 0.01 or
+            abs(state.initY - base.direct.dr.mouseY) > 0.01):
             taskMgr.remove('manip-move-wait')
             taskMgr.remove('manip-move-wait')
             self.mode = 'move'
             self.mode = 'move'
             self.manipulateObject()
             self.manipulateObject()
@@ -199,8 +221,8 @@ class DirectManipulationControl(DirectObject):
         endX = base.direct.dr.mouseX
         endX = base.direct.dr.mouseX
         endY = base.direct.dr.mouseY
         endY = base.direct.dr.mouseY
 
 
-        if (((abs (endX - startX)) < 0.01) and
-            ((abs (endY - startY)) < 0.01)):
+        if (abs(endX - startX) < 0.01 and
+            abs(endY - startY) < 0.01):
             return
             return
 
 
         self.marquee = LineNodePath(base.render2d, 'marquee', 0.5, VBase4(.8, .6, .6, 1))
         self.marquee = LineNodePath(base.render2d, 'marquee', 0.5, VBase4(.8, .6, .6, 1))
@@ -213,7 +235,7 @@ class DirectManipulationControl(DirectObject):
         self.marquee.create()
         self.marquee.create()
 
 
         if self.fMultiView:
         if self.fMultiView:
-            LE_showInOneCam(self.marquee, base.direct.camera.getName())
+            DG.LE_showInOneCam(self.marquee, base.direct.camera.getName())
 
 
     def manipulationStop(self):
     def manipulationStop(self):
         taskMgr.remove('manipulateObject')
         taskMgr.remove('manipulateObject')
@@ -227,7 +249,7 @@ class DirectManipulationControl(DirectObject):
             # optionally specified things
             # optionally specified things
             skipFlags = self.defaultSkipFlags | self.optionalSkipFlags
             skipFlags = self.defaultSkipFlags | self.optionalSkipFlags
             # Skip camera (and its children), unless control key is pressed
             # Skip camera (and its children), unless control key is pressed
-            skipFlags |= SKIP_CAMERA * (1 - base.getControl())
+            skipFlags |= DG.SKIP_CAMERA * (1 - base.getControl())
 
 
             if self.marquee:
             if self.marquee:
                 self.marquee.removeNode()
                 self.marquee.removeNode()
@@ -269,18 +291,18 @@ class DirectManipulationControl(DirectObject):
 
 
                 selectionList = []
                 selectionList = []
                 for geom in render.findAllMatches("**/+GeomNode"):
                 for geom in render.findAllMatches("**/+GeomNode"):
-                    if (skipFlags & SKIP_HIDDEN) and geom.isHidden():
+                    if (skipFlags & DG.SKIP_HIDDEN) and geom.isHidden():
                         # Skip if hidden node
                         # Skip if hidden node
                         continue
                         continue
-##                     elif (skipFlags & SKIP_BACKFACE) and base.direct.iRay.isEntryBackfacing():
+##                     elif (skipFlags & DG.SKIP_BACKFACE) and base.direct.iRay.isEntryBackfacing():
 ##                         # Skip, if backfacing poly
 ##                         # Skip, if backfacing poly
 ##                         pass
 ##                         pass
-                    elif (skipFlags & SKIP_CAMERA) and \
+                    elif (skipFlags & DG.SKIP_CAMERA) and \
                          (base.camera in geom.getAncestors()):
                          (base.camera in geom.getAncestors()):
                         # Skip if parented to a camera.
                         # Skip if parented to a camera.
                         continue
                         continue
                     # Can pick unpickable, use the first visible node
                     # Can pick unpickable, use the first visible node
-                    elif (skipFlags & SKIP_UNPICKABLE) and \
+                    elif (skipFlags & DG.SKIP_UNPICKABLE) and \
                          (geom.getName() in base.direct.iRay.unpickable):
                          (geom.getName() in base.direct.iRay.unpickable):
                         # Skip if in unpickable list
                         # Skip if in unpickable list
                         continue
                         continue
@@ -500,7 +522,7 @@ class DirectManipulationControl(DirectObject):
         selectedList = base.direct.selected.getSelectedAsList()
         selectedList = base.direct.selected.getSelectedAsList()
         # See if any of the selected are completely uneditable
         # See if any of the selected are completely uneditable
         editTypes = self.getEditTypes(selectedList)
         editTypes = self.getEditTypes(selectedList)
-        if (editTypes & EDIT_TYPE_UNEDITABLE) == EDIT_TYPE_UNEDITABLE:
+        if (editTypes & DG.EDIT_TYPE_UNEDITABLE) == DG.EDIT_TYPE_UNEDITABLE:
             return
             return
         self.currEditTypes = editTypes
         self.currEditTypes = editTypes
         if selectedList:
         if selectedList:
@@ -568,13 +590,13 @@ class DirectManipulationControl(DirectObject):
             if self.constraint:
             if self.constraint:
                 type = self.constraint[2:]
                 type = self.constraint[2:]
                 if self.useSeparateScaleHandles:
                 if self.useSeparateScaleHandles:
-                    if type == 'post' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
+                    if type == 'post' and not self.currEditTypes & DG.EDIT_TYPE_UNMOVABLE:
                         self.xlate1D(state)
                         self.xlate1D(state)
-                    elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
+                    elif type == 'disc' and not self.currEditTypes & DG.EDIT_TYPE_UNMOVABLE:
                         self.xlate2D(state)
                         self.xlate2D(state)
-                    elif type == 'ring' and not self.currEditTypes & EDIT_TYPE_UNROTATABLE:
+                    elif type == 'ring' and not self.currEditTypes & DG.EDIT_TYPE_UNROTATABLE:
                         self.rotate1D(state)
                         self.rotate1D(state)
-                    elif type == 'scale' and not self.currEditTypes & EDIT_TYPE_UNSCALABLE:
+                    elif type == 'scale' and not self.currEditTypes & DG.EDIT_TYPE_UNSCALABLE:
                         if base.direct.fShift:
                         if base.direct.fShift:
                             self.fScaling3D = 1
                             self.fScaling3D = 1
                             self.scale3D(state)
                             self.scale3D(state)
@@ -582,7 +604,7 @@ class DirectManipulationControl(DirectObject):
                             self.fScaling1D = 1
                             self.fScaling1D = 1
                             self.scale1D(state)
                             self.scale1D(state)
                 else:
                 else:
-                    if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE:
+                    if base.direct.fControl and not self.currEditTypes & DG.EDIT_TYPE_UNSCALABLE:
                         if type == 'post':
                         if type == 'post':
                             # [gjeon] non-uniform scaling
                             # [gjeon] non-uniform scaling
                             self.fScaling1D = 1
                             self.fScaling1D = 1
@@ -592,11 +614,11 @@ class DirectManipulationControl(DirectObject):
                             self.fScaling3D = 1
                             self.fScaling3D = 1
                             self.scale3D(state)
                             self.scale3D(state)
                     else:
                     else:
-                        if type == 'post' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
+                        if type == 'post' and not self.currEditTypes & DG.EDIT_TYPE_UNMOVABLE:
                             self.xlate1D(state)
                             self.xlate1D(state)
-                        elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
+                        elif type == 'disc' and not self.currEditTypes & DG.EDIT_TYPE_UNMOVABLE:
                             self.xlate2D(state)
                             self.xlate2D(state)
-                        elif type == 'ring' and not self.currEditTypes & EDIT_TYPE_UNROTATABLE:
+                        elif type == 'ring' and not self.currEditTypes & DG.EDIT_TYPE_UNROTATABLE:
                             self.rotate1D(state)
                             self.rotate1D(state)
             # No widget interaction, determine free manip mode
             # No widget interaction, determine free manip mode
             elif self.fFreeManip and not self.useSeparateScaleHandles:
             elif self.fFreeManip and not self.useSeparateScaleHandles:
@@ -610,17 +632,17 @@ class DirectManipulationControl(DirectObject):
                     self.fScaling1D = 0
                     self.fScaling1D = 0
                     self.fScaling3D = 0
                     self.fScaling3D = 0
                 # Alt key switches to a scaling mode
                 # Alt key switches to a scaling mode
-                if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE:
+                if base.direct.fControl and not self.currEditTypes & DG.EDIT_TYPE_UNSCALABLE:
                     self.fScaling3D = 1
                     self.fScaling3D = 1
                     self.scale3D(state)
                     self.scale3D(state)
                 # Otherwise, manip mode depends on where you started
                 # Otherwise, manip mode depends on where you started
-                elif state.fMouseX and state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNROTATABLE:
+                elif state.fMouseX and state.fMouseY and not self.currEditTypes & DG.EDIT_TYPE_UNROTATABLE:
                     # In the corner, spin around camera's axis
                     # In the corner, spin around camera's axis
                     self.rotateAboutViewVector(state)
                     self.rotateAboutViewVector(state)
-                elif state.fMouseX or state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
+                elif state.fMouseX or state.fMouseY and not self.currEditTypes & DG.EDIT_TYPE_UNMOVABLE:
                     # Mouse started elsewhere in the outer frame, rotate
                     # Mouse started elsewhere in the outer frame, rotate
                     self.rotate2D(state)
                     self.rotate2D(state)
-                elif not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
+                elif not self.currEditTypes & DG.EDIT_TYPE_UNMOVABLE:
                     # Mouse started in central region, xlate
                     # Mouse started in central region, xlate
                     # Mode depends on shift key
                     # Mode depends on shift key
                     if base.direct.fShift or base.direct.fControl:
                     if base.direct.fShift or base.direct.fControl:
@@ -805,11 +827,11 @@ class DirectManipulationControl(DirectObject):
         widgetDir.normalize()
         widgetDir.normalize()
         # Convert specified widget axis to view space
         # Convert specified widget axis to view space
         if axis == 'x':
         if axis == 'x':
-            widgetAxis = Vec3(mWidget2Cam.xformVec(X_AXIS))
+            widgetAxis = Vec3(mWidget2Cam.xformVec(DG.X_AXIS))
         elif axis == 'y':
         elif axis == 'y':
-            widgetAxis = Vec3(mWidget2Cam.xformVec(Y_AXIS))
+            widgetAxis = Vec3(mWidget2Cam.xformVec(DG.Y_AXIS))
         elif axis == 'z':
         elif axis == 'z':
-            widgetAxis = Vec3(mWidget2Cam.xformVec(Z_AXIS))
+            widgetAxis = Vec3(mWidget2Cam.xformVec(DG.Z_AXIS))
         widgetAxis.normalize()
         widgetAxis.normalize()
         if type == 'top?':
         if type == 'top?':
             # Check sign of angle between two vectors
             # Check sign of angle between two vectors
@@ -868,7 +890,7 @@ class DirectManipulationControl(DirectObject):
                 moveDir.assign(moveDir * -1)
                 moveDir.assign(moveDir * -1)
             moveDir.normalize()
             moveDir.normalize()
         else:
         else:
-            moveDir = Vec3(Y_AXIS)
+            moveDir = Vec3(DG.Y_AXIS)
         # Move selected objects
         # Move selected objects
         dr = base.direct.dr
         dr = base.direct.dr
         # Scale move dir
         # Scale move dir
@@ -1034,8 +1056,8 @@ class DirectManipulationControl(DirectObject):
             self.initScale *
             self.initScale *
             (self.objectHandles.getWidgetIntersectPt(
             (self.objectHandles.getWidgetIntersectPt(
             self.manipRef, 'y').length() /
             self.manipRef, 'y').length() /
-             self.initScaleMag)
-            )
+                self.initScaleMag)
+        )
         base.direct.widget.setScale(currScale)
         base.direct.widget.setScale(currScale)
 
 
     ## Utility functions ##
     ## Utility functions ##
@@ -1043,7 +1065,7 @@ class DirectManipulationControl(DirectObject):
         """ Move selected object to intersection point of cursor on scene """
         """ Move selected object to intersection point of cursor on scene """
         # Check for intersection
         # Check for intersection
         entry = base.direct.iRay.pickGeom(
         entry = base.direct.iRay.pickGeom(
-            skipFlags = SKIP_HIDDEN | SKIP_BACKFACE | SKIP_CAMERA)
+            skipFlags = DG.SKIP_HIDDEN | DG.SKIP_BACKFACE | DG.SKIP_CAMERA)
         # MRM: Need to handle moving COA
         # MRM: Need to handle moving COA
         if entry is not None and base.direct.selected.last is not None:
         if entry is not None and base.direct.selected.last is not None:
             # Record undo point
             # Record undo point
@@ -1060,6 +1082,7 @@ class DirectManipulationControl(DirectObject):
             messenger.send('DIRECT_manipulateObjectCleanup',
             messenger.send('DIRECT_manipulateObjectCleanup',
                            [base.direct.selected.getSelectedAsList()])
                            [base.direct.selected.getSelectedAsList()])
 
 
+
 class ObjectHandles(NodePath, DirectObject):
 class ObjectHandles(NodePath, DirectObject):
     def __init__(self, name='objectHandles'):
     def __init__(self, name='objectHandles'):
         # Initialize the superclass
         # Initialize the superclass
@@ -1642,32 +1665,32 @@ class ObjectHandles(NodePath, DirectObject):
         # by comparing lineDir with plane normals.  The plane with the
         # by comparing lineDir with plane normals.  The plane with the
         # largest dotProduct is most "normal"
         # largest dotProduct is most "normal"
         if axis == 'x':
         if axis == 'x':
-            if abs(lineDir.dot(Y_AXIS)) > abs(lineDir.dot(Z_AXIS)):
+            if abs(lineDir.dot(DG.Y_AXIS)) > abs(lineDir.dot(DG.Z_AXIS)):
                 self.hitPt.assign(
                 self.hitPt.assign(
-                    planeIntersect(lineOrigin, lineDir, ORIGIN, Y_AXIS))
+                    planeIntersect(lineOrigin, lineDir, DG.ORIGIN, DG.Y_AXIS))
             else:
             else:
                 self.hitPt.assign(
                 self.hitPt.assign(
-                    planeIntersect(lineOrigin, lineDir, ORIGIN, Z_AXIS))
+                    planeIntersect(lineOrigin, lineDir, DG.ORIGIN, DG.Z_AXIS))
             # We really only care about the nearest point on the axis
             # We really only care about the nearest point on the axis
             self.hitPt.setY(0)
             self.hitPt.setY(0)
             self.hitPt.setZ(0)
             self.hitPt.setZ(0)
         elif axis == 'y':
         elif axis == 'y':
-            if abs(lineDir.dot(X_AXIS)) > abs(lineDir.dot(Z_AXIS)):
+            if abs(lineDir.dot(DG.X_AXIS)) > abs(lineDir.dot(DG.Z_AXIS)):
                 self.hitPt.assign(
                 self.hitPt.assign(
-                    planeIntersect(lineOrigin, lineDir, ORIGIN, X_AXIS))
+                    planeIntersect(lineOrigin, lineDir, DG.ORIGIN, DG.X_AXIS))
             else:
             else:
                 self.hitPt.assign(
                 self.hitPt.assign(
-                    planeIntersect(lineOrigin, lineDir, ORIGIN, Z_AXIS))
+                    planeIntersect(lineOrigin, lineDir, DG.ORIGIN, DG.Z_AXIS))
             # We really only care about the nearest point on the axis
             # We really only care about the nearest point on the axis
             self.hitPt.setX(0)
             self.hitPt.setX(0)
             self.hitPt.setZ(0)
             self.hitPt.setZ(0)
         elif axis == 'z':
         elif axis == 'z':
-            if abs(lineDir.dot(X_AXIS)) > abs(lineDir.dot(Y_AXIS)):
+            if abs(lineDir.dot(DG.X_AXIS)) > abs(lineDir.dot(DG.Y_AXIS)):
                 self.hitPt.assign(
                 self.hitPt.assign(
-                    planeIntersect(lineOrigin, lineDir, ORIGIN, X_AXIS))
+                    planeIntersect(lineOrigin, lineDir, DG.ORIGIN, DG.X_AXIS))
             else:
             else:
                 self.hitPt.assign(
                 self.hitPt.assign(
-                    planeIntersect(lineOrigin, lineDir, ORIGIN, Y_AXIS))
+                    planeIntersect(lineOrigin, lineDir, DG.ORIGIN, DG.Y_AXIS))
             # We really only care about the nearest point on the axis
             # We really only care about the nearest point on the axis
             self.hitPt.setX(0)
             self.hitPt.setX(0)
             self.hitPt.setY(0)
             self.hitPt.setY(0)
@@ -1722,16 +1745,17 @@ class ObjectHandles(NodePath, DirectObject):
         # Find the hit point
         # Find the hit point
         if plane == 'x':
         if plane == 'x':
             self.hitPt.assign(planeIntersect(
             self.hitPt.assign(planeIntersect(
-                lineOrigin, lineDir, ORIGIN, X_AXIS))
+                lineOrigin, lineDir, DG.ORIGIN, DG.X_AXIS))
         elif plane == 'y':
         elif plane == 'y':
             self.hitPt.assign(planeIntersect(
             self.hitPt.assign(planeIntersect(
-                lineOrigin, lineDir, ORIGIN, Y_AXIS))
+                lineOrigin, lineDir, DG.ORIGIN, DG.Y_AXIS))
         elif plane == 'z':
         elif plane == 'z':
             self.hitPt.assign(planeIntersect(
             self.hitPt.assign(planeIntersect(
-                lineOrigin, lineDir, ORIGIN, Z_AXIS))
+                lineOrigin, lineDir, DG.ORIGIN, DG.Z_AXIS))
 
 
         return self.hitPt
         return self.hitPt
 
 
+
 def drawBox(lines, center, sideLength):
 def drawBox(lines, center, sideLength):
     l = sideLength * 0.5
     l = sideLength * 0.5
     lines.moveTo(center[0] + l, center[1] + l, center[2] + l)
     lines.moveTo(center[0] + l, center[1] + l, center[2] + l)

+ 49 - 27
direct/src/directtools/DirectSelection.py

@@ -1,13 +1,33 @@
+from panda3d.core import (
+    BitMask32,
+    BoundingSphere,
+    CollisionHandlerQueue,
+    CollisionNode,
+    CollisionRay,
+    CollisionSegment,
+    CollisionSphere,
+    CollisionTraverser,
+    GeomNode,
+    Mat4,
+    NodePath,
+    Point3,
+    TransformState,
+    VBase4,
+    Vec3,
+    Vec4,
+)
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
-from .DirectGlobals import *
-from .DirectUtil import *
-from .DirectGeometry import *
+from . import DirectGlobals as DG
+from .DirectUtil import useDirectRenderStyle
+from .DirectGeometry import LineNodePath
 
 
 COA_ORIGIN = 0
 COA_ORIGIN = 0
 COA_CENTER = 1
 COA_CENTER = 1
 
 
 # MRM: To do: handle broken node paths in selected and deselected dicts
 # MRM: To do: handle broken node paths in selected and deselected dicts
+
+
 class DirectNodePath(NodePath):
 class DirectNodePath(NodePath):
     # A node path augmented with info, bounding box, and utility methods
     # A node path augmented with info, bounding box, and utility methods
     def __init__(self, nodePath, bboxColor=None):
     def __init__(self, nodePath, bboxColor=None):
@@ -47,6 +67,7 @@ class DirectNodePath(NodePath):
     def getMax(self):
     def getMax(self):
         return self.bbox.getMax()
         return self.bbox.getMax()
 
 
+
 class SelectedNodePaths(DirectObject):
 class SelectedNodePaths(DirectObject):
     def __init__(self):
     def __init__(self):
         self.reset()
         self.reset()
@@ -427,7 +448,7 @@ class DirectBoundingBox:
                 'Max:\t\t%s\n' % self.vecAsString(self.max) +
                 'Max:\t\t%s\n' % self.vecAsString(self.max) +
                 'Center:\t\t%s\n' % self.vecAsString(self.center) +
                 'Center:\t\t%s\n' % self.vecAsString(self.center) +
                 'Radius:\t\t%.2f' % self.radius
                 'Radius:\t\t%.2f' % self.radius
-               )
+                )
 
 
 
 
 class SelectionQueue(CollisionHandlerQueue):
 class SelectionQueue(CollisionHandlerQueue):
@@ -439,7 +460,7 @@ class SelectionQueue(CollisionHandlerQueue):
         # Current index and entry in collision queue
         # Current index and entry in collision queue
         self.index = -1
         self.index = -1
         self.entry = None
         self.entry = None
-        self.skipFlags = SKIP_NONE
+        self.skipFlags = DG.SKIP_NONE
         # Create a collision node path attached to the given NP
         # Create a collision node path attached to the given NP
         self.collisionNodePath = NodePath(CollisionNode("collisionNP"))
         self.collisionNodePath = NodePath(CollisionNode("collisionNP"))
         self.setParentNP(parentNP)
         self.setParentNP(parentNP)
@@ -454,7 +475,7 @@ class SelectionQueue(CollisionHandlerQueue):
         # Let the traverser know about the collision node and the queue
         # Let the traverser know about the collision node and the queue
         self.ct.addCollider(self.collisionNodePath, self)
         self.ct.addCollider(self.collisionNodePath, self)
         # List of objects that can't be selected
         # List of objects that can't be selected
-        self.unpickable = UNPICKABLE
+        self.unpickable = DG.UNPICKABLE
         # Derived class must add Collider to complete initialization
         # Derived class must add Collider to complete initialization
 
 
     def setParentNP(self, parentNP):
     def setParentNP(self, parentNP):
@@ -548,10 +569,10 @@ class SelectionQueue(CollisionHandlerQueue):
         v.normalize()
         v.normalize()
         return v.dot(n) >= 0
         return v.dot(n) >= 0
 
 
-    def findNextCollisionEntry(self, skipFlags = SKIP_NONE):
+    def findNextCollisionEntry(self, skipFlags = DG.SKIP_NONE):
         return self.findCollisionEntry(skipFlags, self.index + 1)
         return self.findCollisionEntry(skipFlags, self.index + 1)
 
 
-    def findCollisionEntry(self, skipFlags = SKIP_NONE, startIndex = 0):
+    def findCollisionEntry(self, skipFlags = DG.SKIP_NONE, startIndex = 0):
         # Init self.index and self.entry
         # Init self.index and self.entry
         self.setCurrentIndex(-1)
         self.setCurrentIndex(-1)
         self.setCurrentEntry(None)
         self.setCurrentEntry(None)
@@ -559,29 +580,29 @@ class SelectionQueue(CollisionHandlerQueue):
         for i in range(startIndex, self.getNumEntries()):
         for i in range(startIndex, self.getNumEntries()):
             entry = self.getEntry(i)
             entry = self.getEntry(i)
             nodePath = entry.getIntoNodePath()
             nodePath = entry.getIntoNodePath()
-            if (skipFlags & SKIP_HIDDEN) and nodePath.isHidden():
+            if (skipFlags & DG.SKIP_HIDDEN) and nodePath.isHidden():
                 # Skip if hidden node
                 # Skip if hidden node
                 pass
                 pass
-            elif (skipFlags & SKIP_BACKFACE) and self.isEntryBackfacing(entry):
+            elif (skipFlags & DG.SKIP_BACKFACE) and self.isEntryBackfacing(entry):
                 # Skip, if backfacing poly
                 # Skip, if backfacing poly
                 pass
                 pass
-            elif (skipFlags & SKIP_CAMERA) and \
+            elif (skipFlags & DG.SKIP_CAMERA) and \
                  (base.camera in nodePath.getAncestors()):
                  (base.camera in nodePath.getAncestors()):
                 # Skip if parented to a camera.
                 # Skip if parented to a camera.
                 pass
                 pass
             # Can pick unpickable, use the first visible node
             # Can pick unpickable, use the first visible node
-            elif (skipFlags & SKIP_UNPICKABLE) and\
+            elif (skipFlags & DG.SKIP_UNPICKABLE) and \
                  (nodePath.getName() in self.unpickable):
                  (nodePath.getName() in self.unpickable):
                 # Skip if in unpickable list
                 # Skip if in unpickable list
                 pass
                 pass
-            elif base.direct and\
-                 ((skipFlags & SKIP_WIDGET) and
-                (nodePath.getTag('WidgetName') != base.direct.widget.getName())):
+            elif base.direct and \
+                 ((skipFlags & DG.SKIP_WIDGET) and
+                 (nodePath.getTag('WidgetName') != base.direct.widget.getName())):
                 # Skip if this widget part is not belong to current widget
                 # Skip if this widget part is not belong to current widget
                 pass
                 pass
-            elif base.direct and\
-                 ((skipFlags & SKIP_WIDGET) and base.direct.fControl and
-                (nodePath.getName()[2:] == 'ring')):
+            elif base.direct and \
+                 ((skipFlags & DG.SKIP_WIDGET) and base.direct.fControl and
+                 (nodePath.getName()[2:] == 'ring')):
                 # Skip when ununiformly scale in ortho view
                 # Skip when ununiformly scale in ortho view
                 pass
                 pass
             else:
             else:
@@ -590,6 +611,7 @@ class SelectionQueue(CollisionHandlerQueue):
                 break
                 break
         return self.getCurrentEntry()
         return self.getCurrentEntry()
 
 
+
 class SelectionRay(SelectionQueue):
 class SelectionRay(SelectionQueue):
     def __init__(self, parentNP = None):
     def __init__(self, parentNP = None):
         if parentNP is None:
         if parentNP is None:
@@ -623,7 +645,7 @@ class SelectionRay(SelectionQueue):
 
 
     def pickBitMask(self, bitMask = BitMask32.allOff(),
     def pickBitMask(self, bitMask = BitMask32.allOff(),
                     targetNodePath = None,
                     targetNodePath = None,
-                    skipFlags = SKIP_ALL):
+                    skipFlags = DG.SKIP_ALL):
         if targetNodePath is None:
         if targetNodePath is None:
             targetNodePath = render
             targetNodePath = render
         self.collideWithBitMask(bitMask)
         self.collideWithBitMask(bitMask)
@@ -631,7 +653,7 @@ class SelectionRay(SelectionQueue):
         # Determine collision entry
         # Determine collision entry
         return self.findCollisionEntry(skipFlags)
         return self.findCollisionEntry(skipFlags)
 
 
-    def pickGeom(self, targetNodePath = None, skipFlags = SKIP_ALL,
+    def pickGeom(self, targetNodePath = None, skipFlags = DG.SKIP_ALL,
                  xy = None):
                  xy = None):
         if targetNodePath is None:
         if targetNodePath is None:
             targetNodePath = render
             targetNodePath = render
@@ -640,7 +662,7 @@ class SelectionRay(SelectionQueue):
         # Determine collision entry
         # Determine collision entry
         return self.findCollisionEntry(skipFlags)
         return self.findCollisionEntry(skipFlags)
 
 
-    def pickWidget(self, targetNodePath = None, skipFlags = SKIP_NONE):
+    def pickWidget(self, targetNodePath = None, skipFlags = DG.SKIP_NONE):
         if targetNodePath is None:
         if targetNodePath is None:
             targetNodePath = render
             targetNodePath = render
         self.collideWithWidget()
         self.collideWithWidget()
@@ -657,7 +679,7 @@ class SelectionRay(SelectionQueue):
 
 
     def pickGeom3D(self, targetNodePath = None,
     def pickGeom3D(self, targetNodePath = None,
                    origin = Point3(0), dir = Vec3(0, 0, -1),
                    origin = Point3(0), dir = Vec3(0, 0, -1),
-                   skipFlags = SKIP_HIDDEN | SKIP_CAMERA):
+                   skipFlags = DG.SKIP_HIDDEN | DG.SKIP_CAMERA):
         if targetNodePath is None:
         if targetNodePath is None:
             targetNodePath = render
             targetNodePath = render
         self.collideWithGeom()
         self.collideWithGeom()
@@ -668,7 +690,7 @@ class SelectionRay(SelectionQueue):
     def pickBitMask3D(self, bitMask = BitMask32.allOff(),
     def pickBitMask3D(self, bitMask = BitMask32.allOff(),
                       targetNodePath = None,
                       targetNodePath = None,
                       origin = Point3(0), dir = Vec3(0, 0, -1),
                       origin = Point3(0), dir = Vec3(0, 0, -1),
-                      skipFlags = SKIP_ALL):
+                      skipFlags = DG.SKIP_ALL):
         if targetNodePath is None:
         if targetNodePath is None:
             targetNodePath = render
             targetNodePath = render
         self.collideWithBitMask(bitMask)
         self.collideWithBitMask(bitMask)
@@ -698,7 +720,7 @@ class SelectionSegment(SelectionQueue):
         self.numColliders += 1
         self.numColliders += 1
 
 
     def pickGeom(self, targetNodePath = None, endPointList = [],
     def pickGeom(self, targetNodePath = None, endPointList = [],
-                 skipFlags = SKIP_HIDDEN | SKIP_CAMERA):
+                 skipFlags = DG.SKIP_HIDDEN | DG.SKIP_CAMERA):
         if targetNodePath is None:
         if targetNodePath is None:
             targetNodePath = render
             targetNodePath = render
         self.collideWithGeom()
         self.collideWithGeom()
@@ -713,7 +735,7 @@ class SelectionSegment(SelectionQueue):
 
 
     def pickBitMask(self, bitMask = BitMask32.allOff(),
     def pickBitMask(self, bitMask = BitMask32.allOff(),
                     targetNodePath = None, endPointList = [],
                     targetNodePath = None, endPointList = [],
-                 skipFlags = SKIP_HIDDEN | SKIP_CAMERA):
+                 skipFlags = DG.SKIP_HIDDEN | DG.SKIP_CAMERA):
         if targetNodePath is None:
         if targetNodePath is None:
             targetNodePath = render
             targetNodePath = render
         self.collideWithBitMask(bitMask)
         self.collideWithBitMask(bitMask)
@@ -781,7 +803,7 @@ class SelectionSphere(SelectionQueue):
         return self.findCollisionEntry(skipFlags)
         return self.findCollisionEntry(skipFlags)
 
 
     def pickGeom(self, targetNodePath = None,
     def pickGeom(self, targetNodePath = None,
-                 skipFlags = SKIP_HIDDEN | SKIP_CAMERA):
+                 skipFlags = DG.SKIP_HIDDEN | DG.SKIP_CAMERA):
         if targetNodePath is None:
         if targetNodePath is None:
             targetNodePath = render
             targetNodePath = render
         self.collideWithGeom()
         self.collideWithGeom()
@@ -789,7 +811,7 @@ class SelectionSphere(SelectionQueue):
 
 
     def pickBitMask(self, bitMask = BitMask32.allOff(),
     def pickBitMask(self, bitMask = BitMask32.allOff(),
                     targetNodePath = None,
                     targetNodePath = None,
-                    skipFlags = SKIP_HIDDEN | SKIP_CAMERA):
+                    skipFlags = DG.SKIP_HIDDEN | DG.SKIP_CAMERA):
         if targetNodePath is None:
         if targetNodePath is None:
             targetNodePath = render
             targetNodePath = render
         self.collideWithBitMask(bitMask)
         self.collideWithBitMask(bitMask)

+ 53 - 36
direct/src/directtools/DirectSession.py

@@ -1,26 +1,41 @@
 import math
 import math
 
 
-from panda3d.core import *
-from .DirectUtil import *
+from panda3d.core import (
+    CollisionNode,
+    ConfigVariableBool,
+    ConfigVariableString,
+    CSDefault,
+    NodePath,
+    Point3,
+    TextNode,
+    VBase3,
+    VBase4,
+    Vec3,
+    Vec4,
+    decomposeMatrix,
+    deg2Rad,
+)
+from .DirectUtil import useDirectRenderStyle
 
 
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.BulletinBoardGlobal import bulletinBoard as bboard
 from direct.showbase.BulletinBoardGlobal import bulletinBoard as bboard
 from direct.task import Task
 from direct.task import Task
 
 
-from .DirectGlobals import DIRECT_NO_MOD
+from . import DirectGlobals as DG
 from .DirectCameraControl import DirectCameraControl
 from .DirectCameraControl import DirectCameraControl
 from .DirectManipulation import DirectManipulationControl
 from .DirectManipulation import DirectManipulationControl
 from .DirectSelection import SelectionRay, COA_ORIGIN, SelectedNodePaths
 from .DirectSelection import SelectionRay, COA_ORIGIN, SelectedNodePaths
 from .DirectGrid import DirectGrid
 from .DirectGrid import DirectGrid
 #from DirectGeometry import *
 #from DirectGeometry import *
 from .DirectLights import DirectLights
 from .DirectLights import DirectLights
-from direct.cluster.ClusterClient import createClusterClient, DummyClusterClient
-from direct.cluster.ClusterServer import ClusterServer
 ## from direct.tkpanels import Placer
 ## from direct.tkpanels import Placer
 ## from direct.tkwidgets import Slider
 ## from direct.tkwidgets import Slider
 ## from direct.tkwidgets import SceneGraphExplorer
 ## from direct.tkwidgets import SceneGraphExplorer
 from direct.gui import OnscreenText
 from direct.gui import OnscreenText
-from direct.interval.IntervalGlobal import *
+from direct.interval.IntervalGlobal import Func, Sequence
+from direct.task.TaskManagerGlobal import taskMgr
+from direct.showbase.MessengerGlobal import messenger
+
 
 
 class DirectSession(DirectObject):
 class DirectSession(DirectObject):
 
 
@@ -117,7 +132,6 @@ class DirectSession(DirectObject):
                 for i in range(len(fastrak))[1:]:
                 for i in range(len(fastrak))[1:]:
                     self.fastrak.append(DirectFastrak.DirectFastrak(fastrak[0] + ':' + fastrak[i]))
                     self.fastrak.append(DirectFastrak.DirectFastrak(fastrak[0] + ':' + fastrak[i]))
 
 
-
         self.fControl = 0
         self.fControl = 0
         self.fAlt = 0
         self.fAlt = 0
         self.fShift = 0
         self.fShift = 0
@@ -179,7 +193,7 @@ class DirectSession(DirectObject):
             ['DIRECT-doWrtReparent', self.doWrtReparent],
             ['DIRECT-doWrtReparent', self.doWrtReparent],
             ['DIRECT-doReparent', self.doReparent],
             ['DIRECT-doReparent', self.doReparent],
             ['DIRECT-doSelect', self.doSelect],
             ['DIRECT-doSelect', self.doSelect],
-            ]
+        ]
 
 
         if base.wantTk:
         if base.wantTk:
             from direct.tkpanels import Placer
             from direct.tkpanels import Placer
@@ -248,7 +262,7 @@ class DirectSession(DirectObject):
             'shift-[': ('DIRECT-Undo', 'DIRECT-Undo'),
             'shift-[': ('DIRECT-Undo', 'DIRECT-Undo'),
             ']': ('DIRECT-Redo', 'DIRECT-Redo'),
             ']': ('DIRECT-Redo', 'DIRECT-Redo'),
             'shift-]': ('DIRECT-Redo', 'DIRECT-Redo'),
             'shift-]': ('DIRECT-Redo', 'DIRECT-Redo'),
-            }
+        }
 
 
         self.hotKeyMap = {
         self.hotKeyMap = {
             'c': ('Center Camera', 'DIRECT-centerCamIn'),
             'c': ('Center Camera', 'DIRECT-centerCamIn'),
@@ -276,14 +290,14 @@ class DirectSession(DirectObject):
             'shift-a': ('Toggle Vis all', 'DIRECT-toggleVisAll'),
             'shift-a': ('Toggle Vis all', 'DIRECT-toggleVisAll'),
             'w': ('Toggle Wireframe', 'DIRECT-toggleWireframe'),
             'w': ('Toggle Wireframe', 'DIRECT-toggleWireframe'),
             'control-z': ('Undo', 'LE-Undo'),
             'control-z': ('Undo', 'LE-Undo'),
-            'shift-z' : ('Redo', 'LE-Redo'),
+            'shift-z': ('Redo', 'LE-Redo'),
             'control-d': ('Duplicate', 'LE-Duplicate'),
             'control-d': ('Duplicate', 'LE-Duplicate'),
             'control-l': ('Make Live', 'LE-MakeLive'),
             'control-l': ('Make Live', 'LE-MakeLive'),
             'control-n': ('New Scene', 'LE-NewScene'),
             'control-n': ('New Scene', 'LE-NewScene'),
             'control-s': ('Save Scene', 'LE-SaveScene'),
             'control-s': ('Save Scene', 'LE-SaveScene'),
             'control-o': ('Open Scene', 'LE-OpenScene'),
             'control-o': ('Open Scene', 'LE-OpenScene'),
             'control-q': ('Quit', 'LE-Quit'),
             'control-q': ('Quit', 'LE-Quit'),
-            }
+        }
 
 
         self.speicalKeyMap = {
         self.speicalKeyMap = {
                               'enter': 'DIRECT-enter',
                               'enter': 'DIRECT-enter',
@@ -303,14 +317,16 @@ class DirectSession(DirectObject):
             self.clusterMode = ConfigVariableString("cluster-mode", '').value
             self.clusterMode = ConfigVariableString("cluster-mode", '').value
 
 
         if self.clusterMode == 'client':
         if self.clusterMode == 'client':
+            from direct.cluster.ClusterClient import createClusterClient
             self.cluster = createClusterClient()
             self.cluster = createClusterClient()
         elif self.clusterMode == 'server':
         elif self.clusterMode == 'server':
+            from direct.cluster.ClusterServer import ClusterServer
             self.cluster = ClusterServer(base.camera, base.cam)
             self.cluster = ClusterServer(base.camera, base.cam)
         else:
         else:
+            from direct.cluster.ClusterClient import DummyClusterClient
             self.cluster = DummyClusterClient()
             self.cluster = DummyClusterClient()
         __builtins__['cluster'] = self.cluster
         __builtins__['cluster'] = self.cluster
 
 
-
     def addPassThroughKey(self,key):
     def addPassThroughKey(self,key):
 
 
         self.passThroughKeys.append(key)
         self.passThroughKeys.append(key)
@@ -541,7 +557,7 @@ class DirectSession(DirectObject):
                     base.mouseWatcher = winCtrl.mouseWatcher
                     base.mouseWatcher = winCtrl.mouseWatcher
                     base.mouseWatcherNode = winCtrl.mouseWatcher.node()
                     base.mouseWatcherNode = winCtrl.mouseWatcher.node()
                     base.direct.dr.mouseUpdate()
                     base.direct.dr.mouseUpdate()
-                    LE_showInOneCam(self.selectedNPReadout, self.camera.getName())
+                    DG.LE_showInOneCam(self.selectedNPReadout, self.camera.getName())
                     base.direct.widget = base.direct.manipulationControl.widgetList[base.camList.index(NodePath(winCtrl.camNode))]
                     base.direct.widget = base.direct.manipulationControl.widgetList[base.camList.index(NodePath(winCtrl.camNode))]
 
 
                 input = input[8:] # get rid of camera prefix
                 input = input[8:] # get rid of camera prefix
@@ -590,8 +606,8 @@ class DirectSession(DirectObject):
             self.fControl = 1
             self.fControl = 1
             # [gjeon] to update control key information while mouse1 is pressed
             # [gjeon] to update control key information while mouse1 is pressed
             if self.fMouse1:
             if self.fMouse1:
-                modifiers = DIRECT_NO_MOD
-                modifiers |= DIRECT_CONTROL_MOD
+                modifiers = DG.DIRECT_NO_MOD
+                modifiers |= DG.DIRECT_CONTROL_MOD
                 messenger.send('DIRECT-mouse1', sentArgs = [modifiers])
                 messenger.send('DIRECT-mouse1', sentArgs = [modifiers])
         elif input == 'control-up':
         elif input == 'control-up':
             self.fControl = 0
             self.fControl = 0
@@ -601,16 +617,16 @@ class DirectSession(DirectObject):
             self.fAlt = 1
             self.fAlt = 1
             # [gjeon] to update alt key information while mouse1 is pressed
             # [gjeon] to update alt key information while mouse1 is pressed
             if self.fMouse1:
             if self.fMouse1:
-                modifiers = DIRECT_NO_MOD
-                modifiers |= DIRECT_ALT_MOD
+                modifiers = DG.DIRECT_NO_MOD
+                modifiers |= DG.DIRECT_ALT_MOD
                 messenger.send('DIRECT-mouse1', sentArgs = [modifiers])
                 messenger.send('DIRECT-mouse1', sentArgs = [modifiers])
             elif self.fMouse2:
             elif self.fMouse2:
-                modifiers = DIRECT_NO_MOD
-                modifiers |= DIRECT_ALT_MOD
+                modifiers = DG.DIRECT_NO_MOD
+                modifiers |= DG.DIRECT_ALT_MOD
                 messenger.send('DIRECT-mouse2', sentArgs = [modifiers])
                 messenger.send('DIRECT-mouse2', sentArgs = [modifiers])
             elif self.fMouse3:
             elif self.fMouse3:
-                modifiers = DIRECT_NO_MOD
-                modifiers |= DIRECT_ALT_MOD
+                modifiers = DG.DIRECT_NO_MOD
+                modifiers |= DG.DIRECT_ALT_MOD
                 messenger.send('DIRECT-mouse3', sentArgs = [modifiers])
                 messenger.send('DIRECT-mouse3', sentArgs = [modifiers])
         elif input == 'alt-up':
         elif input == 'alt-up':
             self.fAlt = 0
             self.fAlt = 0
@@ -637,24 +653,24 @@ class DirectSession(DirectObject):
             self.select(self.selected.last)
             self.select(self.selected.last)
 
 
     def getModifiers(self, input, base):
     def getModifiers(self, input, base):
-        modifiers = DIRECT_NO_MOD
+        modifiers = DG.DIRECT_NO_MOD
         modifierString = input[: input.find(base)]
         modifierString = input[: input.find(base)]
         if modifierString.find('shift') != -1:
         if modifierString.find('shift') != -1:
-            modifiers |= DIRECT_SHIFT_MOD
+            modifiers |= DG.DIRECT_SHIFT_MOD
         if modifierString.find('control') != -1:
         if modifierString.find('control') != -1:
-            modifiers |= DIRECT_CONTROL_MOD
+            modifiers |= DG.DIRECT_CONTROL_MOD
         if modifierString.find('alt') != -1:
         if modifierString.find('alt') != -1:
-            modifiers |= DIRECT_ALT_MOD
+            modifiers |= DG.DIRECT_ALT_MOD
         return modifiers
         return modifiers
 
 
     def gotShift(self, modifiers):
     def gotShift(self, modifiers):
-        return modifiers & DIRECT_SHIFT_MOD
+        return modifiers & DG.DIRECT_SHIFT_MOD
 
 
     def gotControl(self, modifiers):
     def gotControl(self, modifiers):
-        return modifiers & DIRECT_CONTROL_MOD
+        return modifiers & DG.DIRECT_CONTROL_MOD
 
 
     def gotAlt(self, modifiers):
     def gotAlt(self, modifiers):
-        return modifiers & DIRECT_ALT_MOD
+        return modifiers & DG.DIRECT_ALT_MOD
 
 
     def setFScaleWidgetByCam(self, flag):
     def setFScaleWidgetByCam(self, flag):
         self.fScaleWidgetByCam = flag
         self.fScaleWidgetByCam = flag
@@ -708,7 +724,7 @@ class DirectSession(DirectObject):
             else:
             else:
                 self.widget.showWidget()
                 self.widget.showWidget()
             editTypes = self.manipulationControl.getEditTypes([dnp])
             editTypes = self.manipulationControl.getEditTypes([dnp])
-            if (editTypes & EDIT_TYPE_UNEDITABLE) == EDIT_TYPE_UNEDITABLE:
+            if (editTypes & DG.EDIT_TYPE_UNEDITABLE) == DG.EDIT_TYPE_UNEDITABLE:
                 self.manipulationControl.disableWidgetMove()
                 self.manipulationControl.disableWidgetMove()
             else:
             else:
                 self.manipulationControl.enableWidgetMove()
                 self.manipulationControl.enableWidgetMove()
@@ -831,7 +847,7 @@ class DirectSession(DirectObject):
             # Temporarily set node path color
             # Temporarily set node path color
             nodePath.setColor(flashColor)
             nodePath.setColor(flashColor)
             # Clean up color in a few seconds
             # Clean up color in a few seconds
-            t = taskMgr.doMethodLater(DIRECT_FLASH_DURATION,
+            t = taskMgr.doMethodLater(DG.DIRECT_FLASH_DURATION,
                                       # This is just a dummy task
                                       # This is just a dummy task
                                       self.flashDummy,
                                       self.flashDummy,
                                       'flashNodePath',)
                                       'flashNodePath',)
@@ -859,6 +875,7 @@ class DirectSession(DirectObject):
             # If nothing specified, try selected node path
             # If nothing specified, try selected node path
             nodePath = self.selected.last
             nodePath = self.selected.last
         base.direct.select(nodePath)
         base.direct.select(nodePath)
+
         def fitTask(state, self = self):
         def fitTask(state, self = self):
             self.cameraControl.fitOnWidget()
             self.cameraControl.fitOnWidget()
             return Task.done
             return Task.done
@@ -1203,12 +1220,13 @@ class DisplayRegionContext(DirectObject):
                          self.near,
                          self.near,
                          (self.nearHeight*0.5) * self.mouseY)
                          (self.nearHeight*0.5) * self.mouseY)
 
 
+
 class DisplayRegionList(DirectObject):
 class DisplayRegionList(DirectObject):
     def __init__(self):
     def __init__(self):
         self.displayRegionList = []
         self.displayRegionList = []
         i = 0
         i = 0
         # Things are funky if we are oobe
         # Things are funky if we are oobe
-        if (hasattr(base, 'oobeMode') and base.oobeMode):
+        if getattr(base, 'oobeMode', False):
             # assume we only have one cam at this point
             # assume we only have one cam at this point
             drc = DisplayRegionContext(base.cam)
             drc = DisplayRegionContext(base.cam)
             self.displayRegionList.append(drc)
             self.displayRegionList.append(drc)
@@ -1224,10 +1242,9 @@ class DisplayRegionList(DirectObject):
             # a display region for each real display region, and then
             # a display region for each real display region, and then
             # keep track of which are currently active (e.g. use a flag)
             # keep track of which are currently active (e.g. use a flag)
             # processing only them.
             # processing only them.
-            for camIndex in range(len(base.camList)):
-                cam = base.camList[camIndex]
-                if cam.getName()=='<noname>':
-                    cam.setName('Camera%d' % camIndex)
+            for camIndex, cam in enumerate(base.camList):
+                if cam.name == '<noname>':
+                    cam.name = f'Camera{camIndex}'
                 drc = DisplayRegionContext(cam)
                 drc = DisplayRegionContext(cam)
                 self.displayRegionList.append(drc)
                 self.displayRegionList.append(drc)
 
 
@@ -1272,7 +1289,7 @@ class DisplayRegionList(DirectObject):
         for dr in self.displayRegionList:
         for dr in self.displayRegionList:
             dr.setVfov(fov)
             dr.setVfov(fov)
 
 
-    def mouseUpdate(self, modifiers = DIRECT_NO_MOD):
+    def mouseUpdate(self, modifiers = DG.DIRECT_NO_MOD):
         for dr in self.displayRegionList:
         for dr in self.displayRegionList:
             dr.mouseUpdate()
             dr.mouseUpdate()
         #base.direct.dr = self.getCurrentDr()
         #base.direct.dr = self.getCurrentDr()

+ 0 - 2
direct/src/directtools/DirectUtil.py

@@ -1,5 +1,3 @@
-
-from .DirectGlobals import *
 from panda3d.core import VBase4
 from panda3d.core import VBase4
 from direct.task.Task import Task
 from direct.task.Task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr

+ 3 - 1
direct/src/directutil/LargeBlobSenderConsts.py

@@ -7,6 +7,8 @@ ChunkSize = 100
 FilePattern = 'largeBlob.%s'
 FilePattern = 'largeBlob.%s'
 
 
 def getLargeBlobPath():
 def getLargeBlobPath():
+    from panda3d.core import ConfigVariableString, ConfigFlags
+
     # this folder needs to be accessible by everyone that is going to level edit
     # this folder needs to be accessible by everyone that is going to level edit
     # an area as a group
     # an area as a group
-    return config.GetString('large-blob-path', 'i:\\toontown_in_game_editor_temp')
+    return ConfigVariableString('large-blob-path', 'i:\\toontown_in_game_editor_temp', 'DConfig', ConfigFlags.F_dconfig).value

+ 22 - 11
direct/src/directutil/Mopath.py

@@ -1,8 +1,20 @@
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
-from direct.directtools.DirectGeometry import *
-
-from panda3d.core import NodePath, LineSegs, ClockObject
+from direct.directtools.DirectUtil import CLAMP
+from direct.task.TaskManagerGlobal import taskMgr
+
+from panda3d.core import (
+    PCTHPR,
+    PCTNONE,
+    PCTT,
+    PCTXYZ,
+    ClockObject,
+    LineSegs,
+    NodePath,
+    ParametricCurve,
+    Point3,
+    Vec3,
+)
 
 
 
 
 class Mopath(DirectObject):
 class Mopath(DirectObject):
@@ -11,7 +23,7 @@ class Mopath(DirectObject):
 
 
     def __init__(self, name = None, fluid = 1, objectToLoad = None, upVectorNodePath = None, reverseUpVector = False):
     def __init__(self, name = None, fluid = 1, objectToLoad = None, upVectorNodePath = None, reverseUpVector = False):
         if name is None:
         if name is None:
-            name = 'mopath%d' % self.nameIndex
+            name = f'mopath{self.nameIndex}'
             self.nameIndex = self.nameIndex + 1
             self.nameIndex = self.nameIndex + 1
         self.name = name
         self.name = name
         self.fluid = fluid
         self.fluid = fluid
@@ -26,12 +38,12 @@ class Mopath(DirectObject):
         self.upVectorNodePath = upVectorNodePath
         self.upVectorNodePath = upVectorNodePath
         self.reverseUpVector = reverseUpVector
         self.reverseUpVector = reverseUpVector
         self.reset()
         self.reset()
-        if isinstance( objectToLoad, NodePath ):
-            self.loadNodePath( objectToLoad )
-        elif isinstance( objectToLoad, str ):
-            self.loadFile( objectToLoad )
+        if isinstance(objectToLoad, NodePath):
+            self.loadNodePath(objectToLoad)
+        elif isinstance(objectToLoad, str):
+            self.loadFile(objectToLoad)
         elif objectToLoad is not None:
         elif objectToLoad is not None:
-            print("Mopath: Unable to load object '%s', objectToLoad must be a file name string or a NodePath" % objectToLoad)
+            print(f"Mopath: Unable to load object '{objectToLoad}', objectToLoad must be a file name string or a NodePath")
 
 
     def getMaxT(self):
     def getMaxT(self):
         return self.maxT * self.timeScale
         return self.maxT * self.timeScale
@@ -49,7 +61,7 @@ class Mopath(DirectObject):
             self.reset()
             self.reset()
 
 
         self.__extractCurves(nodePath)
         self.__extractCurves(nodePath)
-        if self.tNurbsCurve != []:
+        if self.tNurbsCurve:
             self.maxT = self.tNurbsCurve[-1].getMaxT()
             self.maxT = self.tNurbsCurve[-1].getMaxT()
         elif self.xyzNurbsCurve is not None:
         elif self.xyzNurbsCurve is not None:
             self.maxT = self.xyzNurbsCurve.getMaxT()
             self.maxT = self.xyzNurbsCurve.getMaxT()
@@ -58,7 +70,6 @@ class Mopath(DirectObject):
         else:
         else:
             print('Mopath: no valid curves in nodePath: %s' % nodePath)
             print('Mopath: no valid curves in nodePath: %s' % nodePath)
 
 
-
     def reset(self):
     def reset(self):
         self.maxT = 0.0
         self.maxT = 0.0
         self.loop = 0
         self.loop = 0

+ 2 - 0
direct/src/directutil/Verify.py

@@ -45,6 +45,8 @@ Please use assert (properly) and do proper error handling; and use
 where it helps you resist using assert for error handling.
 where it helps you resist using assert for error handling.
 """
 """
 
 
+__all__ = ["verify"]
+
 from panda3d.core import ConfigVariableBool
 from panda3d.core import ConfigVariableBool
 
 
 # Set to true to load pdb on failure.
 # Set to true to load pdb on failure.

+ 64 - 70
direct/src/dist/FreezeTool.py

@@ -22,7 +22,7 @@ try:
 except ImportError:
 except ImportError:
     p3extend_frozen = None
     p3extend_frozen = None
 
 
-from panda3d.core import *
+from panda3d.core import Filename, Multifile, PandaSystem, StringStream
 
 
 # Check to see if we are running python_d, which implies we have a
 # Check to see if we are running python_d, which implies we have a
 # debug build, and we have to build the module with debug options.
 # debug build, and we have to build the module with debug options.
@@ -83,7 +83,9 @@ defaultHiddenImports = {
     'plyer': ['plyer.platforms'],
     'plyer': ['plyer.platforms'],
     'scipy.linalg': ['scipy.linalg.cython_blas', 'scipy.linalg.cython_lapack'],
     'scipy.linalg': ['scipy.linalg.cython_blas', 'scipy.linalg.cython_lapack'],
     'scipy.sparse.csgraph': ['scipy.sparse.csgraph._validation'],
     'scipy.sparse.csgraph': ['scipy.sparse.csgraph._validation'],
+    'scipy.spatial.qhull': ['scipy._lib.messagestream'],
     'scipy.spatial._qhull': ['scipy._lib.messagestream'],
     'scipy.spatial._qhull': ['scipy._lib.messagestream'],
+    'scipy.spatial.transform.rotation': ['scipy.spatial.transform._rotation_groups'],
     'scipy.spatial.transform._rotation': ['scipy.spatial.transform._rotation_groups'],
     'scipy.spatial.transform._rotation': ['scipy.spatial.transform._rotation_groups'],
     'scipy.special._ufuncs': ['scipy.special._ufuncs_cxx'],
     'scipy.special._ufuncs': ['scipy.special._ufuncs_cxx'],
     'scipy.stats._stats': ['scipy.special.cython_special'],
     'scipy.stats._stats': ['scipy.special.cython_special'],
@@ -273,32 +275,32 @@ class CompilationEnvironment:
 
 
     def compileExe(self, filename, basename, extraLink=[]):
     def compileExe(self, filename, basename, extraLink=[]):
         compile = self.compileObjExe % dict({
         compile = self.compileObjExe % dict({
-            'python' : self.Python,
-            'MSVC' : self.MSVC,
-            'PSDK' : self.PSDK,
-            'suffix64' : self.suffix64,
-            'MD' : self.MD,
-            'pythonIPath' : self.PythonIPath,
-            'pythonVersion' : self.PythonVersion,
-            'arch' : self.arch,
-            'filename' : filename,
-            'basename' : basename,
-            }, **sysconf.get_config_vars())
+            'python': self.Python,
+            'MSVC': self.MSVC,
+            'PSDK': self.PSDK,
+            'suffix64': self.suffix64,
+            'MD': self.MD,
+            'pythonIPath': self.PythonIPath,
+            'pythonVersion': self.PythonVersion,
+            'arch': self.arch,
+            'filename': filename,
+            'basename': basename,
+        }, **sysconf.get_config_vars())
         sys.stderr.write(compile + '\n')
         sys.stderr.write(compile + '\n')
         if os.system(compile) != 0:
         if os.system(compile) != 0:
             raise Exception('failed to compile %s.' % basename)
             raise Exception('failed to compile %s.' % basename)
 
 
         link = self.linkExe % dict({
         link = self.linkExe % dict({
-            'python' : self.Python,
-            'MSVC' : self.MSVC,
-            'PSDK' : self.PSDK,
-            'suffix64' : self.suffix64,
-            'pythonIPath' : self.PythonIPath,
-            'pythonVersion' : self.PythonVersion,
-            'arch' : self.arch,
-            'filename' : filename,
-            'basename' : basename,
-            }, **sysconf.get_config_vars())
+            'python': self.Python,
+            'MSVC': self.MSVC,
+            'PSDK': self.PSDK,
+            'suffix64': self.suffix64,
+            'pythonIPath': self.PythonIPath,
+            'pythonVersion': self.PythonVersion,
+            'arch': self.arch,
+            'filename': filename,
+            'basename': basename,
+        }, **sysconf.get_config_vars())
         link += ' ' + ' '.join(extraLink)
         link += ' ' + ' '.join(extraLink)
         sys.stderr.write(link + '\n')
         sys.stderr.write(link + '\n')
         if os.system(link) != 0:
         if os.system(link) != 0:
@@ -306,38 +308,39 @@ class CompilationEnvironment:
 
 
     def compileDll(self, filename, basename, extraLink=[]):
     def compileDll(self, filename, basename, extraLink=[]):
         compile = self.compileObjDll % dict({
         compile = self.compileObjDll % dict({
-            'python' : self.Python,
-            'MSVC' : self.MSVC,
-            'PSDK' : self.PSDK,
-            'suffix64' : self.suffix64,
-            'MD' : self.MD,
-            'pythonIPath' : self.PythonIPath,
-            'pythonVersion' : self.PythonVersion,
-            'arch' : self.arch,
-            'filename' : filename,
-            'basename' : basename,
-            }, **sysconf.get_config_vars())
+            'python': self.Python,
+            'MSVC': self.MSVC,
+            'PSDK': self.PSDK,
+            'suffix64': self.suffix64,
+            'MD': self.MD,
+            'pythonIPath': self.PythonIPath,
+            'pythonVersion': self.PythonVersion,
+            'arch': self.arch,
+            'filename': filename,
+            'basename': basename,
+        }, **sysconf.get_config_vars())
         sys.stderr.write(compile + '\n')
         sys.stderr.write(compile + '\n')
         if os.system(compile) != 0:
         if os.system(compile) != 0:
             raise Exception('failed to compile %s.' % basename)
             raise Exception('failed to compile %s.' % basename)
 
 
         link = self.linkDll % dict({
         link = self.linkDll % dict({
-            'python' : self.Python,
-            'MSVC' : self.MSVC,
-            'PSDK' : self.PSDK,
-            'suffix64' : self.suffix64,
-            'pythonIPath' : self.PythonIPath,
-            'pythonVersion' : self.PythonVersion,
-            'arch' : self.arch,
-            'filename' : filename,
-            'basename' : basename,
-            'dllext' : self.dllext,
-            }, **sysconf.get_config_vars())
+            'python': self.Python,
+            'MSVC': self.MSVC,
+            'PSDK': self.PSDK,
+            'suffix64': self.suffix64,
+            'pythonIPath': self.PythonIPath,
+            'pythonVersion': self.PythonVersion,
+            'arch': self.arch,
+            'filename': filename,
+            'basename': basename,
+            'dllext': self.dllext,
+        }, **sysconf.get_config_vars())
         link += ' ' + ' '.join(extraLink)
         link += ' ' + ' '.join(extraLink)
         sys.stderr.write(link + '\n')
         sys.stderr.write(link + '\n')
         if os.system(link) != 0:
         if os.system(link) != 0:
             raise Exception('failed to link %s.' % basename)
             raise Exception('failed to link %s.' % basename)
 
 
+
 # The code from frozenmain.c in the Python source repository.
 # The code from frozenmain.c in the Python source repository.
 frozenMainCode = """
 frozenMainCode = """
 /* Python interpreter main program for frozen scripts */
 /* Python interpreter main program for frozen scripts */
@@ -673,7 +676,7 @@ okMissing = [
     'direct.extensions_native.extensions_darwin', '_manylinux',
     'direct.extensions_native.extensions_darwin', '_manylinux',
     'collections.Iterable', 'collections.Mapping', 'collections.MutableMapping',
     'collections.Iterable', 'collections.Mapping', 'collections.MutableMapping',
     'collections.Sequence', 'numpy_distutils', '_winapi',
     'collections.Sequence', 'numpy_distutils', '_winapi',
-    ]
+]
 
 
 # Since around macOS 10.15, Apple's codesigning process has become more strict.
 # Since around macOS 10.15, Apple's codesigning process has become more strict.
 # Appending data to the end of a Mach-O binary is now explicitly forbidden. The
 # Appending data to the end of a Mach-O binary is now explicitly forbidden. The
@@ -720,6 +723,7 @@ lc_indices_to_slide = {
     LC_DATA_IN_CODE: [2],
     LC_DATA_IN_CODE: [2],
 }
 }
 
 
+
 class Freezer:
 class Freezer:
     class ModuleDef:
     class ModuleDef:
         def __init__(self, moduleName, filename = None,
         def __init__(self, moduleName, filename = None,
@@ -1139,7 +1143,7 @@ class Freezer:
             if mdef.implicit and '.' in newName:
             if mdef.implicit and '.' in newName:
                 # For implicit modules, check if the parent is excluded.
                 # For implicit modules, check if the parent is excluded.
                 parentName, baseName = newName.rsplit('.', 1)
                 parentName, baseName = newName.rsplit('.', 1)
-                if parentName in excludeDict :
+                if parentName in excludeDict:
                     mdef = excludeDict[parentName]
                     mdef = excludeDict[parentName]
 
 
             if mdef.exclude:
             if mdef.exclude:
@@ -1180,7 +1184,7 @@ class Freezer:
                 self.__loadModule(mdef)
                 self.__loadModule(mdef)
                 # Since it successfully loaded, it's no longer a guess.
                 # Since it successfully loaded, it's no longer a guess.
                 mdef.guess = False
                 mdef.guess = False
-            except:
+            except Exception:
                 # Something went wrong, guess it's not an importable
                 # Something went wrong, guess it's not an importable
                 # module.
                 # module.
                 pass
                 pass
@@ -1218,7 +1222,7 @@ class Freezer:
 
 
             try:
             try:
                 self.__loadModule(self.ModuleDef(modname, implicit=True))
                 self.__loadModule(self.ModuleDef(modname, implicit=True))
-            except:
+            except Exception:
                 missing.append(modname)
                 missing.append(modname)
 
 
         # Now, any new modules we found get added to the export list.
         # Now, any new modules we found get added to the export list.
@@ -1594,7 +1598,7 @@ class Freezer:
         text = programFile % {
         text = programFile % {
             'moduleDefs': '\n'.join(moduleDefs),
             'moduleDefs': '\n'.join(moduleDefs),
             'moduleList': '\n'.join(moduleList),
             'moduleList': '\n'.join(moduleList),
-            }
+        }
 
 
         if self.linkExtensionModules and self.extras:
         if self.linkExtensionModules and self.extras:
             # Should we link in extension modules?  If so, we write out a new
             # Should we link in extension modules?  If so, we write out a new
@@ -1695,11 +1699,11 @@ class Freezer:
             if self.platform.startswith('win'):
             if self.platform.startswith('win'):
                 code += self.frozenDllMainCode
                 code += self.frozenDllMainCode
             initCode = self.mainInitCode % {
             initCode = self.mainInitCode % {
-                'frozenMainCode' : code,
-                'programName' : os.path.basename(basename),
-                'dllexport' : dllexport,
-                'dllimport' : dllimport,
-                }
+                'frozenMainCode': code,
+                'programName': os.path.basename(basename),
+                'dllexport': dllexport,
+                'dllimport': dllimport,
+            }
             if self.platform.startswith('win'):
             if self.platform.startswith('win'):
                 target = basename + '.exe'
                 target = basename + '.exe'
             else:
             else:
@@ -1714,10 +1718,10 @@ class Freezer:
                 target = basename + '.so'
                 target = basename + '.so'
 
 
             initCode = dllInitCode % {
             initCode = dllInitCode % {
-                'moduleName' : os.path.basename(basename),
-                'dllexport' : dllexport,
-                'dllimport' : dllimport,
-                }
+                'moduleName': os.path.basename(basename),
+                'dllexport': dllexport,
+                'dllimport': dllimport,
+            }
             compileFunc = self.cenv.compileDll
             compileFunc = self.cenv.compileDll
 
 
         self.writeCode(filename, initCode=initCode)
         self.writeCode(filename, initCode=initCode)
@@ -2333,17 +2337,8 @@ class Freezer:
         return blob_offset
         return blob_offset
 
 
     def makeModuleDef(self, mangledName, code):
     def makeModuleDef(self, mangledName, code):
-        result = ''
-        result += 'static unsigned char %s[] = {' % (mangledName)
-        for i in range(0, len(code), 16):
-            result += '\n  '
-            for c in code[i:i+16]:
-                if isinstance(c, int): # Python 3
-                    result += ('%d,' % c)
-                else: # Python 2
-                    result += ('%d,' % ord(c))
-        result += '\n};\n'
-        return result
+        lines = ',\n  '.join(','.join(map(str, code[i:i+16])) for i in range(0, len(code), 16))
+        return f'static unsigned char {mangledName}[] = {{\n  {lines}\n}};\n'
 
 
     def makeModuleListEntry(self, mangledName, code, moduleName, module):
     def makeModuleListEntry(self, mangledName, code, moduleName, module):
         size = len(code)
         size = len(code)
@@ -2355,7 +2350,6 @@ class Freezer:
     def makeForbiddenModuleListEntry(self, moduleName):
     def makeForbiddenModuleListEntry(self, moduleName):
         return '  {"%s", NULL, 0},' % (moduleName)
         return '  {"%s", NULL, 0},' % (moduleName)
 
 
-
     def __writingModule(self, moduleName):
     def __writingModule(self, moduleName):
         """ Returns true if we are outputting the named module in this
         """ Returns true if we are outputting the named module in this
         pass, false if we have already output in a previous pass, or
         pass, false if we have already output in a previous pass, or

+ 4 - 3
direct/src/dist/_android.py

@@ -3,9 +3,10 @@
 import xml.etree.ElementTree as ET
 import xml.etree.ElementTree as ET
 
 
 from ._proto.targeting_pb2 import Abi
 from ._proto.targeting_pb2 import Abi
-from ._proto.config_pb2 import BundleConfig
-from ._proto.files_pb2 import NativeLibraries
-from ._proto.Resources_pb2 import XmlNode, ResourceTable
+from ._proto.config_pb2 import BundleConfig # pylint: disable=unused-import
+from ._proto.files_pb2 import NativeLibraries # pylint: disable=unused-import
+from ._proto.Resources_pb2 import ResourceTable # pylint: disable=unused-import
+from ._proto.Resources_pb2 import XmlNode
 
 
 
 
 AbiAlias = Abi.AbiAlias
 AbiAlias = Abi.AbiAlias

+ 5 - 4
direct/src/dist/commands.py

@@ -125,7 +125,7 @@ PACKAGE_LIB_DIRS = {
     'PyQt5':  [('PyQt5/Qt5/bin', 'PyQt5_Qt5')],
     'PyQt5':  [('PyQt5/Qt5/bin', 'PyQt5_Qt5')],
 }
 }
 
 
-SITE_PY = u"""
+SITE_PY = """
 import sys
 import sys
 from _frozen_importlib import _imp, FrozenImporter
 from _frozen_importlib import _imp, FrozenImporter
 
 
@@ -592,7 +592,7 @@ class build_apps(setuptools.Command):
 
 
         whlcache = os.path.join(self.build_base, '__whl_cache__')
         whlcache = os.path.join(self.build_base, '__whl_cache__')
 
 
-        pip_version = int(pip.__version__.split('.')[0])
+        pip_version = int(pip.__version__.split('.', 1)[0])
         if pip_version < 9:
         if pip_version < 9:
             raise RuntimeError("pip 9.0 or greater is required, but found {}".format(pip.__version__))
             raise RuntimeError("pip 9.0 or greater is required, but found {}".format(pip.__version__))
 
 
@@ -1121,7 +1121,7 @@ class build_apps(setuptools.Command):
 
 
                 # Remove python version string
                 # Remove python version string
                 parts = basename.split('.')
                 parts = basename.split('.')
-                if len(parts) >= 3 and '-' in parts[-2]:
+                if len(parts) >= 3 and ('-' in parts[-2] or parts[-2] == 'abi' + str(sys.version_info[0])):
                     parts = parts[:-2] + parts[-1:]
                     parts = parts[:-2] + parts[-1:]
                     basename = '.'.join(parts)
                     basename = '.'.join(parts)
 
 
@@ -1494,7 +1494,8 @@ class build_apps(setuptools.Command):
         for idx in string_tables.keys():
         for idx in string_tables.keys():
             elf.seek(shoff + idx * shentsize)
             elf.seek(shoff + idx * shentsize)
             type, offset, size, link, entsize = struct.unpack_from(section_struct, elf.read(shentsize))
             type, offset, size, link, entsize = struct.unpack_from(section_struct, elf.read(shentsize))
-            if type != 3: continue
+            if type != 3:
+                continue
             elf.seek(offset)
             elf.seek(offset)
             string_tables[idx] = elf.read(size)
             string_tables[idx] = elf.read(size)
 
 

+ 1 - 4
direct/src/dist/icon.py

@@ -1,4 +1,4 @@
-from direct.directnotify.DirectNotifyGlobal import *
+from direct.directnotify.DirectNotifyGlobal import directNotify
 from panda3d.core import PNMImage, Filename, PNMFileTypeRegistry, StringStream
 from panda3d.core import PNMImage, Filename, PNMFileTypeRegistry, StringStream
 import struct
 import struct
 
 
@@ -114,9 +114,6 @@ class Icon:
                 for x in range(size):
                 for x in range(size):
                     pixel = image2.get_pixel(x, size - y - 1)
                     pixel = image2.get_pixel(x, size - y - 1)
                     index = colors.index(pixel)
                     index = colors.index(pixel)
-                    if index >= 256:
-                        # Find closest pixel instead.
-                        index = closest_indices[index - 256]
                     fp.write(struct.pack('<B', index))
                     fp.write(struct.pack('<B', index))
                 fp.write(rowalign)
                 fp.write(rowalign)
         else:
         else:

+ 2 - 2
direct/src/dist/installers.py

@@ -271,7 +271,7 @@ def create_aab(command, basename, build_dir):
     bundle.add_subfile('base/manifest/AndroidManifest.xml', p3d.StringStream(axml.dumps()), 9)
     bundle.add_subfile('base/manifest/AndroidManifest.xml', p3d.StringStream(axml.dumps()), 9)
 
 
     # Add the classes.dex.
     # Add the classes.dex.
-    bundle.add_subfile(f'base/dex/classes.dex', build_dir_fn / 'classes.dex', 9)
+    bundle.add_subfile('base/dex/classes.dex', build_dir_fn / 'classes.dex', 9)
 
 
     # Add libraries, compressed.
     # Add libraries, compressed.
     for abi in os.listdir(os.path.join(build_dir, 'lib')):
     for abi in os.listdir(os.path.join(build_dir, 'lib')):
@@ -302,7 +302,7 @@ def create_aab(command, basename, build_dir):
             # It appears to be encrypted, and we don't have a passphrase, so we
             # It appears to be encrypted, and we don't have a passphrase, so we
             # must request it on the command-line.
             # must request it on the command-line.
             from getpass import getpass
             from getpass import getpass
-            password = getpass(f'Enter pass phrase for private key: ')
+            password = getpass('Enter pass phrase for private key: ')
 
 
         if not bundle.add_jar_signature(
         if not bundle.add_jar_signature(
                 p3d.Filename.from_os_specific(command.signing_certificate),
                 p3d.Filename.from_os_specific(command.signing_certificate),

+ 5 - 3
direct/src/dist/pefile.py

@@ -28,6 +28,7 @@ def _unpack_zstring(mem, offs=0):
         c = mem[offs]
         c = mem[offs]
     return str
     return str
 
 
+
 def _unpack_wstring(mem, offs=0):
 def _unpack_wstring(mem, offs=0):
     "Read a UCS-2 string from memory."
     "Read a UCS-2 string from memory."
     name_len, = unpack('<H', mem[offs:offs+2])
     name_len, = unpack('<H', mem[offs:offs+2])
@@ -37,6 +38,7 @@ def _unpack_wstring(mem, offs=0):
         name += chr(*unpack('<H', mem[offs:offs+2]))
         name += chr(*unpack('<H', mem[offs:offs+2]))
     return name
     return name
 
 
+
 def _padded(n, boundary):
 def _padded(n, boundary):
     align = n % boundary
     align = n % boundary
     if align:
     if align:
@@ -250,11 +252,11 @@ class VersionInfoResource(object):
             self.struct_version = dwords[1]
             self.struct_version = dwords[1]
         if len(dwords) > 3:
         if len(dwords) > 3:
             self.file_version = \
             self.file_version = \
-               (int(dwords[2] >> 16), int(dwords[2] & 0xffff),
+                (int(dwords[2] >> 16), int(dwords[2] & 0xffff),
                 int(dwords[3] >> 16), int(dwords[3] & 0xffff))
                 int(dwords[3] >> 16), int(dwords[3] & 0xffff))
         if len(dwords) > 5:
         if len(dwords) > 5:
             self.product_version = \
             self.product_version = \
-               (int(dwords[4] >> 16), int(dwords[4] & 0xffff),
+                (int(dwords[4] >> 16), int(dwords[4] & 0xffff),
                 int(dwords[5] >> 16), int(dwords[5] & 0xffff))
                 int(dwords[5] >> 16), int(dwords[5] & 0xffff))
         if len(dwords) > 7:
         if len(dwords) > 7:
             self.file_flags_mask = dwords[6]
             self.file_flags_mask = dwords[6]
@@ -302,7 +304,7 @@ class VersionInfoResource(object):
             # It contains a value.
             # It contains a value.
             if type:
             if type:
                 # It's a wchar array value.
                 # It's a wchar array value.
-                value = u""
+                value = ""
                 c, = unpack('<H', data[offset:offset+2])
                 c, = unpack('<H', data[offset:offset+2])
                 offset += 2
                 offset += 2
                 while c:
                 while c:

+ 3 - 2
direct/src/distributed/AsyncRequest.py

@@ -2,7 +2,8 @@
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
-from .ConnectionRepository import *
+from direct.task import Task
+from direct.task.TaskManagerGlobal import taskMgr
 from panda3d.core import ConfigVariableDouble, ConfigVariableInt, ConfigVariableBool
 from panda3d.core import ConfigVariableDouble, ConfigVariableInt, ConfigVariableBool
 
 
 ASYNC_REQUEST_DEFAULT_TIMEOUT_IN_SECONDS = 8.0
 ASYNC_REQUEST_DEFAULT_TIMEOUT_IN_SECONDS = 8.0
@@ -266,4 +267,4 @@ def cleanupAsyncRequests():
     """
     """
     for asyncRequest in AsyncRequest._asyncRequests:
     for asyncRequest in AsyncRequest._asyncRequests:
         asyncRequest.delete()
         asyncRequest.delete()
-    assert AsyncRequest._asyncRequests == {}
+    assert not AsyncRequest._asyncRequests

+ 13 - 1
direct/src/distributed/ClientRepository.py

@@ -3,7 +3,19 @@
 from .ClientRepositoryBase import ClientRepositoryBase
 from .ClientRepositoryBase import ClientRepositoryBase
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
-from .MsgTypesCMU import *
+from .MsgTypesCMU import (
+    CLIENT_DISCONNECT_CMU,
+    CLIENT_HEARTBEAT_CMU,
+    CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU,
+    CLIENT_SET_INTEREST_CMU,
+    OBJECT_DELETE_CMU,
+    OBJECT_DISABLE_CMU,
+    OBJECT_GENERATE_CMU,
+    OBJECT_SET_ZONE_CMU,
+    OBJECT_UPDATE_FIELD_CMU,
+    REQUEST_GENERATES_CMU,
+    SET_DOID_RANGE_CMU,
+)
 from .PyDatagram import PyDatagram
 from .PyDatagram import PyDatagram
 from .PyDatagramIterator import PyDatagramIterator
 from .PyDatagramIterator import PyDatagramIterator
 from panda3d.core import UniqueIdAllocator, Notify, ClockObject
 from panda3d.core import UniqueIdAllocator, Notify, ClockObject

+ 16 - 16
direct/src/distributed/ClientRepositoryBase.py

@@ -1,5 +1,10 @@
-from panda3d.core import *
-from panda3d.direct import *
+from panda3d.core import (
+    ClockObject,
+    ConfigVariableBool,
+    ConfigVariableDouble,
+    Datagram,
+    DatagramIterator,
+)
 from direct.task import Task
 from direct.task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
@@ -7,11 +12,10 @@ from direct.distributed.CRDataCache import CRDataCache
 from direct.distributed.ConnectionRepository import ConnectionRepository
 from direct.distributed.ConnectionRepository import ConnectionRepository
 from direct.showbase.PythonUtil import safeRepr, itype, makeList
 from direct.showbase.PythonUtil import safeRepr, itype, makeList
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
-from .MsgTypes import *
+from .MsgTypes import CLIENT_ENTER_OBJECT_REQUIRED_OTHER, MsgId2Names
 from . import CRCache
 from . import CRCache
 from . import ParentMgr
 from . import ParentMgr
 from . import RelatedObjectMgr
 from . import RelatedObjectMgr
-from .ClockDelta import *
 import time
 import time
 
 
 
 
@@ -106,7 +110,7 @@ class ClientRepositoryBase(ConnectionRepository):
         ## self.flush()
         ## self.flush()
 
 
     def specialName(self, label):
     def specialName(self, label):
-        name = ("SpecialName %s %s" % (self.specialNameNumber, label))
+        name = f"SpecialName {self.specialNameNumber} {label}"
         self.specialNameNumber += 1
         self.specialNameNumber += 1
         return name
         return name
 
 
@@ -118,7 +122,7 @@ class ClientRepositoryBase(ConnectionRepository):
 
 
     def _getMsgName(self, msgId):
     def _getMsgName(self, msgId):
         # we might get a list of message names, use the first one
         # we might get a list of message names, use the first one
-        return makeList(MsgId2Names.get(msgId, 'UNKNOWN MESSAGE: %s' % msgId))[0]
+        return makeList(MsgId2Names.get(msgId, f'UNKNOWN MESSAGE: {msgId}'))[0]
 
 
     def allocateContext(self):
     def allocateContext(self):
         self.context+=1
         self.context+=1
@@ -157,7 +161,7 @@ class ClientRepositoryBase(ConnectionRepository):
         # Look up the dclass
         # Look up the dclass
         assert parentId == self.GameGlobalsId or parentId in self.doId2do
         assert parentId == self.GameGlobalsId or parentId in self.doId2do
         dclass = self.dclassesByNumber[classId]
         dclass = self.dclassesByNumber[classId]
-        assert self.notify.debug("performing generate for %s %s" % (dclass.getName(), doId))
+        assert self.notify.debug(f"performing generate for {dclass.getName()} {doId}")
         dclass.startGenerate()
         dclass.startGenerate()
         # Create a new distributed object, and put it in the dictionary
         # Create a new distributed object, and put it in the dictionary
         distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
         distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
@@ -356,7 +360,6 @@ class ClientRepositoryBase(ConnectionRepository):
             # updateRequiredOtherFields calls announceGenerate
             # updateRequiredOtherFields calls announceGenerate
         return distObj
         return distObj
 
 
-
     def disableDoId(self, doId, ownerView=False):
     def disableDoId(self, doId, ownerView=False):
         table, cache = self.getTables(ownerView)
         table, cache = self.getTables(ownerView)
         # Make sure the object exists
         # Make sure the object exists
@@ -438,7 +441,6 @@ class ClientRepositoryBase(ConnectionRepository):
             # This object has been fully generated.  It's OK to update.
             # This object has been fully generated.  It's OK to update.
             self.__doUpdate(doId, di, ovUpdated)
             self.__doUpdate(doId, di, ovUpdated)
 
 
-
     def __doUpdate(self, doId, di, ovUpdated):
     def __doUpdate(self, doId, di, ovUpdated):
         # Find the DO
         # Find the DO
         do = self.doId2do.get(doId)
         do = self.doId2do.get(doId)
@@ -459,13 +461,12 @@ class ClientRepositoryBase(ConnectionRepository):
                 if handle:
                 if handle:
                     dclass = self.dclassesByName[handle.dclassName]
                     dclass = self.dclassesByName[handle.dclassName]
                     dclass.receiveUpdate(handle, di)
                     dclass.receiveUpdate(handle, di)
-
                 else:
                 else:
                     self.notify.warning(
                     self.notify.warning(
-                        "Asked to update non-existent DistObj " + str(doId))
-            except:
+                        f"Asked to update non-existent DistObj {doId}")
+            except Exception:
                 self.notify.warning(
                 self.notify.warning(
-                        "Asked to update non-existent DistObj " + str(doId) + "and failed to find it")
+                    f"Asked to update non-existent DistObj {doId} and failed to find it")
 
 
     def __doUpdateOwner(self, doId, di):
     def __doUpdateOwner(self, doId, di):
         ovObj = self.doId2ownerView.get(doId)
         ovObj = self.doId2ownerView.get(doId)
@@ -484,7 +485,7 @@ class ClientRepositoryBase(ConnectionRepository):
             self.bootedText = di.getString()
             self.bootedText = di.getString()
 
 
             self.notify.warning(
             self.notify.warning(
-                "Server is booting us out (%d): %s" % (self.bootedIndex, self.bootedText))
+                f"Server is booting us out ({self.bootedIndex}): {self.bootedText}")
         else:
         else:
             self.bootedIndex = None
             self.bootedIndex = None
             self.bootedText = None
             self.bootedText = None
@@ -532,7 +533,6 @@ class ClientRepositoryBase(ConnectionRepository):
                 doDict[doId] = do
                 doDict[doId] = do
         return doDict
         return doDict
 
 
-
     def considerHeartbeat(self):
     def considerHeartbeat(self):
         """Send a heartbeat message if we haven't sent one recently."""
         """Send a heartbeat message if we haven't sent one recently."""
         if not self.heartbeatStarted:
         if not self.heartbeatStarted:
@@ -562,7 +562,7 @@ class ClientRepositoryBase(ConnectionRepository):
 
 
     def waitForNextHeartBeat(self):
     def waitForNextHeartBeat(self):
         taskMgr.doMethodLater(self.heartbeatInterval, self.sendHeartbeatTask,
         taskMgr.doMethodLater(self.heartbeatInterval, self.sendHeartbeatTask,
-                              "heartBeat", taskChain = 'net')
+                              "heartBeat", taskChain='net')
 
 
     def replaceMethod(self, oldMethod, newFunction):
     def replaceMethod(self, oldMethod, newFunction):
         return 0
         return 0

+ 8 - 6
direct/src/distributed/ConnectionRepository.py

@@ -1,5 +1,5 @@
-from panda3d.core import *
-from panda3d.direct import *
+from panda3d.core import DocumentSpec, Filename, HTTPClient, VirtualFileSystem, getModelPath
+from panda3d.direct import CConnectionRepository, DCPacker
 from direct.task import Task
 from direct.task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
@@ -13,6 +13,7 @@ import gc
 
 
 __all__ = ["ConnectionRepository", "GCTrigger"]
 __all__ = ["ConnectionRepository", "GCTrigger"]
 
 
+
 class ConnectionRepository(
 class ConnectionRepository(
         DoInterestManager, DoCollectionManager, CConnectionRepository):
         DoInterestManager, DoCollectionManager, CConnectionRepository):
     """
     """
@@ -233,7 +234,7 @@ class ConnectionRepository(
         distObj.parentId = 0
         distObj.parentId = 0
         distObj.zoneId = 0
         distObj.zoneId = 0
         # updateRequiredFields calls announceGenerate
         # updateRequiredFields calls announceGenerate
-        return  distObj
+        return distObj
 
 
     def readDCFile(self, dcFileNames = None):
     def readDCFile(self, dcFileNames = None):
         """
         """
@@ -382,7 +383,7 @@ class ConnectionRepository(
             # in the DC file.
             # in the DC file.
             for i in range(dcFile.getNumClasses()):
             for i in range(dcFile.getNumClasses()):
                 dclass = dcFile.getClass(i)
                 dclass = dcFile.getClass(i)
-                if (dclass.getName()+ownerDcSuffix) in ownerImportSymbols:
+                if dclass.getName() + ownerDcSuffix in ownerImportSymbols:
                     number = dclass.getNumber()
                     number = dclass.getNumber()
                     className = dclass.getName() + ownerDcSuffix
                     className = dclass.getName() + ownerDcSuffix
 
 
@@ -466,7 +467,7 @@ class ConnectionRepository(
         hasProxy = 0
         hasProxy = 0
         if self.checkHttp():
         if self.checkHttp():
             proxies = self.http.getProxiesForUrl(serverList[0])
             proxies = self.http.getProxiesForUrl(serverList[0])
-            hasProxy = (proxies != 'DIRECT')
+            hasProxy = proxies != 'DIRECT'
 
 
         if hasProxy:
         if hasProxy:
             self.notify.info("Connecting to gameserver via proxy list: %s" % (proxies))
             self.notify.info("Connecting to gameserver via proxy list: %s" % (proxies))
@@ -589,7 +590,7 @@ class ConnectionRepository(
         if self.http is None:
         if self.http is None:
             try:
             try:
                 self.http = HTTPClient()
                 self.http = HTTPClient()
-            except:
+            except Exception:
                 pass
                 pass
 
 
         return self.http
         return self.http
@@ -667,6 +668,7 @@ class ConnectionRepository(
     def uniqueName(self, idString):
     def uniqueName(self, idString):
         return "%s-%s" % (idString, self.uniqueId)
         return "%s-%s" % (idString, self.uniqueId)
 
 
+
 class GCTrigger:
 class GCTrigger:
     # used to trigger garbage collection
     # used to trigger garbage collection
     pass
     pass

+ 3 - 4
direct/src/distributed/DistributedCamera.py

@@ -1,9 +1,8 @@
-from panda3d.core import *
-from panda3d.direct import *
+from panda3d.core import ConfigVariableInt, GeomNode, NodePath, PerspectiveLens, Point3, VBase2
 from direct.fsm.FSM import FSM
 from direct.fsm.FSM import FSM
-from direct.interval.IntervalGlobal import *
+from direct.interval.IntervalGlobal import LerpScaleInterval, Sequence
 from direct.distributed.DistributedObject import DistributedObject
 from direct.distributed.DistributedObject import DistributedObject
-
+from direct.showbase.MessengerGlobal import messenger
 
 
 _camera_id = ConfigVariableInt('camera-id', -1)
 _camera_id = ConfigVariableInt('camera-id', -1)
 _aware_of_cameras = ConfigVariableInt('aware-of-cameras', 0)
 _aware_of_cameras = ConfigVariableInt('aware-of-cameras', 0)

+ 0 - 2
direct/src/distributed/DistributedCameraOV.py

@@ -1,5 +1,3 @@
-from panda3d.core import *
-from panda3d.direct import *
 from direct.distributed.DistributedObjectOV import DistributedObjectOV
 from direct.distributed.DistributedObjectOV import DistributedObjectOV
 
 
 class DistributedCameraOV(DistributedObjectOV):
 class DistributedCameraOV(DistributedObjectOV):

+ 4 - 5
direct/src/distributed/DistributedCartesianGrid.py

@@ -1,19 +1,18 @@
-
-from panda3d.core import *
-from panda3d.direct import *
-from direct.interval.IntervalGlobal import *
+from panda3d.core import ConfigVariableBool, TextNode, VBase4, Vec3
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 
 
 from direct.distributed.DistributedNode import DistributedNode
 from direct.distributed.DistributedNode import DistributedNode
 from direct.task import Task
 from direct.task import Task
+from direct.task.TaskManagerGlobal import taskMgr
 from direct.gui import DirectGuiGlobals
 from direct.gui import DirectGuiGlobals
 from direct.showbase.EventGroup import EventGroup
 from direct.showbase.EventGroup import EventGroup
 from direct.showbase.PythonUtil import report
 from direct.showbase.PythonUtil import report
+from direct.showbase.MessengerGlobal import messenger
 from direct.distributed.GridParent import GridParent
 from direct.distributed.GridParent import GridParent
 
 
 if __debug__:
 if __debug__:
     # For grid drawing
     # For grid drawing
-    from direct.directtools.DirectGeometry import *
+    from direct.directtools.DirectGeometry import LineNodePath
     from direct.showbase.PythonUtil import randFloat
     from direct.showbase.PythonUtil import randFloat
 
 
 from .CartesianGridBase import CartesianGridBase
 from .CartesianGridBase import CartesianGridBase

+ 0 - 3
direct/src/distributed/DistributedCartesianGridAI.py

@@ -1,6 +1,3 @@
-
-from panda3d.core import *
-from panda3d.direct import *
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.task import Task
 from direct.task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr

+ 3 - 5
direct/src/distributed/DistributedObject.py

@@ -1,7 +1,6 @@
 """DistributedObject module: contains the DistributedObject class"""
 """DistributedObject module: contains the DistributedObject class"""
 
 
-from panda3d.core import *
-from panda3d.direct import *
+from panda3d.direct import DCPacker
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
@@ -25,7 +24,7 @@ ESNum2Str = {
     ESDisabled: 'ESDisabled',
     ESDisabled: 'ESDisabled',
     ESGenerating: 'ESGenerating',
     ESGenerating: 'ESGenerating',
     ESGenerated: 'ESGenerated',
     ESGenerated: 'ESGenerated',
-    }
+}
 
 
 
 
 class DistributedObject(DistributedObjectBase):
 class DistributedObject(DistributedObjectBase):
@@ -241,7 +240,6 @@ class DistributedObject(DistributedObjectBase):
         """
         """
         assert self.notify.debug('announceGenerate(): %s' % (self.doId))
         assert self.notify.debug('announceGenerate(): %s' % (self.doId))
 
 
-
     def _deactivateDO(self):
     def _deactivateDO(self):
         # after this is called, the object is no longer an active DistributedObject
         # after this is called, the object is no longer an active DistributedObject
         # and it may be placed in the cache
         # and it may be placed in the cache
@@ -325,9 +323,9 @@ class DistributedObject(DistributedObjectBase):
         """
         """
         return self.doId
         return self.doId
 
 
-
     #This message was moved out of announce generate
     #This message was moved out of announce generate
     #to avoid ordering issues.
     #to avoid ordering issues.
+
     def postGenerateMessage(self):
     def postGenerateMessage(self):
         if self.activeState != ESGenerated:
         if self.activeState != ESGenerated:
             self.activeState = ESGenerated
             self.activeState = ESGenerated

+ 0 - 2
direct/src/distributed/DistributedObjectAI.py

@@ -4,8 +4,6 @@ from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase import PythonUtil
 from direct.showbase import PythonUtil
-from panda3d.core import *
-from panda3d.direct import *
 #from PyDatagram import PyDatagram
 #from PyDatagram import PyDatagram
 #from PyDatagramIterator import PyDatagramIterator
 #from PyDatagramIterator import PyDatagramIterator
 
 

+ 0 - 2
direct/src/distributed/DistributedObjectUD.py

@@ -4,8 +4,6 @@ from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase import PythonUtil
 from direct.showbase import PythonUtil
-from panda3d.core import *
-from panda3d.direct import *
 #from PyDatagram import PyDatagram
 #from PyDatagram import PyDatagram
 #from PyDatagramIterator import PyDatagramIterator
 #from PyDatagramIterator import PyDatagramIterator
 
 

+ 33 - 6
direct/src/distributed/DistributedSmoothNode.py

@@ -1,8 +1,9 @@
 """DistributedSmoothNode module: contains the DistributedSmoothNode class"""
 """DistributedSmoothNode module: contains the DistributedSmoothNode class"""
 
 
-from panda3d.core import *
-from panda3d.direct import *
-from .ClockDelta import *
+import math
+from panda3d.core import ClockObject, ConfigVariableBool, ConfigVariableDouble, NodePath
+from panda3d.direct import SmoothMover
+from .ClockDelta import globalClockDelta
 from . import DistributedNode
 from . import DistributedNode
 from . import DistributedSmoothNodeBase
 from . import DistributedSmoothNodeBase
 from direct.task.Task import cont
 from direct.task.Task import cont
@@ -35,6 +36,8 @@ PredictionLag = ConfigVariableDouble("smooth-prediction-lag", 0.0)
 
 
 GlobalSmoothing = 0
 GlobalSmoothing = 0
 GlobalPrediction = 0
 GlobalPrediction = 0
+
+
 def globalActivateSmoothing(smoothing, prediction):
 def globalActivateSmoothing(smoothing, prediction):
     """ Globally activates or deactivates smoothing and prediction on
     """ Globally activates or deactivates smoothing and prediction on
     all DistributedSmoothNodes currently in existence, or yet to be
     all DistributedSmoothNodes currently in existence, or yet to be
@@ -47,6 +50,7 @@ def globalActivateSmoothing(smoothing, prediction):
     for obj in base.cr.getAllOfType(DistributedSmoothNode):
     for obj in base.cr.getAllOfType(DistributedSmoothNode):
         obj.activateSmoothing(smoothing, prediction)
         obj.activateSmoothing(smoothing, prediction)
 
 
+
 # For historical reasons, we temporarily define
 # For historical reasons, we temporarily define
 # DistributedSmoothNode.activateSmoothing() to be the global function.
 # DistributedSmoothNode.activateSmoothing() to be the global function.
 # We'll remove this soon, so it won't get confused with the instance
 # We'll remove this soon, so it won't get confused with the instance
@@ -153,6 +157,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
 
 
     def setSmoothWrtReparents(self, flag):
     def setSmoothWrtReparents(self, flag):
         self._smoothWrtReparents = flag
         self._smoothWrtReparents = flag
+
     def getSmoothWrtReparents(self):
     def getSmoothWrtReparents(self):
         return self._smoothWrtReparents
         return self._smoothWrtReparents
 
 
@@ -212,42 +217,50 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
     def setSmStop(self, timestamp=None):
     def setSmStop(self, timestamp=None):
         self.setComponentTLive(timestamp)
         self.setComponentTLive(timestamp)
         self.stopped = True
         self.stopped = True
+
     def setSmH(self, h, timestamp=None):
     def setSmH(self, h, timestamp=None):
         self._checkResume(timestamp)
         self._checkResume(timestamp)
         self.setComponentH(h)
         self.setComponentH(h)
         self.setComponentTLive(timestamp)
         self.setComponentTLive(timestamp)
+
     def setSmZ(self, z, timestamp=None):
     def setSmZ(self, z, timestamp=None):
         self._checkResume(timestamp)
         self._checkResume(timestamp)
         self.setComponentZ(z)
         self.setComponentZ(z)
         self.setComponentTLive(timestamp)
         self.setComponentTLive(timestamp)
+
     def setSmXY(self, x, y, timestamp=None):
     def setSmXY(self, x, y, timestamp=None):
         self._checkResume(timestamp)
         self._checkResume(timestamp)
         self.setComponentX(x)
         self.setComponentX(x)
         self.setComponentY(y)
         self.setComponentY(y)
         self.setComponentTLive(timestamp)
         self.setComponentTLive(timestamp)
+
     def setSmXZ(self, x, z, timestamp=None):
     def setSmXZ(self, x, z, timestamp=None):
         self._checkResume(timestamp)
         self._checkResume(timestamp)
         self.setComponentX(x)
         self.setComponentX(x)
         self.setComponentZ(z)
         self.setComponentZ(z)
         self.setComponentTLive(timestamp)
         self.setComponentTLive(timestamp)
+
     def setSmPos(self, x, y, z, timestamp=None):
     def setSmPos(self, x, y, z, timestamp=None):
         self._checkResume(timestamp)
         self._checkResume(timestamp)
         self.setComponentX(x)
         self.setComponentX(x)
         self.setComponentY(y)
         self.setComponentY(y)
         self.setComponentZ(z)
         self.setComponentZ(z)
         self.setComponentTLive(timestamp)
         self.setComponentTLive(timestamp)
+
     def setSmHpr(self, h, p, r, timestamp=None):
     def setSmHpr(self, h, p, r, timestamp=None):
         self._checkResume(timestamp)
         self._checkResume(timestamp)
         self.setComponentH(h)
         self.setComponentH(h)
         self.setComponentP(p)
         self.setComponentP(p)
         self.setComponentR(r)
         self.setComponentR(r)
         self.setComponentTLive(timestamp)
         self.setComponentTLive(timestamp)
+
     def setSmXYH(self, x, y, h, timestamp):
     def setSmXYH(self, x, y, h, timestamp):
         self._checkResume(timestamp)
         self._checkResume(timestamp)
         self.setComponentX(x)
         self.setComponentX(x)
         self.setComponentY(y)
         self.setComponentY(y)
         self.setComponentH(h)
         self.setComponentH(h)
         self.setComponentTLive(timestamp)
         self.setComponentTLive(timestamp)
+
     def setSmXYZH(self, x, y, z, h, timestamp=None):
     def setSmXYZH(self, x, y, z, h, timestamp=None):
         self._checkResume(timestamp)
         self._checkResume(timestamp)
         self.setComponentX(x)
         self.setComponentX(x)
@@ -255,6 +268,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
         self.setComponentZ(z)
         self.setComponentZ(z)
         self.setComponentH(h)
         self.setComponentH(h)
         self.setComponentTLive(timestamp)
         self.setComponentTLive(timestamp)
+
     def setSmPosHpr(self, x, y, z, h, p, r, timestamp=None):
     def setSmPosHpr(self, x, y, z, h, p, r, timestamp=None):
         self._checkResume(timestamp)
         self._checkResume(timestamp)
         self.setComponentX(x)
         self.setComponentX(x)
@@ -284,26 +298,33 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
     @report(types = ['args'], dConfigParam = 'smoothnode')
     @report(types = ['args'], dConfigParam = 'smoothnode')
     def setComponentX(self, x):
     def setComponentX(self, x):
         self.smoother.setX(x)
         self.smoother.setX(x)
+
     @report(types = ['args'], dConfigParam = 'smoothnode')
     @report(types = ['args'], dConfigParam = 'smoothnode')
     def setComponentY(self, y):
     def setComponentY(self, y):
         self.smoother.setY(y)
         self.smoother.setY(y)
+
     @report(types = ['args'], dConfigParam = 'smoothnode')
     @report(types = ['args'], dConfigParam = 'smoothnode')
     def setComponentZ(self, z):
     def setComponentZ(self, z):
         self.smoother.setZ(z)
         self.smoother.setZ(z)
+
     @report(types = ['args'], dConfigParam = 'smoothnode')
     @report(types = ['args'], dConfigParam = 'smoothnode')
     def setComponentH(self, h):
     def setComponentH(self, h):
         self.smoother.setH(h)
         self.smoother.setH(h)
+
     @report(types = ['args'], dConfigParam = 'smoothnode')
     @report(types = ['args'], dConfigParam = 'smoothnode')
     def setComponentP(self, p):
     def setComponentP(self, p):
         self.smoother.setP(p)
         self.smoother.setP(p)
+
     @report(types = ['args'], dConfigParam = 'smoothnode')
     @report(types = ['args'], dConfigParam = 'smoothnode')
     def setComponentR(self, r):
     def setComponentR(self, r):
         self.smoother.setR(r)
         self.smoother.setR(r)
+
     @report(types = ['args'], dConfigParam = 'smoothnode')
     @report(types = ['args'], dConfigParam = 'smoothnode')
     def setComponentL(self, l):
     def setComponentL(self, l):
         if l != self.zoneId:
         if l != self.zoneId:
             # only perform set location if location is different
             # only perform set location if location is different
             self.setLocation(self.parentId,l)
             self.setLocation(self.parentId,l)
+
     @report(types = ['args'], dConfigParam = 'smoothnode')
     @report(types = ['args'], dConfigParam = 'smoothnode')
     def setComponentT(self, timestamp):
     def setComponentT(self, timestamp):
         # This is a little bit hacky.  If *this* function is called,
         # This is a little bit hacky.  If *this* function is called,
@@ -386,18 +407,25 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
     # match set* in more cases than the Disney server does.
     # match set* in more cases than the Disney server does.
     def getComponentL(self):
     def getComponentL(self):
         return self.zoneId
         return self.zoneId
+
     def getComponentX(self):
     def getComponentX(self):
         return self.getX()
         return self.getX()
+
     def getComponentY(self):
     def getComponentY(self):
         return self.getY()
         return self.getY()
+
     def getComponentZ(self):
     def getComponentZ(self):
         return self.getZ()
         return self.getZ()
+
     def getComponentH(self):
     def getComponentH(self):
         return self.getH()
         return self.getH()
+
     def getComponentP(self):
     def getComponentP(self):
         return self.getP()
         return self.getP()
+
     def getComponentR(self):
     def getComponentR(self):
         return self.getR()
         return self.getR()
+
     def getComponentT(self):
     def getComponentT(self):
         return 0
         return 0
 
 
@@ -408,7 +436,6 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
         #printStack()
         #printStack()
         self.smoother.clearPositions(1)
         self.smoother.clearPositions(1)
 
 
-
     @report(types = ['args'], dConfigParam = 'smoothnode')
     @report(types = ['args'], dConfigParam = 'smoothnode')
     def wrtReparentTo(self, parent):
     def wrtReparentTo(self, parent):
         # We override this NodePath method to force it to
         # We override this NodePath method to force it to
@@ -464,6 +491,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
                     "Warning: couldn't find the avatar %d" % (avId))
                     "Warning: couldn't find the avatar %d" % (avId))
             elif hasattr(other, "d_returnResync") and \
             elif hasattr(other, "d_returnResync") and \
                  hasattr(self.cr, 'localAvatarDoId'):
                  hasattr(self.cr, 'localAvatarDoId'):
+                globalClock = ClockObject.getGlobalClock()
                 realTime = globalClock.getRealTime()
                 realTime = globalClock.getRealTime()
                 serverTime = realTime - globalClockDelta.getDelta()
                 serverTime = realTime - globalClockDelta.getDelta()
                 assert self.notify.info(
                 assert self.notify.info(
@@ -474,7 +502,6 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
                     serverTime,
                     serverTime,
                     globalClockDelta.getUncertainty())
                     globalClockDelta.getUncertainty())
 
 
-
     def d_returnResync(self, avId, timestampB, serverTime, uncertainty):
     def d_returnResync(self, avId, timestampB, serverTime, uncertainty):
         serverTimeSec = math.floor(serverTime)
         serverTimeSec = math.floor(serverTime)
         serverTimeUSec = (serverTime - serverTimeSec) * 10000.0
         serverTimeUSec = (serverTime - serverTimeSec) * 10000.0
@@ -482,7 +509,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
             avId, timestampB, serverTimeSec, serverTimeUSec, uncertainty])
             avId, timestampB, serverTimeSec, serverTimeUSec, uncertainty])
 
 
     def returnResync(self, avId, timestampB, serverTimeSec, serverTimeUSec,
     def returnResync(self, avId, timestampB, serverTimeSec, serverTimeUSec,
-            uncertainty):
+                     uncertainty):
         """
         """
         A reply sent by a client whom we recently sent suggestResync
         A reply sent by a client whom we recently sent suggestResync
         to, this reports the client's new delta information so we can
         to, this reports the client's new delta information so we can

+ 5 - 2
direct/src/distributed/DistributedSmoothNodeBase.py

@@ -1,6 +1,6 @@
 """DistributedSmoothNodeBase module: contains the DistributedSmoothNodeBase class"""
 """DistributedSmoothNodeBase module: contains the DistributedSmoothNodeBase class"""
 
 
-from .ClockDelta import *
+from .ClockDelta import globalClockDelta
 from direct.task import Task
 from direct.task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.showbase.PythonUtil import randFloat
 from direct.showbase.PythonUtil import randFloat
@@ -13,8 +13,10 @@ class DummyTaskClass:
     def setDelay(self, blah):
     def setDelay(self, blah):
         pass
         pass
 
 
+
 DummyTask = DummyTaskClass()
 DummyTask = DummyTaskClass()
 
 
+
 class DistributedSmoothNodeBase:
 class DistributedSmoothNodeBase:
     """common base class for DistributedSmoothNode and DistributedSmoothNodeAI
     """common base class for DistributedSmoothNode and DistributedSmoothNodeAI
     """
     """
@@ -43,6 +45,7 @@ class DistributedSmoothNodeBase:
     def b_clearSmoothing(self):
     def b_clearSmoothing(self):
         self.d_clearSmoothing()
         self.d_clearSmoothing()
         self.clearSmoothing()
         self.clearSmoothing()
+
     def d_clearSmoothing(self):
     def d_clearSmoothing(self):
         self.sendUpdate("clearSmoothing", [0])
         self.sendUpdate("clearSmoothing", [0])
 
 
@@ -85,7 +88,7 @@ class DistributedSmoothNodeBase:
             BT.FULL: self.cnode.broadcastPosHprFull,
             BT.FULL: self.cnode.broadcastPosHprFull,
             BT.XYH:  self.cnode.broadcastPosHprXyh,
             BT.XYH:  self.cnode.broadcastPosHprXyh,
             BT.XY:  self.cnode.broadcastPosHprXy,
             BT.XY:  self.cnode.broadcastPosHprXy,
-            }
+        }
         # this comment is here so it will show up in a grep for 'def d_broadcastPosHpr'
         # this comment is here so it will show up in a grep for 'def d_broadcastPosHpr'
         self.d_broadcastPosHpr = broadcastFuncs[self.broadcastType]
         self.d_broadcastPosHpr = broadcastFuncs[self.broadcastType]
 
 

+ 13 - 6
direct/src/distributed/DoInterestManager.py

@@ -7,16 +7,22 @@ zone, remove interest in that zone.
 p.s. A great deal of this code is just code moved from ClientRepository.py.
 p.s. A great deal of this code is just code moved from ClientRepository.py.
 """
 """
 
 
-from panda3d.core import *
-from panda3d.direct import *
-from .MsgTypes import *
-from direct.showbase.PythonUtil import *
+from panda3d.core import ConfigVariableBool
+from .MsgTypes import CLIENT_ADD_INTEREST, CLIENT_ADD_INTEREST_MULTIPLE, CLIENT_REMOVE_INTEREST
 from direct.showbase import DirectObject
 from direct.showbase import DirectObject
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 from .PyDatagram import PyDatagram
 from .PyDatagram import PyDatagram
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 import types
 import types
-from direct.showbase.PythonUtil import report
+from direct.showbase.PythonUtil import (
+    FrameDelayedCall,
+    ScratchPad,
+    SerialNumGen,
+    report,
+    serialNum,
+    uniqueElements,
+    uniqueName,
+)
 
 
 class InterestState:
 class InterestState:
     StateActive = 'Active'
     StateActive = 'Active'
@@ -627,6 +633,7 @@ class DoInterestManager(DirectObject.DirectObject):
 
 
 if __debug__:
 if __debug__:
     import unittest
     import unittest
+    import time
 
 
     class AsyncTestCase(unittest.TestCase):
     class AsyncTestCase(unittest.TestCase):
         def setCompleted(self):
         def setCompleted(self):
@@ -641,7 +648,7 @@ if __debug__:
         suiteClass = AsyncTestSuite
         suiteClass = AsyncTestSuite
 
 
     class AsyncTextTestRunner(unittest.TextTestRunner):
     class AsyncTextTestRunner(unittest.TextTestRunner):
-        def run(self, testCase):
+        def run(self, test):
             result = self._makeResult()
             result = self._makeResult()
             startTime = time.time()
             startTime = time.time()
             test(result)
             test(result)

+ 1 - 1
direct/src/distributed/GridChild.py

@@ -1,6 +1,6 @@
 from direct.distributed.DistributedSmoothNodeBase import DistributedSmoothNodeBase
 from direct.distributed.DistributedSmoothNodeBase import DistributedSmoothNodeBase
 from direct.distributed.GridParent import GridParent
 from direct.distributed.GridParent import GridParent
-from direct.showbase.PythonUtil import report
+from direct.showbase.PythonUtil import report, getBase
 
 
 
 
 class GridChild:
 class GridChild:

+ 1 - 3
direct/src/distributed/GridParent.py

@@ -1,6 +1,4 @@
-
-from panda3d.core import *
-from panda3d.direct import *
+from panda3d.core import NodePath
 
 
 #
 #
 # GridParent.py
 # GridParent.py

+ 2 - 2
direct/src/distributed/MsgTypes.py

@@ -137,7 +137,7 @@ MsgName2Id = {
     'CLIENTAGENT_ADD_INTEREST':                     1200,
     'CLIENTAGENT_ADD_INTEREST':                     1200,
     'CLIENTAGENT_ADD_INTEREST_MULTIPLE':            1201,
     'CLIENTAGENT_ADD_INTEREST_MULTIPLE':            1201,
     'CLIENTAGENT_REMOVE_INTEREST':                  1203,
     'CLIENTAGENT_REMOVE_INTEREST':                  1203,
-    }
+}
 
 
 # create id->name table for debugging
 # create id->name table for debugging
 MsgId2Names = invertDictLossless(MsgName2Id)
 MsgId2Names = invertDictLossless(MsgName2Id)
@@ -157,7 +157,7 @@ QUIET_ZONE_IGNORED_LIST = [
     #CLIENT_CREATE_OBJECT_REQUIRED,
     #CLIENT_CREATE_OBJECT_REQUIRED,
     #CLIENT_CREATE_OBJECT_REQUIRED_OTHER,
     #CLIENT_CREATE_OBJECT_REQUIRED_OTHER,
 
 
-    ]
+]
 
 
 # The following is a different set of numbers from above.
 # The following is a different set of numbers from above.
 # These are the sub-message types for CLIENT_LOGIN_2.
 # These are the sub-message types for CLIENT_LOGIN_2.

+ 1 - 1
direct/src/distributed/MsgTypesCMU.py

@@ -20,7 +20,7 @@ MsgName2Id = {
     'CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU'  : 9011,
     'CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU'  : 9011,
 
 
     'CLIENT_OBJECT_UPDATE_FIELD' : 120,  # Matches MsgTypes.CLIENT_OBJECT_SET_FIELD
     'CLIENT_OBJECT_UPDATE_FIELD' : 120,  # Matches MsgTypes.CLIENT_OBJECT_SET_FIELD
-    }
+}
 
 
 # create id->name table for debugging
 # create id->name table for debugging
 MsgId2Names = invertDictLossless(MsgName2Id)
 MsgId2Names = invertDictLossless(MsgName2Id)

+ 3 - 3
direct/src/distributed/NetMessenger.py

@@ -20,9 +20,9 @@ MESSAGE_TYPES=(
 
 
 # This is the reverse look up for the recipient of the
 # This is the reverse look up for the recipient of the
 # datagram:
 # datagram:
-MESSAGE_STRINGS={}
-for i in zip(MESSAGE_TYPES, range(1, len(MESSAGE_TYPES)+1)):
-    MESSAGE_STRINGS[i[0]]=i[1]
+MESSAGE_STRINGS = {}
+for i in zip(MESSAGE_TYPES, range(1, len(MESSAGE_TYPES) + 1)):
+    MESSAGE_STRINGS[i[0]] = i[1]
 
 
 
 
 class NetMessenger(Messenger):
 class NetMessenger(Messenger):

+ 23 - 3
direct/src/distributed/PyDatagram.py

@@ -4,10 +4,30 @@
 # of the file rather than every time we call the putArg function.
 # of the file rather than every time we call the putArg function.
 
 
 from panda3d.core import Datagram
 from panda3d.core import Datagram
-from panda3d.direct import *
+from panda3d.direct import (
+    STInt8,
+    STInt16,
+    STInt32,
+    STInt64,
+    STUint8,
+    STUint16,
+    STUint32,
+    STUint64,
+    STFloat64,
+    STString,
+    STBlob,
+    STBlob32,
+    STInt16array,
+    STInt32array,
+    STUint16array,
+    STUint32array,
+    STInt8array,
+    STUint8array,
+    STUint32uint8array,
+)
 # Import the type numbers
 # Import the type numbers
 
 
-from direct.distributed.MsgTypes import *
+from direct.distributed.MsgTypes import CONTROL_CHANNEL
 
 
 
 
 class PyDatagram(Datagram):
 class PyDatagram(Datagram):
@@ -28,7 +48,7 @@ class PyDatagram(Datagram):
         STString: (Datagram.addString, None),
         STString: (Datagram.addString, None),
         STBlob: (Datagram.addBlob, None),
         STBlob: (Datagram.addBlob, None),
         STBlob32: (Datagram.addBlob32, None),
         STBlob32: (Datagram.addBlob32, None),
-        }
+    }
 
 
     addChannel = Datagram.addUint64
     addChannel = Datagram.addUint64
 
 

+ 23 - 3
direct/src/distributed/PyDatagramIterator.py

@@ -3,8 +3,28 @@
 # class variable FuncDict and so we can import DCSubatomicType at the top
 # class variable FuncDict and so we can import DCSubatomicType at the top
 # of the file rather than every time we call the putArg function.
 # of the file rather than every time we call the putArg function.
 
 
-from panda3d.core import *
-from panda3d.direct import *
+from panda3d.core import DatagramIterator
+from panda3d.direct import (
+    STInt8,
+    STInt16,
+    STInt32,
+    STInt64,
+    STUint8,
+    STUint16,
+    STUint32,
+    STUint64,
+    STFloat64,
+    STString,
+    STBlob,
+    STBlob32,
+    STInt16array,
+    STInt32array,
+    STUint16array,
+    STUint32array,
+    STInt8array,
+    STUint8array,
+    STUint32uint8array,
+)
 # Import the type numbers
 # Import the type numbers
 
 
 
 
@@ -26,7 +46,7 @@ class PyDatagramIterator(DatagramIterator):
         STString: DatagramIterator.getString,
         STString: DatagramIterator.getString,
         STBlob: DatagramIterator.getBlob,
         STBlob: DatagramIterator.getBlob,
         STBlob32: DatagramIterator.getBlob32,
         STBlob32: DatagramIterator.getBlob32,
-        }
+    }
 
 
     getChannel = DatagramIterator.getUint64
     getChannel = DatagramIterator.getUint64
 
 

+ 2 - 2
direct/src/distributed/SampleObject.py

@@ -1,7 +1,7 @@
 """SampleObject module: contains the SampleObject class"""
 """SampleObject module: contains the SampleObject class"""
 
 
-from direct.directnotify.DirectNotifyGlobal import *
-from direct.distributed.DistributedObject import *
+from direct.directnotify.DirectNotifyGlobal import directNotify
+from direct.distributed.DistributedObject import DistributedObject
 
 
 class SampleObject(DistributedObject):
 class SampleObject(DistributedObject):
 
 

+ 33 - 3
direct/src/distributed/ServerRepository.py

@@ -1,8 +1,38 @@
 """ServerRepository module: contains the ServerRepository class"""
 """ServerRepository module: contains the ServerRepository class"""
 
 
-from panda3d.core import *
-from panda3d.direct import *
-from direct.distributed.MsgTypesCMU import *
+from panda3d.core import (
+    ConfigVariableBool,
+    ConfigVariableDouble,
+    ConfigVariableInt,
+    ConnectionWriter,
+    DatagramIterator,
+    Filename,
+    NetAddress,
+    NetDatagram,
+    PointerToConnection,
+    QueuedConnectionListener,
+    QueuedConnectionManager,
+    QueuedConnectionReader,
+    TPLow,
+    UniqueIdAllocator,
+    VirtualFileSystem,
+    getModelPath,
+)
+from panda3d.direct import DCFile
+from direct.distributed.MsgTypesCMU import (
+    CLIENT_DISCONNECT_CMU,
+    CLIENT_OBJECT_GENERATE_CMU,
+    CLIENT_OBJECT_UPDATE_FIELD,
+    CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU,
+    CLIENT_SET_INTEREST_CMU,
+    OBJECT_DELETE_CMU,
+    OBJECT_DISABLE_CMU,
+    OBJECT_GENERATE_CMU,
+    OBJECT_SET_ZONE_CMU,
+    OBJECT_UPDATE_FIELD_CMU,
+    REQUEST_GENERATES_CMU,
+    SET_DOID_RANGE_CMU,
+)
 from direct.task import Task
 from direct.task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal

+ 2 - 2
direct/src/distributed/TimeManager.py

@@ -1,10 +1,10 @@
-from panda3d.core import *
-from direct.showbase.DirectObject import *
+from panda3d.core import ClockObject, ConfigVariableDouble, ConfigVariableInt
 from direct.task import Task
 from direct.task import Task
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.distributed import DistributedObject
 from direct.distributed import DistributedObject
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 from direct.distributed.ClockDelta import globalClockDelta
 from direct.distributed.ClockDelta import globalClockDelta
+from direct.showbase.MessengerGlobal import messenger
 
 
 
 
 class TimeManager(DistributedObject.DistributedObject):
 class TimeManager(DistributedObject.DistributedObject):

+ 2 - 2
direct/src/distributed/TimeManagerAI.py

@@ -1,5 +1,5 @@
-from panda3d.core import *
-from direct.distributed.ClockDelta import *
+from direct.directnotify import DirectNotifyGlobal
+from direct.distributed.ClockDelta import globalClockDelta
 from direct.distributed import DistributedObjectAI
 from direct.distributed import DistributedObjectAI
 
 
 class TimeManagerAI(DistributedObjectAI.DistributedObjectAI):
 class TimeManagerAI(DistributedObjectAI.DistributedObjectAI):

+ 58 - 58
direct/src/extensions_native/CInterval_extensions.py

@@ -61,66 +61,66 @@ del privPostEvent
 #####################################################################
 #####################################################################
 
 
 def popupControls(self, tl = None):
 def popupControls(self, tl = None):
-        """
-        Popup control panel for interval.
-        """
-        import math
-        # Don't use a regular import, to prevent ModuleFinder from picking
-        # it up as a dependency when building a .p3d package.
-        import importlib
-        EntryScale = importlib.import_module('direct.tkwidgets.EntryScale')
-        tkinter = importlib.import_module('tkinter')
+    """
+    Popup control panel for interval.
+    """
+    import math
+    # Don't use a regular import, to prevent ModuleFinder from picking
+    # it up as a dependency when building a .p3d package.
+    import importlib
+    EntryScale = importlib.import_module('direct.tkwidgets.EntryScale')
+    tkinter = importlib.import_module('tkinter')
 
 
-        if tl is None:
-            tl = tkinter.Toplevel()
-            tl.title('Interval Controls')
-        outerFrame = tkinter.Frame(tl)
-        def entryScaleCommand(t, s=self):
-            s.setT(t)
-            s.pause()
-        self.es = es = EntryScale.EntryScale(
-            outerFrame, text = self.getName(),
-            min = 0, max = math.floor(self.getDuration() * 100) / 100,
-            command = entryScaleCommand)
-        es.set(self.getT(), fCommand = 0)
-        es.pack(expand = 1, fill = tkinter.X)
-        bf = tkinter.Frame(outerFrame)
-        # Jump to start and end
-        def toStart(s=self, es=es):
-            s.setT(0.0)
-            s.pause()
-        def toEnd(s=self):
-            s.setT(s.getDuration())
-            s.pause()
-        jumpToStart = tkinter.Button(bf, text = '<<', command = toStart)
-        # Stop/play buttons
-        def doPlay(s=self, es=es):
-            s.resume(es.get())
+    if tl is None:
+        tl = tkinter.Toplevel()
+        tl.title('Interval Controls')
+    outerFrame = tkinter.Frame(tl)
+    def entryScaleCommand(t, s=self):
+        s.setT(t)
+        s.pause()
+    self.es = es = EntryScale.EntryScale(
+        outerFrame, text = self.getName(),
+        min = 0, max = math.floor(self.getDuration() * 100) / 100,
+        command = entryScaleCommand)
+    es.set(self.getT(), fCommand = 0)
+    es.pack(expand = 1, fill = tkinter.X)
+    bf = tkinter.Frame(outerFrame)
+    # Jump to start and end
+    def toStart(s=self, es=es):
+        s.setT(0.0)
+        s.pause()
+    def toEnd(s=self):
+        s.setT(s.getDuration())
+        s.pause()
+    jumpToStart = tkinter.Button(bf, text = '<<', command = toStart)
+    # Stop/play buttons
+    def doPlay(s=self, es=es):
+        s.resume(es.get())
 
 
-        stop = tkinter.Button(bf, text = 'Stop',
-                      command = lambda s=self: s.pause())
-        play = tkinter.Button(
-            bf, text = 'Play',
-            command = doPlay)
-        jumpToEnd = tkinter.Button(bf, text = '>>', command = toEnd)
-        jumpToStart.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
-        play.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
-        stop.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
-        jumpToEnd.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
-        bf.pack(expand = 1, fill = tkinter.X)
-        outerFrame.pack(expand = 1, fill = tkinter.X)
-        # Add function to update slider during setT calls
-        def update(t, es=es):
-            es.set(t, fCommand = 0)
-        if not hasattr(self, "setTHooks"):
-            self.setTHooks = []
-        self.setTHooks.append(update)
-        self.setWantsTCallback(1)
-        # Clear out function on destroy
-        def onDestroy(e, s=self, u=update):
-            if u in s.setTHooks:
-                s.setTHooks.remove(u)
-        tl.bind('<Destroy>', onDestroy)
+    stop = tkinter.Button(bf, text = 'Stop',
+                  command = lambda s=self: s.pause())
+    play = tkinter.Button(
+        bf, text = 'Play',
+        command = doPlay)
+    jumpToEnd = tkinter.Button(bf, text = '>>', command = toEnd)
+    jumpToStart.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
+    play.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
+    stop.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
+    jumpToEnd.pack(side = tkinter.LEFT, expand = 1, fill = tkinter.X)
+    bf.pack(expand = 1, fill = tkinter.X)
+    outerFrame.pack(expand = 1, fill = tkinter.X)
+    # Add function to update slider during setT calls
+    def update(t, es=es):
+        es.set(t, fCommand = 0)
+    if not hasattr(self, "setTHooks"):
+        self.setTHooks = []
+    self.setTHooks.append(update)
+    self.setWantsTCallback(1)
+    # Clear out function on destroy
+    def onDestroy(e, s=self, u=update):
+        if u in s.setTHooks:
+            s.setTHooks.remove(u)
+    tl.bind('<Destroy>', onDestroy)
 
 
 Dtool_funcToMethod(popupControls, CInterval)
 Dtool_funcToMethod(popupControls, CInterval)
 del popupControls
 del popupControls

+ 21 - 21
direct/src/extensions_native/HTTPChannel_extensions.py

@@ -8,22 +8,22 @@ from .extension_native_helpers import Dtool_funcToMethod
 
 
 
 
 def spawnTask(self, name = None, callback = None, extraArgs = []):
 def spawnTask(self, name = None, callback = None, extraArgs = []):
-        """Spawns a task to service the download recently requested
-        via beginGetDocument(), etc., and/or downloadToFile() or
-        downloadToRam().  If a callback is specified, that function is
-        called when the download is complete, passing in the extraArgs
-        given.
+    """Spawns a task to service the download recently requested
+    via beginGetDocument(), etc., and/or downloadToFile() or
+    downloadToRam().  If a callback is specified, that function is
+    called when the download is complete, passing in the extraArgs
+    given.
 
 
-        Returns the newly-spawned task.
-        """
-        if not name:
-            name = str(self.getUrl())
-        from direct.task import Task
-        from direct.task.TaskManagerGlobal import taskMgr
-        task = Task.Task(self.doTask)
-        task.callback = callback
-        task.callbackArgs = extraArgs
-        return taskMgr.add(task, name)
+    Returns the newly-spawned task.
+    """
+    if not name:
+        name = str(self.getUrl())
+    from direct.task import Task
+    from direct.task.TaskManagerGlobal import taskMgr
+    task = Task.Task(self.doTask)
+    task.callback = callback
+    task.callbackArgs = extraArgs
+    return taskMgr.add(task, name)
 
 
 if hasattr(core, 'HTTPChannel'):
 if hasattr(core, 'HTTPChannel'):
     Dtool_funcToMethod(spawnTask, core.HTTPChannel)
     Dtool_funcToMethod(spawnTask, core.HTTPChannel)
@@ -31,12 +31,12 @@ del spawnTask
 #####################################################################
 #####################################################################
 
 
 def doTask(self, task):
 def doTask(self, task):
-        from direct.task import Task
-        if self.run():
-            return Task.cont
-        if task.callback:
-            task.callback(*task.callbackArgs)
-        return Task.done
+    from direct.task import Task
+    if self.run():
+        return Task.cont
+    if task.callback:
+        task.callback(*task.callbackArgs)
+    return Task.done
 
 
 if hasattr(core, 'HTTPChannel'):
 if hasattr(core, 'HTTPChannel'):
     Dtool_funcToMethod(doTask, core.HTTPChannel)
     Dtool_funcToMethod(doTask, core.HTTPChannel)

+ 147 - 146
direct/src/extensions_native/NodePath_extensions.py

@@ -116,6 +116,7 @@ def remove(self):
         warnings.warn("NodePath.remove() is deprecated.  Use remove_node() instead.", DeprecationWarning, stacklevel=2)
         warnings.warn("NodePath.remove() is deprecated.  Use remove_node() instead.", DeprecationWarning, stacklevel=2)
     # Send message in case anyone needs to do something
     # Send message in case anyone needs to do something
     # before node is deleted
     # before node is deleted
+    from direct.showbase.MessengerGlobal import messenger
     messenger.send('preRemoveNodePath', [self])
     messenger.send('preRemoveNodePath', [self])
     # Remove nodePath
     # Remove nodePath
     self.removeNode()
     self.removeNode()
@@ -493,7 +494,7 @@ def showCS(self, mask = None):
     npc = self.findAllMatches('**/+CollisionNode')
     npc = self.findAllMatches('**/+CollisionNode')
     for p in range(0, npc.getNumPaths()):
     for p in range(0, npc.getNumPaths()):
         np = npc[p]
         np = npc[p]
-        if (mask == None or (np.node().getIntoCollideMask() & mask).getWord()):
+        if mask is None or (np.node().getIntoCollideMask() & mask).getWord():
             np.show()
             np.show()
 
 
 Dtool_funcToMethod(showCS, NodePath)
 Dtool_funcToMethod(showCS, NodePath)
@@ -512,7 +513,7 @@ def hideCS(self, mask = None):
     npc = self.findAllMatches('**/+CollisionNode')
     npc = self.findAllMatches('**/+CollisionNode')
     for p in range(0, npc.getNumPaths()):
     for p in range(0, npc.getNumPaths()):
         np = npc[p]
         np = npc[p]
-        if (mask == None or (np.node().getIntoCollideMask() & mask).getWord()):
+        if mask is None or (np.node().getIntoCollideMask() & mask).getWord():
             np.hide()
             np.hide()
 
 
 Dtool_funcToMethod(hideCS, NodePath)
 Dtool_funcToMethod(hideCS, NodePath)
@@ -667,40 +668,40 @@ del attachCollisionRay
 #####################################################################
 #####################################################################
 def flattenMultitex(self, stateFrom = None, target = None,
 def flattenMultitex(self, stateFrom = None, target = None,
                         useGeom = 0, allowTexMat = 0, win = None):
                         useGeom = 0, allowTexMat = 0, win = None):
-        from panda3d.core import MultitexReducer
-        mr = MultitexReducer()
-        if target is not None:
-            mr.setTarget(target)
-        mr.setUseGeom(useGeom)
-        mr.setAllowTexMat(allowTexMat)
-
-        if win is None:
-            win = base.win
-
-        if stateFrom is None:
-            mr.scan(self)
-        else:
-            mr.scan(self, stateFrom)
-        mr.flatten(win)
+    from panda3d.core import MultitexReducer
+    mr = MultitexReducer()
+    if target is not None:
+        mr.setTarget(target)
+    mr.setUseGeom(useGeom)
+    mr.setAllowTexMat(allowTexMat)
+
+    if win is None:
+        win = base.win
+
+    if stateFrom is None:
+        mr.scan(self)
+    else:
+        mr.scan(self, stateFrom)
+    mr.flatten(win)
 Dtool_funcToMethod(flattenMultitex, NodePath)
 Dtool_funcToMethod(flattenMultitex, NodePath)
 del flattenMultitex
 del flattenMultitex
 #####################################################################
 #####################################################################
 def getNumDescendants(self):
 def getNumDescendants(self):
-        return len(self.findAllMatches('**')) - 1
+    return len(self.findAllMatches('**')) - 1
 Dtool_funcToMethod(getNumDescendants, NodePath)
 Dtool_funcToMethod(getNumDescendants, NodePath)
 del getNumDescendants
 del getNumDescendants
 #####################################################################
 #####################################################################
 def removeNonCollisions(self):
 def removeNonCollisions(self):
-        # remove anything that is not collision-related
-        print("NodePath.removeNonCollisions() is deprecated")
-        stack = [self]
-        while len(stack) > 0:
-                np = stack.pop()
-                # if there are no CollisionNodes under this node, remove it
-                if np.find('**/+CollisionNode').isEmpty():
-                        np.detachNode()
-                else:
-                        stack.extend(np.getChildren())
+    # remove anything that is not collision-related
+    print("NodePath.removeNonCollisions() is deprecated")
+    stack = [self]
+    while len(stack) > 0:
+        np = stack.pop()
+        # if there are no CollisionNodes under this node, remove it
+        if np.find('**/+CollisionNode').isEmpty():
+            np.detachNode()
+        else:
+            stack.extend(np.getChildren())
 Dtool_funcToMethod(removeNonCollisions, NodePath)
 Dtool_funcToMethod(removeNonCollisions, NodePath)
 del removeNonCollisions
 del removeNonCollisions
 #####################################################################
 #####################################################################
@@ -729,130 +730,130 @@ def subdivideCollisions(self, numSolidsInLeaves):
         colNp.stash()
         colNp.stash()
 
 
 def r_subdivideCollisions(self, solids, numSolidsInLeaves):
 def r_subdivideCollisions(self, solids, numSolidsInLeaves):
-        # takes a list of solids, returns a list containing some number of lists,
-        # with the solids evenly distributed between them (recursively nested until
-        # the lists at the leaves contain no more than numSolidsInLeaves)
-        # if solids is already small enough, returns solids unchanged
-        if len(solids) <= numSolidsInLeaves:
-            return solids
-        origins = []
-        avgX = 0
-        avgY = 0
-        avgZ = 0
-        minX = None
-        minY = None
-        minZ = None
-        maxX = None
-        maxY = None
-        maxZ = None
-        for solid in solids:
-            origin = solid.getCollisionOrigin()
-            origins.append(origin)
-            x = origin.getX()
-            y = origin.getY()
-            z = origin.getZ()
-            avgX += x
-            avgY += y
-            avgZ += z
-            if minX is None:
-                minX = x
-                minY = y
-                minZ = z
-                maxX = x
-                maxY = y
-                maxZ = z
+    # takes a list of solids, returns a list containing some number of lists,
+    # with the solids evenly distributed between them (recursively nested until
+    # the lists at the leaves contain no more than numSolidsInLeaves)
+    # if solids is already small enough, returns solids unchanged
+    if len(solids) <= numSolidsInLeaves:
+        return solids
+    origins = []
+    avgX = 0
+    avgY = 0
+    avgZ = 0
+    minX = None
+    minY = None
+    minZ = None
+    maxX = None
+    maxY = None
+    maxZ = None
+    for solid in solids:
+        origin = solid.getCollisionOrigin()
+        origins.append(origin)
+        x = origin.getX()
+        y = origin.getY()
+        z = origin.getZ()
+        avgX += x
+        avgY += y
+        avgZ += z
+        if minX is None:
+            minX = x
+            minY = y
+            minZ = z
+            maxX = x
+            maxY = y
+            maxZ = z
+        else:
+            minX = min(x, minX)
+            minY = min(y, minY)
+            minZ = min(z, minZ)
+            maxX = max(x, maxX)
+            maxY = max(y, maxY)
+            maxZ = max(z, maxZ)
+    avgX /= len(solids)
+    avgY /= len(solids)
+    avgZ /= len(solids)
+    extentX = maxX - minX
+    extentY = maxY - minY
+    extentZ = maxZ - minZ
+    maxExtent = max(extentX, extentY, extentZ)
+    # sparse octree
+    xyzSolids = []
+    XyzSolids = []
+    xYzSolids = []
+    XYzSolids = []
+    xyZSolids = []
+    XyZSolids = []
+    xYZSolids = []
+    XYZSolids = []
+    midX = avgX
+    midY = avgY
+    midZ = avgZ
+    # throw out axes that are not close to the max axis extent; try and keep
+    # the divisions square/spherical
+    if extentX < (maxExtent * .75) or extentX > (maxExtent * 1.25):
+        midX += maxExtent
+    if extentY < (maxExtent * .75) or extentY > (maxExtent * 1.25):
+        midY += maxExtent
+    if extentZ < (maxExtent * .75) or extentZ > (maxExtent * 1.25):
+        midZ += maxExtent
+    for i, solid in enumerate(solids):
+        origin = origins[i]
+        x = origin.getX()
+        y = origin.getY()
+        z = origin.getZ()
+        if x < midX:
+            if y < midY:
+                if z < midZ:
+                    xyzSolids.append(solids[i])
+                else:
+                    xyZSolids.append(solids[i])
             else:
             else:
-                minX = min(x, minX)
-                minY = min(y, minY)
-                minZ = min(z, minZ)
-                maxX = max(x, maxX)
-                maxY = max(y, maxY)
-                maxZ = max(z, maxZ)
-        avgX /= len(solids)
-        avgY /= len(solids)
-        avgZ /= len(solids)
-        extentX = maxX - minX
-        extentY = maxY - minY
-        extentZ = maxZ - minZ
-        maxExtent = max(max(extentX, extentY), extentZ)
-        # sparse octree
-        xyzSolids = []
-        XyzSolids = []
-        xYzSolids = []
-        XYzSolids = []
-        xyZSolids = []
-        XyZSolids = []
-        xYZSolids = []
-        XYZSolids = []
-        midX = avgX
-        midY = avgY
-        midZ = avgZ
-        # throw out axes that are not close to the max axis extent; try and keep
-        # the divisions square/spherical
-        if extentX < (maxExtent * .75) or extentX > (maxExtent * 1.25):
-            midX += maxExtent
-        if extentY < (maxExtent * .75) or extentY > (maxExtent * 1.25):
-            midY += maxExtent
-        if extentZ < (maxExtent * .75) or extentZ > (maxExtent * 1.25):
-            midZ += maxExtent
-        for i, solid in enumerate(solids):
-            origin = origins[i]
-            x = origin.getX()
-            y = origin.getY()
-            z = origin.getZ()
-            if x < midX:
-                if y < midY:
-                    if z < midZ:
-                        xyzSolids.append(solids[i])
-                    else:
-                        xyZSolids.append(solids[i])
+                if z < midZ:
+                    xYzSolids.append(solids[i])
                 else:
                 else:
-                    if z < midZ:
-                        xYzSolids.append(solids[i])
-                    else:
-                        xYZSolids.append(solids[i])
+                    xYZSolids.append(solids[i])
+        else:
+            if y < midY:
+                if z < midZ:
+                    XyzSolids.append(solids[i])
+                else:
+                    XyZSolids.append(solids[i])
             else:
             else:
-                if y < midY:
-                    if z < midZ:
-                        XyzSolids.append(solids[i])
-                    else:
-                        XyZSolids.append(solids[i])
+                if z < midZ:
+                    XYzSolids.append(solids[i])
                 else:
                 else:
-                    if z < midZ:
-                        XYzSolids.append(solids[i])
-                    else:
-                        XYZSolids.append(solids[i])
-        newSolids = []
-        if len(xyzSolids) > 0:
-            newSolids.append(self.r_subdivideCollisions(xyzSolids, numSolidsInLeaves))
-        if len(XyzSolids) > 0:
-            newSolids.append(self.r_subdivideCollisions(XyzSolids, numSolidsInLeaves))
-        if len(xYzSolids) > 0:
-            newSolids.append(self.r_subdivideCollisions(xYzSolids, numSolidsInLeaves))
-        if len(XYzSolids) > 0:
-            newSolids.append(self.r_subdivideCollisions(XYzSolids, numSolidsInLeaves))
-        if len(xyZSolids) > 0:
-            newSolids.append(self.r_subdivideCollisions(xyZSolids, numSolidsInLeaves))
-        if len(XyZSolids) > 0:
-            newSolids.append(self.r_subdivideCollisions(XyZSolids, numSolidsInLeaves))
-        if len(xYZSolids) > 0:
-            newSolids.append(self.r_subdivideCollisions(xYZSolids, numSolidsInLeaves))
-        if len(XYZSolids) > 0:
-            newSolids.append(self.r_subdivideCollisions(XYZSolids, numSolidsInLeaves))
-        #import pdb;pdb.set_trace()
-        return newSolids
+                    XYZSolids.append(solids[i])
+    newSolids = []
+    if len(xyzSolids) > 0:
+        newSolids.append(self.r_subdivideCollisions(xyzSolids, numSolidsInLeaves))
+    if len(XyzSolids) > 0:
+        newSolids.append(self.r_subdivideCollisions(XyzSolids, numSolidsInLeaves))
+    if len(xYzSolids) > 0:
+        newSolids.append(self.r_subdivideCollisions(xYzSolids, numSolidsInLeaves))
+    if len(XYzSolids) > 0:
+        newSolids.append(self.r_subdivideCollisions(XYzSolids, numSolidsInLeaves))
+    if len(xyZSolids) > 0:
+        newSolids.append(self.r_subdivideCollisions(xyZSolids, numSolidsInLeaves))
+    if len(XyZSolids) > 0:
+        newSolids.append(self.r_subdivideCollisions(XyZSolids, numSolidsInLeaves))
+    if len(xYZSolids) > 0:
+        newSolids.append(self.r_subdivideCollisions(xYZSolids, numSolidsInLeaves))
+    if len(XYZSolids) > 0:
+        newSolids.append(self.r_subdivideCollisions(XYZSolids, numSolidsInLeaves))
+    #import pdb;pdb.set_trace()
+    return newSolids
 
 
 def r_constructCollisionTree(self, solidTree, parentNode, colName):
 def r_constructCollisionTree(self, solidTree, parentNode, colName):
-        from panda3d.core import CollisionNode
-        for item in solidTree:
-            if isinstance(item[0], list):
-                newNode = parentNode.attachNewNode('%s-branch' % colName)
-                self.r_constructCollisionTree(item, newNode, colName)
-            else:
-                cn = CollisionNode('%s-leaf' % colName)
-                for solid in item:
-                    cn.addSolid(solid)
-                parentNode.attachNewNode(cn)
+    from panda3d.core import CollisionNode
+    for item in solidTree:
+        if isinstance(item[0], list):
+            newNode = parentNode.attachNewNode(f'{colName}-branch')
+            self.r_constructCollisionTree(item, newNode, colName)
+        else:
+            cn = CollisionNode(f'{colName}-leaf')
+            for solid in item:
+                cn.addSolid(solid)
+            parentNode.attachNewNode(cn)
 
 
 Dtool_funcToMethod(subdivideCollisions, NodePath)
 Dtool_funcToMethod(subdivideCollisions, NodePath)
 Dtool_funcToMethod(r_subdivideCollisions, NodePath)
 Dtool_funcToMethod(r_subdivideCollisions, NodePath)

+ 1 - 1
direct/src/filter/CommonFilters.py

@@ -351,7 +351,7 @@ class CommonFilters:
             text += "{\n"
             text += "{\n"
             text += "  o_color = tex2D(k_txcolor, %s);\n" % (texcoords["color"])
             text += "  o_color = tex2D(k_txcolor, %s);\n" % (texcoords["color"])
             if "CartoonInk" in configuration:
             if "CartoonInk" in configuration:
-                text += CARTOON_BODY % {"texcoord" : texcoords["aux"]}
+                text += CARTOON_BODY % {"texcoord": texcoords["aux"]}
             if "AmbientOcclusion" in configuration:
             if "AmbientOcclusion" in configuration:
                 text += "  o_color *= tex2D(k_txssao2, %s).r;\n" % (texcoords["ssao2"])
                 text += "  o_color *= tex2D(k_txssao2, %s).r;\n" % (texcoords["ssao2"])
             if "BlurSharpen" in configuration:
             if "BlurSharpen" in configuration:

+ 3 - 3
direct/src/filter/FilterManager.py

@@ -25,7 +25,7 @@ from panda3d.core import Camera
 from panda3d.core import OrthographicLens
 from panda3d.core import OrthographicLens
 from panda3d.core import AuxBitplaneAttrib
 from panda3d.core import AuxBitplaneAttrib
 from panda3d.core import LightRampAttrib
 from panda3d.core import LightRampAttrib
-from direct.directnotify.DirectNotifyGlobal import *
+from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 
 
 __all__ = ["FilterManager"]
 __all__ = ["FilterManager"]
@@ -348,10 +348,10 @@ class FilterManager(DirectObject):
 
 
     def resizeBuffers(self):
     def resizeBuffers(self):
         """ Resize all buffers to match the size of the window. """
         """ Resize all buffers to match the size of the window. """
-        for i in range(len(self.buffers)):
+        for i, buffer in enumerate(self.buffers):
             (mul, div, align) = self.sizes[i]
             (mul, div, align) = self.sizes[i]
             (xsize, ysize) = self.getScaledSize(mul, div, align)
             (xsize, ysize) = self.getScaledSize(mul, div, align)
-            self.buffers[i].setSize(xsize, ysize)
+            buffer.setSize(xsize, ysize)
 
 
     def cleanup(self):
     def cleanup(self):
         """ Restore everything to its original state, deleting any
         """ Restore everything to its original state, deleting any

+ 4 - 8
direct/src/fsm/ClassicFSM.py

@@ -16,7 +16,6 @@ if __debug__:
     _debugFsms = {}
     _debugFsms = {}
 
 
     def printDebugFsmList():
     def printDebugFsmList():
-        global _debugFsms
         for k in sorted(_debugFsms.keys()):
         for k in sorted(_debugFsms.keys()):
             print("%s %s" % (k, _debugFsms[k]()))
             print("%s %s" % (k, _debugFsms[k]()))
     __builtins__['debugFsmList'] = printDebugFsmList
     __builtins__['debugFsmList'] = printDebugFsmList
@@ -83,7 +82,6 @@ class ClassicFSM(DirectObject):
         # doing this.
         # doing this.
         self.__internalStateInFlux = 0
         self.__internalStateInFlux = 0
         if __debug__:
         if __debug__:
-            global _debugFsms
             _debugFsms[name] = weakref.ref(self)
             _debugFsms[name] = weakref.ref(self)
 
 
     # I know this isn't how __repr__ is supposed to be used, but it
     # I know this isn't how __repr__ is supposed to be used, but it
@@ -95,12 +93,12 @@ class ClassicFSM(DirectObject):
         """
         """
         Print out something useful about the fsm
         Print out something useful about the fsm
         """
         """
+        name = self.getName()
         currentState = self.getCurrentState()
         currentState = self.getCurrentState()
         if currentState:
         if currentState:
-            str = ("ClassicFSM " + self.getName() + ' in state "' +
-                   currentState.getName() + '"')
+            str = f'ClassicFSM {name} in state "{currentState.getName()}"'
         else:
         else:
-            str = ("ClassicFSM " + self.getName() + ' not in any state')
+            str = f'ClassicFSM {name} not in any state'
         return str
         return str
 
 
     def enterInitialState(self, argList=[]):
     def enterInitialState(self, argList=[]):
@@ -152,7 +150,6 @@ class ClassicFSM(DirectObject):
     def getCurrentState(self):
     def getCurrentState(self):
         return self.__currentState
         return self.__currentState
 
 
-
     # lookup funcs
     # lookup funcs
 
 
     def getStateNamed(self, stateName):
     def getStateNamed(self, stateName):
@@ -317,7 +314,6 @@ class ClassicFSM(DirectObject):
                 ClassicFSM.notify.warning(msg)
                 ClassicFSM.notify.warning(msg)
             return 0
             return 0
 
 
-
     def forceTransition(self, aStateName, enterArgList=[], exitArgList=[]):
     def forceTransition(self, aStateName, enterArgList=[], exitArgList=[]):
         """
         """
         force a transition -- for debugging ONLY
         force a transition -- for debugging ONLY
@@ -357,7 +353,7 @@ class ClassicFSM(DirectObject):
             self.__currentState.isTransitionDefined(aStateName) or
             self.__currentState.isTransitionDefined(aStateName) or
             aStateName in [self.__currentState.getName(),
             aStateName in [self.__currentState.getName(),
                            self.__finalState.getName()]
                            self.__finalState.getName()]
-            )
+        )
 
 
         if transitionDefined:
         if transitionDefined:
             return self.request(aStateName, enterArgList, exitArgList)
             return self.request(aStateName, enterArgList, exitArgList)

+ 2 - 3
direct/src/fsm/FSM.py

@@ -615,9 +615,8 @@ class FSM(DirectObject):
         try:
         try:
             className = self.__class__.__name__
             className = self.__class__.__name__
             if self.state:
             if self.state:
-                str = ('%s FSM:%s in state "%s"' % (className, self._name, self.state))
+                return f'{className} FSM:{self._name} in state "{self.state}"'
             else:
             else:
-                str = ('%s FSM:%s in transition from \'%s\' to \'%s\'' % (className, self._name, self.oldState, self.newState))
-            return str
+                return f'{className} FSM:{self._name} in transition from \'{self.oldState}\' to \'{self.newState}\''
         finally:
         finally:
             self.fsmLock.release()
             self.fsmLock.release()

+ 1 - 1
direct/src/fsm/FourState.py

@@ -115,7 +115,7 @@ class FourState:
                            self.enterState4,
                            self.enterState4,
                            self.exitState4,
                            self.exitState4,
                            [names[1]]),
                            [names[1]]),
-            }
+        }
         self.fsm = ClassicFSM.ClassicFSM('FourState',
         self.fsm = ClassicFSM.ClassicFSM('FourState',
                            list(self.states.values()),
                            list(self.states.values()),
                            # Initial State
                            # Initial State

+ 4 - 1
direct/src/fsm/FourStateAI.py

@@ -123,7 +123,7 @@ class FourStateAI:
                            self.enterState4,
                            self.enterState4,
                            self.exitState4,
                            self.exitState4,
                            [names[1]]),
                            [names[1]]),
-            }
+        }
         self.fsm = ClassicFSM.ClassicFSM('FourState',
         self.fsm = ClassicFSM.ClassicFSM('FourState',
                            list(self.states.values()),
                            list(self.states.values()),
                            # Initial State
                            # Initial State
@@ -145,6 +145,9 @@ class FourStateAI:
         assert self.__debugPrint("getState() returning %s"%(self.stateIndex,))
         assert self.__debugPrint("getState() returning %s"%(self.stateIndex,))
         return [self.stateIndex]
         return [self.stateIndex]
 
 
+    def sendUpdate(self, fieldName, args = [], sendToId = None):
+        raise NotImplementedError
+
     def sendState(self):
     def sendState(self):
         assert self.__debugPrint("sendState()")
         assert self.__debugPrint("sendState()")
         self.sendUpdate('setState', self.getState())
         self.sendUpdate('setState', self.getState())

+ 1 - 1
direct/src/fsm/SampleFSM.py

@@ -16,7 +16,7 @@ class ClassicStyle(FSM.FSM):
             'Red': ['Green'],
             'Red': ['Green'],
             'Yellow': ['Red'],
             'Yellow': ['Red'],
             'Green': ['Yellow'],
             'Green': ['Yellow'],
-            }
+        }
 
 
     def enterRed(self):
     def enterRed(self):
         print("enterRed(self, '%s', '%s')" % (self.oldState, self.newState))
         print("enterRed(self, '%s', '%s')" % (self.oldState, self.newState))

+ 12 - 12
direct/src/fsm/StatePush.py

@@ -251,12 +251,12 @@ class FunctionCall(ReceivesMultipleStateChanges, PushesStateChanges):
 
 
 if __debug__:
 if __debug__:
     l = []
     l = []
-    def handler(value, l=l):
+    def handler1(value, l=l):
         l.append(value)
         l.append(value)
-    assert l == []
+    assert not l
     sv = StateVar(0)
     sv = StateVar(0)
-    fc = FunctionCall(handler, sv)
-    assert l == []
+    fc = FunctionCall(handler1, sv)
+    assert not l
     fc.pushCurrentState()
     fc.pushCurrentState()
     assert l == [0,]
     assert l == [0,]
     sv.set(1)
     sv.set(1)
@@ -267,17 +267,17 @@ if __debug__:
     sv.destroy()
     sv.destroy()
     del fc
     del fc
     del sv
     del sv
-    del handler
+    del handler1
     del l
     del l
 
 
     l = []
     l = []
-    def handler(value, kDummy=None, kValue=None, l=l):
+    def handler2(value, kDummy=None, kValue=None, l=l):
         l.append((value, kValue))
         l.append((value, kValue))
-    assert l == []
+    assert not l
     sv = StateVar(0)
     sv = StateVar(0)
     ksv = StateVar('a')
     ksv = StateVar('a')
-    fc = FunctionCall(handler, sv, kValue=ksv)
-    assert l == []
+    fc = FunctionCall(handler2, sv, kValue=ksv)
+    assert not l
     fc.pushCurrentState()
     fc.pushCurrentState()
     assert l == [(0,'a',),]
     assert l == [(0,'a',),]
     sv.set(1)
     sv.set(1)
@@ -288,7 +288,7 @@ if __debug__:
     sv.destroy()
     sv.destroy()
     del fc
     del fc
     del sv
     del sv
-    del handler
+    del handler2
     del l
     del l
 
 
 class EnterExit(StateChangeNode):
 class EnterExit(StateChangeNode):
@@ -323,7 +323,7 @@ if __debug__:
     sv = StateVar(0)
     sv = StateVar(0)
     ee = EnterExit(sv, enter, exit)
     ee = EnterExit(sv, enter, exit)
     sv.set(0)
     sv.set(0)
-    assert l == []
+    assert not l
     sv.set(1)
     sv.set(1)
     assert l == [1,]
     assert l == [1,]
     sv.set(2)
     sv.set(2)
@@ -357,7 +357,7 @@ if __debug__:
         l.append(value)
         l.append(value)
     p = Pulse()
     p = Pulse()
     fc = FunctionCall(handler, p)
     fc = FunctionCall(handler, p)
-    assert l == []
+    assert not l
     fc.pushCurrentState()
     fc.pushCurrentState()
     assert l == [False, ]
     assert l == [False, ]
     p.sendPulse()
     p.sendPulse()

+ 5 - 3
direct/src/gui/DirectButton.py

@@ -6,15 +6,17 @@ in-depth explanation and an example of how to use this class.
 
 
 __all__ = ['DirectButton']
 __all__ = ['DirectButton']
 
 
-from panda3d.core import *
+from panda3d.core import Mat4, MouseButton, PGButton
 from . import DirectGuiGlobals as DGG
 from . import DirectGuiGlobals as DGG
-from .DirectFrame import *
+from .DirectFrame import DirectFrame
+
 
 
 class DirectButton(DirectFrame):
 class DirectButton(DirectFrame):
     """
     """
     DirectButton(parent) - Create a DirectGuiWidget which responds
     DirectButton(parent) - Create a DirectGuiWidget which responds
     to mouse clicks and execute a callback function if defined
     to mouse clicks and execute a callback function if defined
     """
     """
+
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectFrame
         # Inherits from DirectFrame
         # A Direct Frame can have:
         # A Direct Frame can have:
@@ -45,7 +47,7 @@ class DirectButton(DirectFrame):
             # Can only be specified at time of widget contruction
             # Can only be specified at time of widget contruction
             # Do the text/graphics appear to move when the button is clicked
             # Do the text/graphics appear to move when the button is clicked
             ('pressEffect',     1,         DGG.INITOPT),
             ('pressEffect',     1,         DGG.INITOPT),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
 
 

+ 4 - 4
direct/src/gui/DirectCheckBox.py

@@ -1,5 +1,5 @@
-from direct.gui.DirectGui import *
-from panda3d.core import *
+from direct.gui.DirectGui import DGG, DirectButton
+from panda3d.core import PGButton
 
 
 
 
 class DirectCheckBox(DirectButton):
 class DirectCheckBox(DirectButton):
@@ -10,6 +10,7 @@ class DirectCheckBox(DirectButton):
 
 
     Uses an image swap rather than a text change to indicate state.
     Uses an image swap rather than a text change to indicate state.
     """
     """
+
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
 
 
         optiondefs = (
         optiondefs = (
@@ -33,7 +34,7 @@ class DirectCheckBox(DirectButton):
             ('uncheckedImage',  None,      None),
             ('uncheckedImage',  None,      None),
             ('checkedImage',    None,      None),
             ('checkedImage',    None,      None),
             ('isChecked',       False,     None),
             ('isChecked',       False,     None),
-            )
+        )
 
 
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
@@ -42,7 +43,6 @@ class DirectCheckBox(DirectButton):
 
 
         self.initialiseoptions(DirectCheckBox)
         self.initialiseoptions(DirectCheckBox)
 
 
-
     def commandFunc(self, event):
     def commandFunc(self, event):
         self['isChecked'] = not self['isChecked']
         self['isChecked'] = not self['isChecked']
 
 

+ 6 - 5
direct/src/gui/DirectCheckButton.py

@@ -8,9 +8,10 @@ in-depth explanation and an example of how to use this class.
 
 
 __all__ = ['DirectCheckButton']
 __all__ = ['DirectCheckButton']
 
 
-from panda3d.core import *
-from .DirectButton import *
-from .DirectLabel import *
+from panda3d.core import PGFrameStyle, VBase4
+from .DirectButton import DirectButton
+from .DirectLabel import DirectLabel
+
 
 
 class DirectCheckButton(DirectButton):
 class DirectCheckButton(DirectButton):
     """
     """
@@ -18,6 +19,7 @@ class DirectCheckButton(DirectButton):
     to mouse clicks by setting a state of on or off and execute a callback
     to mouse clicks by setting a state of on or off and execute a callback
     function (passing that state through) if defined
     function (passing that state through) if defined
     """
     """
+
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectButton
         # Inherits from DirectButton
         # A Direct Frame can have:
         # A Direct Frame can have:
@@ -42,7 +44,7 @@ class DirectCheckButton(DirectButton):
             ('boxImageScale', 1, None),
             ('boxImageScale', 1, None),
             ('boxImageColor', None, None),
             ('boxImageColor', None, None),
             ('boxRelief', 'sunken', None),
             ('boxRelief', 'sunken', None),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         # Initialize superclasses
         # Initialize superclasses
@@ -167,7 +169,6 @@ class DirectCheckButton(DirectButton):
 
 
             self.indicator.setPos(newpos[0], newpos[1], newpos[2])
             self.indicator.setPos(newpos[0], newpos[1], newpos[2])
 
 
-
     def commandFunc(self, event):
     def commandFunc(self, event):
         self['indicatorValue'] = 1 - self['indicatorValue']
         self['indicatorValue'] = 1 - self['indicatorValue']
         if self.colors is not None:
         if self.colors is not None:

+ 15 - 10
direct/src/gui/DirectDialog.py

@@ -9,11 +9,11 @@ __all__ = [
     'OkCancelDialog', 'YesNoDialog', 'YesNoCancelDialog', 'RetryCancelDialog',
     'OkCancelDialog', 'YesNoDialog', 'YesNoCancelDialog', 'RetryCancelDialog',
 ]
 ]
 
 
-from panda3d.core import *
+from panda3d.core import NodePath, Point3, TextNode, VBase3
 from direct.showbase import ShowBaseGlobal
 from direct.showbase import ShowBaseGlobal
 from . import DirectGuiGlobals as DGG
 from . import DirectGuiGlobals as DGG
-from .DirectFrame import *
-from .DirectButton import *
+from .DirectFrame import DirectFrame
+from .DirectButton import DirectButton
 
 
 
 
 def findDialog(uniqueName):
 def findDialog(uniqueName):
@@ -120,7 +120,7 @@ class DirectDialog(DirectFrame):
             ('command',           None,          None),
             ('command',           None,          None),
             ('extraArgs',         [],            None),
             ('extraArgs',         [],            None),
             ('sortOrder',    DGG.NO_FADE_SORT_INDEX, None),
             ('sortOrder',    DGG.NO_FADE_SORT_INDEX, None),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs, dynamicGroups = ("button",))
         self.defineoptions(kw, optiondefs, dynamicGroups = ("button",))
 
 
@@ -178,7 +178,7 @@ class DirectDialog(DirectFrame):
                 suppressKeys = self['suppressKeys'],
                 suppressKeys = self['suppressKeys'],
                 frameSize = self['buttonSize'],
                 frameSize = self['buttonSize'],
                 command = lambda s = self, v = value: s.buttonCommand(v)
                 command = lambda s = self, v = value: s.buttonCommand(v)
-                )
+            )
             self.buttonList.append(button)
             self.buttonList.append(button)
 
 
         # Update dialog when everything has been initialised
         # Update dialog when everything has been initialised
@@ -356,6 +356,7 @@ class DirectDialog(DirectFrame):
             button.destroy()
             button.destroy()
         DirectFrame.destroy(self)
         DirectFrame.destroy(self)
 
 
+
 class OkDialog(DirectDialog):
 class OkDialog(DirectDialog):
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectFrame
         # Inherits from DirectFrame
@@ -363,12 +364,13 @@ class OkDialog(DirectDialog):
             # Define type of DirectGuiWidget
             # Define type of DirectGuiWidget
             ('buttonTextList',  ['OK'],       DGG.INITOPT),
             ('buttonTextList',  ['OK'],       DGG.INITOPT),
             ('buttonValueList', [DGG.DIALOG_OK],          DGG.INITOPT),
             ('buttonValueList', [DGG.DIALOG_OK],          DGG.INITOPT),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         DirectDialog.__init__(self, parent)
         DirectDialog.__init__(self, parent)
         self.initialiseoptions(OkDialog)
         self.initialiseoptions(OkDialog)
 
 
+
 class OkCancelDialog(DirectDialog):
 class OkCancelDialog(DirectDialog):
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectFrame
         # Inherits from DirectFrame
@@ -376,12 +378,13 @@ class OkCancelDialog(DirectDialog):
             # Define type of DirectGuiWidget
             # Define type of DirectGuiWidget
             ('buttonTextList',  ['OK','Cancel'],       DGG.INITOPT),
             ('buttonTextList',  ['OK','Cancel'],       DGG.INITOPT),
             ('buttonValueList', [DGG.DIALOG_OK, DGG.DIALOG_CANCEL], DGG.INITOPT),
             ('buttonValueList', [DGG.DIALOG_OK, DGG.DIALOG_CANCEL], DGG.INITOPT),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         DirectDialog.__init__(self, parent)
         DirectDialog.__init__(self, parent)
         self.initialiseoptions(OkCancelDialog)
         self.initialiseoptions(OkCancelDialog)
 
 
+
 class YesNoDialog(DirectDialog):
 class YesNoDialog(DirectDialog):
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectFrame
         # Inherits from DirectFrame
@@ -389,12 +392,13 @@ class YesNoDialog(DirectDialog):
             # Define type of DirectGuiWidget
             # Define type of DirectGuiWidget
             ('buttonTextList',  ['Yes', 'No'],       DGG.INITOPT),
             ('buttonTextList',  ['Yes', 'No'],       DGG.INITOPT),
             ('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO], DGG.INITOPT),
             ('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO], DGG.INITOPT),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         DirectDialog.__init__(self, parent)
         DirectDialog.__init__(self, parent)
         self.initialiseoptions(YesNoDialog)
         self.initialiseoptions(YesNoDialog)
 
 
+
 class YesNoCancelDialog(DirectDialog):
 class YesNoCancelDialog(DirectDialog):
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectFrame
         # Inherits from DirectFrame
@@ -403,12 +407,13 @@ class YesNoCancelDialog(DirectDialog):
             ('buttonTextList',  ['Yes', 'No', 'Cancel'],  DGG.INITOPT),
             ('buttonTextList',  ['Yes', 'No', 'Cancel'],  DGG.INITOPT),
             ('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO, DGG.DIALOG_CANCEL],
             ('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO, DGG.DIALOG_CANCEL],
              DGG.INITOPT),
              DGG.INITOPT),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         DirectDialog.__init__(self, parent)
         DirectDialog.__init__(self, parent)
         self.initialiseoptions(YesNoCancelDialog)
         self.initialiseoptions(YesNoCancelDialog)
 
 
+
 class RetryCancelDialog(DirectDialog):
 class RetryCancelDialog(DirectDialog):
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectFrame
         # Inherits from DirectFrame
@@ -416,7 +421,7 @@ class RetryCancelDialog(DirectDialog):
             # Define type of DirectGuiWidget
             # Define type of DirectGuiWidget
             ('buttonTextList',  ['Retry','Cancel'],   DGG.INITOPT),
             ('buttonTextList',  ['Retry','Cancel'],   DGG.INITOPT),
             ('buttonValueList', [DGG.DIALOG_RETRY, DGG.DIALOG_CANCEL], DGG.INITOPT),
             ('buttonValueList', [DGG.DIALOG_RETRY, DGG.DIALOG_CANCEL], DGG.INITOPT),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         DirectDialog.__init__(self, parent)
         DirectDialog.__init__(self, parent)

+ 10 - 8
direct/src/gui/DirectEntry.py

@@ -7,13 +7,13 @@ explanation and an example of how to use this class.
 
 
 __all__ = ['DirectEntry']
 __all__ = ['DirectEntry']
 
 
-from panda3d.core import *
+from panda3d.core import ConfigVariableBool, PGEntry, Point3, TextNode, Vec3
 from direct.showbase import ShowBaseGlobal
 from direct.showbase import ShowBaseGlobal
 from . import DirectGuiGlobals as DGG
 from . import DirectGuiGlobals as DGG
-from .DirectFrame import *
+from .DirectFrame import DirectFrame
 from .OnscreenText import OnscreenText
 from .OnscreenText import OnscreenText
 # import this to make sure it gets pulled into the publish
 # import this to make sure it gets pulled into the publish
-import encodings.utf_8
+import encodings.utf_8 # pylint: disable=unused-import
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 
 
 # DirectEntry States:
 # DirectEntry States:
@@ -21,6 +21,7 @@ ENTRY_FOCUS_STATE    = PGEntry.SFocus      # 0
 ENTRY_NO_FOCUS_STATE = PGEntry.SNoFocus    # 1
 ENTRY_NO_FOCUS_STATE = PGEntry.SNoFocus    # 1
 ENTRY_INACTIVE_STATE = PGEntry.SInactive   # 2
 ENTRY_INACTIVE_STATE = PGEntry.SInactive   # 2
 
 
+
 class DirectEntry(DirectFrame):
 class DirectEntry(DirectFrame):
     """
     """
     DirectEntry(parent) - Create a DirectGuiWidget which responds
     DirectEntry(parent) - Create a DirectGuiWidget which responds
@@ -82,7 +83,7 @@ class DirectEntry(DirectFrame):
             ('autoCapitalize',  0,                self.autoCapitalizeFunc),
             ('autoCapitalize',  0,                self.autoCapitalizeFunc),
             ('autoCapitalizeAllowPrefixes', DirectEntry.AllowCapNamePrefixes, None),
             ('autoCapitalizeAllowPrefixes', DirectEntry.AllowCapNamePrefixes, None),
             ('autoCapitalizeForcePrefixes', DirectEntry.ForceCapNamePrefixes, None),
             ('autoCapitalizeForcePrefixes', DirectEntry.ForceCapNamePrefixes, None),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
 
 
@@ -215,15 +216,16 @@ class DirectEntry(DirectFrame):
 
 
     def _handleTyping(self, guiEvent):
     def _handleTyping(self, guiEvent):
         self._autoCapitalize()
         self._autoCapitalize()
+
     def _handleErasing(self, guiEvent):
     def _handleErasing(self, guiEvent):
         self._autoCapitalize()
         self._autoCapitalize()
 
 
     def _autoCapitalize(self):
     def _autoCapitalize(self):
         name = self.guiItem.getWtext()
         name = self.guiItem.getWtext()
         # capitalize each word, allowing for things like McMutton
         # capitalize each word, allowing for things like McMutton
-        capName = u''
+        capName = ''
         # track each individual word to detect prefixes like Mc
         # track each individual word to detect prefixes like Mc
-        wordSoFar = u''
+        wordSoFar = ''
         # track whether the previous character was part of a word or not
         # track whether the previous character was part of a word or not
         wasNonWordChar = True
         wasNonWordChar = True
         for i, character in enumerate(name):
         for i, character in enumerate(name):
@@ -232,9 +234,9 @@ class DirectEntry(DirectFrame):
             #   This assumes that string.lower and string.upper will return different
             #   This assumes that string.lower and string.upper will return different
             #   values for all unicode letters.
             #   values for all unicode letters.
             # - Don't count apostrophes as a break between words
             # - Don't count apostrophes as a break between words
-            if character.lower() == character.upper() and character != u"'":
+            if character.lower() == character.upper() and character != "'":
                 # we are between words
                 # we are between words
-                wordSoFar = u''
+                wordSoFar = ''
                 wasNonWordChar = True
                 wasNonWordChar = True
             else:
             else:
                 capitalize = False
                 capitalize = False

+ 4 - 7
direct/src/gui/DirectEntryScroll.py

@@ -1,10 +1,9 @@
 __all__ = ['DirectEntryScroll']
 __all__ = ['DirectEntryScroll']
 
 
-from panda3d.core import *
+from panda3d.core import NodePath, OmniBoundingVolume, PGVirtualFrame
 from . import DirectGuiGlobals as DGG
 from . import DirectGuiGlobals as DGG
-from .DirectScrolledFrame import *
-from .DirectFrame import *
-from .DirectEntry import *
+from .DirectFrame import DirectFrame
+
 
 
 class DirectEntryScroll(DirectFrame):
 class DirectEntryScroll(DirectFrame):
     def __init__(self, entry, parent = None, **kw):
     def __init__(self, entry, parent = None, **kw):
@@ -12,7 +11,7 @@ class DirectEntryScroll(DirectFrame):
             ('pgFunc',         PGVirtualFrame,      None),
             ('pgFunc',         PGVirtualFrame,      None),
             ('relief', None, None),
             ('relief', None, None),
             ('clipSize',     (-1, 1, -1, 1),        self.setClipSize),
             ('clipSize',     (-1, 1, -1, 1),        self.setClipSize),
-            )
+        )
 
 
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         DirectFrame.__init__(self, parent, **kw)
         DirectFrame.__init__(self, parent, **kw)
@@ -81,7 +80,6 @@ class DirectEntryScroll(DirectFrame):
         if abs(distanceToCenter) > (clipExtent * 0.5):
         if abs(distanceToCenter) > (clipExtent * 0.5):
             self.moveToCenterCursor()
             self.moveToCenterCursor()
 
 
-
     def moveToCenterCursor(self):
     def moveToCenterCursor(self):
         cursorX = self.entry.guiItem.getCursorX() * self.entry['text_scale'][0]
         cursorX = self.entry.guiItem.getCursorX() * self.entry['text_scale'][0]
         canvasX = self.canvas.getX()
         canvasX = self.canvas.getX()
@@ -122,7 +120,6 @@ class DirectEntryScroll(DirectFrame):
         self.entry = None
         self.entry = None
         DirectFrame.destroy(self)
         DirectFrame.destroy(self)
 
 
-
     def getCanvas(self):
     def getCanvas(self):
         return self.canvas
         return self.canvas
 
 

+ 2 - 2
direct/src/gui/DirectFrame.py

@@ -18,9 +18,9 @@ explanation and an example of how to use this class.
 
 
 __all__ = ['DirectFrame']
 __all__ = ['DirectFrame']
 
 
-from panda3d.core import *
+from panda3d.core import Filename, NodePath, PGItem, Texture
 from . import DirectGuiGlobals as DGG
 from . import DirectGuiGlobals as DGG
-from .DirectGuiBase import *
+from .DirectGuiBase import DirectGuiWidget
 from .OnscreenImage import OnscreenImage
 from .OnscreenImage import OnscreenImage
 from .OnscreenGeom import OnscreenGeom
 from .OnscreenGeom import OnscreenGeom
 from .OnscreenText import OnscreenText
 from .OnscreenText import OnscreenText

+ 15 - 7
direct/src/gui/DirectGuiBase.py

@@ -87,14 +87,21 @@ Code overview:
 __all__ = ['DirectGuiBase', 'DirectGuiWidget']
 __all__ = ['DirectGuiBase', 'DirectGuiWidget']
 
 
 
 
-from panda3d.core import *
+from panda3d.core import (
+    ConfigVariableBool,
+    KeyboardButton,
+    MouseWatcherRegion,
+    NodePath,
+    PGFrameStyle,
+    PGItem,
+    Point3,
+    Texture,
+    Vec3,
+)
 from direct.showbase import ShowBaseGlobal
 from direct.showbase import ShowBaseGlobal
 from direct.showbase.ShowBase import ShowBase
 from direct.showbase.ShowBase import ShowBase
 from direct.showbase.MessengerGlobal import messenger
 from direct.showbase.MessengerGlobal import messenger
 from . import DirectGuiGlobals as DGG
 from . import DirectGuiGlobals as DGG
-from .OnscreenText import *
-from .OnscreenGeom import *
-from .OnscreenImage import *
 from direct.directtools.DirectUtil import ROUND_TO
 from direct.directtools.DirectUtil import ROUND_TO
 from direct.showbase import DirectObject
 from direct.showbase import DirectObject
 from direct.task import Task
 from direct.task import Task
@@ -652,9 +659,11 @@ class DirectGuiBase(DirectObject.DirectObject):
         gEvent = event + self.guiId
         gEvent = event + self.guiId
         self.ignore(gEvent)
         self.ignore(gEvent)
 
 
+
 def toggleGuiGridSnap():
 def toggleGuiGridSnap():
     DirectGuiWidget.snapToGrid = 1 - DirectGuiWidget.snapToGrid
     DirectGuiWidget.snapToGrid = 1 - DirectGuiWidget.snapToGrid
 
 
+
 def setGuiGridSpacing(spacing):
 def setGuiGridSpacing(spacing):
     DirectGuiWidget.gridSpacing = spacing
     DirectGuiWidget.gridSpacing = spacing
 
 
@@ -715,7 +724,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
             ('suppressMouse',  1,            DGG.INITOPT),
             ('suppressMouse',  1,            DGG.INITOPT),
             ('suppressKeys',   0,            DGG.INITOPT),
             ('suppressKeys',   0,            DGG.INITOPT),
             ('enableEdit',     1,            DGG.INITOPT),
             ('enableEdit',     1,            DGG.INITOPT),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
 
 
@@ -822,7 +831,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
         vMouse2render2d = Point3(event.getMouse()[0], 0, event.getMouse()[1])
         vMouse2render2d = Point3(event.getMouse()[0], 0, event.getMouse()[1])
         editVec = Vec3(vWidget2render2d - vMouse2render2d)
         editVec = Vec3(vWidget2render2d - vMouse2render2d)
         if base.mouseWatcherNode.getModifierButtons().isDown(
         if base.mouseWatcherNode.getModifierButtons().isDown(
-            KeyboardButton.control()):
+                KeyboardButton.control()):
             t = taskMgr.add(self.guiScaleTask, 'guiEditTask')
             t = taskMgr.add(self.guiScaleTask, 'guiEditTask')
             t.refPos = vWidget2render2d
             t.refPos = vWidget2render2d
             t.editVecLen = editVec.length()
             t.editVecLen = editVec.length()
@@ -904,7 +913,6 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
             self.bounds[2] - bw[1],
             self.bounds[2] - bw[1],
             self.bounds[3] + bw[1])
             self.bounds[3] + bw[1])
 
 
-
     def getBounds(self, state = 0):
     def getBounds(self, state = 0):
         self.stateNodePath[state].calcTightBounds(self.ll, self.ur)
         self.stateNodePath[state].calcTightBounds(self.ll, self.ur)
         # Scale bounds to give a pad around graphics
         # Scale bounds to give a pad around graphics

+ 9 - 3
direct/src/gui/DirectGuiGlobals.py

@@ -5,7 +5,15 @@ that can be used during widget construction
 
 
 __all__ = []
 __all__ = []
 
 
-from panda3d.core import *
+from panda3d.core import (
+    KeyboardButton,
+    MouseButton,
+    PGButton,
+    PGEntry,
+    PGFrameStyle,
+    PGSliderBar,
+    TextNode,
+)
 
 
 defaultFont = None
 defaultFont = None
 defaultFontFunc = TextNode.getDefaultFont
 defaultFontFunc = TextNode.getDefaultFont
@@ -138,11 +146,9 @@ def setDefaultFontFunc(newFontFunc):
     defaultFontFunc = newFontFunc
     defaultFontFunc = newFontFunc
 
 
 def getDefaultDialogGeom():
 def getDefaultDialogGeom():
-    global defaultDialogGeom
     return defaultDialogGeom
     return defaultDialogGeom
 
 
 def getDefaultDialogRelief():
 def getDefaultDialogRelief():
-    global defaultDialogRelief
     return defaultDialogRelief
     return defaultDialogRelief
 
 
 def setDefaultDialogGeom(newDialogGeom, relief=None):
 def setDefaultDialogGeom(newDialogGeom, relief=None):

+ 3 - 2
direct/src/gui/DirectGuiTest.py

@@ -4,12 +4,13 @@ __all__ = []
 
 
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
+    from panda3d.core import Point3
     from direct.showbase.ShowBase import ShowBase
     from direct.showbase.ShowBase import ShowBase
     from direct.task.TaskManagerGlobal import taskMgr
     from direct.task.TaskManagerGlobal import taskMgr
     from . import DirectGuiGlobals
     from . import DirectGuiGlobals
-    from .DirectGui import *
+    from .DirectGui import DirectButton, DirectDialog, DirectEntry, DirectFrame, YesNoDialog
     #from whrandom import *
     #from whrandom import *
-    from random import *
+    from random import random
 
 
     base = ShowBase()
     base = ShowBase()
 
 

+ 5 - 3
direct/src/gui/DirectLabel.py

@@ -6,14 +6,16 @@ explanation and an example of how to use this class.
 
 
 __all__ = ['DirectLabel']
 __all__ = ['DirectLabel']
 
 
-from panda3d.core import *
-from .DirectFrame import *
+from panda3d.core import PGItem
+from .DirectFrame import DirectFrame
+
 
 
 class DirectLabel(DirectFrame):
 class DirectLabel(DirectFrame):
     """
     """
     DirectLabel(parent) - Create a DirectGuiWidget which has multiple
     DirectLabel(parent) - Create a DirectGuiWidget which has multiple
     states.  User explicitly chooses a state to display
     states.  User explicitly chooses a state to display
     """
     """
+
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectFrame
         # Inherits from DirectFrame
         # A Direct Frame can have:
         # A Direct Frame can have:
@@ -32,7 +34,7 @@ class DirectLabel(DirectFrame):
             ('numStates',       1,         None),
             ('numStates',       1,         None),
             ('state',           self.inactiveInitState, None),
             ('state',           self.inactiveInitState, None),
             ('activeState',     0,         self.setActiveState),
             ('activeState',     0,         self.setActiveState),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
 
 

+ 5 - 5
direct/src/gui/DirectOptionMenu.py

@@ -6,12 +6,11 @@ in-depth explanation and an example of how to use this class.
 
 
 __all__ = ['DirectOptionMenu']
 __all__ = ['DirectOptionMenu']
 
 
-from panda3d.core import *
+from panda3d.core import OmniBoundingVolume, TextNode, VBase3
 from direct.showbase import ShowBaseGlobal
 from direct.showbase import ShowBaseGlobal
 from . import DirectGuiGlobals as DGG
 from . import DirectGuiGlobals as DGG
-from .DirectButton import *
-from .DirectLabel import *
-from .DirectFrame import *
+from .DirectButton import DirectButton
+from .DirectFrame import DirectFrame
 
 
 
 
 class DirectOptionMenu(DirectButton):
 class DirectOptionMenu(DirectButton):
@@ -22,6 +21,7 @@ class DirectOptionMenu(DirectButton):
     To cancel the popup menu click anywhere on the screen outside of the
     To cancel the popup menu click anywhere on the screen outside of the
     popup menu.  No command is executed in this case.
     popup menu.  No command is executed in this case.
     """
     """
+
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectButton
         # Inherits from DirectButton
         optiondefs = (
         optiondefs = (
@@ -43,7 +43,7 @@ class DirectOptionMenu(DirectButton):
             ('text_align',  TextNode.ALeft, None),
             ('text_align',  TextNode.ALeft, None),
             # Remove press effect because it looks a bit funny
             # Remove press effect because it looks a bit funny
             ('pressEffect',     0,          DGG.INITOPT),
             ('pressEffect',     0,          DGG.INITOPT),
-           )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         # Initialize superclasses
         # Initialize superclasses

+ 6 - 5
direct/src/gui/DirectRadioButton.py

@@ -9,10 +9,11 @@ in-depth explanation and an example of how to use this class.
 
 
 __all__ = ['DirectRadioButton']
 __all__ = ['DirectRadioButton']
 
 
-from panda3d.core import *
+from panda3d.core import PGFrameStyle, VBase4
 from . import DirectGuiGlobals as DGG
 from . import DirectGuiGlobals as DGG
-from .DirectButton import *
-from .DirectLabel import *
+from .DirectButton import DirectButton
+from .DirectLabel import DirectLabel
+
 
 
 class DirectRadioButton(DirectButton):
 class DirectRadioButton(DirectButton):
     """
     """
@@ -20,6 +21,7 @@ class DirectRadioButton(DirectButton):
     to mouse clicks by setting given value to given variable and
     to mouse clicks by setting given value to given variable and
     execute a callback function (passing that state through) if defined
     execute a callback function (passing that state through) if defined
     """
     """
+
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectButton
         # Inherits from DirectButton
         # A Direct Frame can have:
         # A Direct Frame can have:
@@ -54,7 +56,7 @@ class DirectRadioButton(DirectButton):
             ('boxImageScale', 1.0, None),
             ('boxImageScale', 1.0, None),
             ('boxImageColor', VBase4(1, 1, 1, 1), None),
             ('boxImageColor', VBase4(1, 1, 1, 1), None),
             ('boxRelief', None, None),
             ('boxRelief', None, None),
-            )
+        )
         # Merge keyword options with default options
         # Merge keyword options with default options
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         # Initialize superclasses
         # Initialize superclasses
@@ -194,7 +196,6 @@ class DirectRadioButton(DirectButton):
 
 
             self.indicator.setPos(newpos[0], newpos[1], newpos[2])
             self.indicator.setPos(newpos[0], newpos[1], newpos[2])
 
 
-
     def commandFunc(self, event):
     def commandFunc(self, event):
         if len(self['value']) == len(self['variable']) != 0:
         if len(self['value']) == len(self['variable']) != 0:
             for i in range(len(self['value'])):
             for i in range(len(self['value'])):

Some files were not shown because too many files changed in this diff