Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
70d467c150
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,performance-*,portability-*,modernize-use-nullptr'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: ''
|
||||
FormatStyle: none
|
||||
...
|
||||
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
|
||||
include:
|
||||
- profile: ubuntu-bionic-standard-unity-makefile
|
||||
os: ubuntu-18.04
|
||||
os: ubuntu-20.04
|
||||
config: Standard
|
||||
unity: YES
|
||||
generator: Unix Makefiles
|
||||
|
|
@ -30,7 +30,7 @@ jobs:
|
|||
eigen: NO
|
||||
|
||||
- profile: ubuntu-bionic-coverage-ninja
|
||||
os: ubuntu-18.04
|
||||
os: ubuntu-20.04
|
||||
config: Coverage
|
||||
unity: NO
|
||||
generator: Ninja
|
||||
|
|
@ -92,10 +92,10 @@ jobs:
|
|||
- name: Install dependencies (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
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.
|
||||
install_name_tool -id "$(pwd)/thirdparty/darwin-libs-a/nvidiacg/lib/libCg.dylib" thirdparty/darwin-libs-a/nvidiacg/lib/libCg.dylib
|
||||
|
|
@ -115,10 +115,6 @@ jobs:
|
|||
libxcursor-dev libxrandr-dev nvidia-cg-toolkit zlib1g-dev
|
||||
python3-setuptools
|
||||
|
||||
# Workaround for CMake 3.12 finding this first:
|
||||
|
||||
sudo rm /usr/bin/x86_64-linux-gnu-python2.7-config
|
||||
|
||||
- name: Cache dependencies (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/cache@v1
|
||||
|
|
@ -365,12 +361,12 @@ jobs:
|
|||
if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')"
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04, windows-2019, macOS-11]
|
||||
os: [ubuntu-20.04, windows-2019, macOS-11]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Install dependencies (Ubuntu)
|
||||
if: matrix.os == 'ubuntu-18.04'
|
||||
if: matrix.os == 'ubuntu-20.04'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential bison flex libfreetype6-dev libgl1-mesa-dev libjpeg-dev libode-dev libopenal-dev libpng-dev libssl-dev libvorbis-dev libx11-dev libxcursor-dev libxrandr-dev nvidia-cg-toolkit zlib1g-dev
|
||||
|
|
@ -385,10 +381,10 @@ jobs:
|
|||
- name: Get thirdparty packages (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
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)
|
||||
|
||||
- name: Set up Python 3.11
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
@ -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/github-script@v3.1.0
|
||||
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/github-script@v3.1.0
|
||||
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
|
||||
826
.pylintrc
826
.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
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
# 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=
|
||||
|
||||
# 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
|
||||
# pygtk.require().
|
||||
#init-hook=
|
||||
|
||||
# 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
|
||||
|
||||
# Control the amount of potential inferred values when inferring a single
|
||||
|
|
@ -36,259 +82,23 @@ load-plugins=
|
|||
# Pickle collected data for later comparisons.
|
||||
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
|
||||
# user-friendly hints instead of false-positive error messages.
|
||||
suggestion-mode=yes
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
#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=
|
||||
|
||||
|
||||
[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]
|
||||
|
|
@ -297,13 +107,15 @@ notes=FIXME,
|
|||
argument-naming-style=snake_case
|
||||
|
||||
# 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=
|
||||
|
||||
# Naming style matching correct attribute names.
|
||||
attr-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct attribute names. Overrides attr-naming-
|
||||
# style. If left empty, attribute names will be checked with the set naming
|
||||
# style.
|
||||
#attr-rgx=
|
||||
|
||||
|
|
@ -323,20 +135,30 @@ bad-names-rgxs=
|
|||
class-attribute-naming-style=any
|
||||
|
||||
# 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=
|
||||
|
||||
# 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.
|
||||
class-naming-style=PascalCase
|
||||
|
||||
# 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=
|
||||
|
||||
# Naming style matching correct constant names.
|
||||
const-naming-style=UPPER_CASE
|
||||
|
||||
# Regular expression matching correct constant names. Overrides const-naming-
|
||||
# style. If left empty, constant names will be checked with the set naming
|
||||
# style.
|
||||
#const-rgx=
|
||||
|
||||
|
|
@ -348,7 +170,8 @@ docstring-min-length=-1
|
|||
function-naming-style=snake_case
|
||||
|
||||
# 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=
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma.
|
||||
|
|
@ -370,21 +193,22 @@ include-naming-hint=no
|
|||
inlinevar-naming-style=any
|
||||
|
||||
# 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=
|
||||
|
||||
# Naming style matching correct method names.
|
||||
method-naming-style=snake_case
|
||||
|
||||
# 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=
|
||||
|
||||
# Naming style matching correct module names.
|
||||
module-naming-style=snake_case
|
||||
|
||||
# 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=
|
||||
|
||||
# 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.
|
||||
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.
|
||||
variable-naming-style=snake_case
|
||||
|
||||
# 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=
|
||||
|
||||
|
||||
[LOGGING]
|
||||
[CLASSES]
|
||||
|
||||
# The type of string formatting that logging methods do. `old` means using %
|
||||
# formatting, `new` is for `{}` formatting.
|
||||
logging-format-style=old
|
||||
# Warn about protected attribute access inside special methods
|
||||
check-protected-access-in-special-methods=no
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format.
|
||||
logging-modules=logging
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,
|
||||
__new__,
|
||||
setUp,
|
||||
__post_init__
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,
|
||||
_fields,
|
||||
_replace,
|
||||
_source,
|
||||
_make
|
||||
|
||||
[STRING]
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# 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
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=cls
|
||||
|
||||
|
||||
[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.
|
||||
max-args=5
|
||||
|
||||
|
|
@ -463,6 +304,42 @@ max-statements=50
|
|||
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]
|
||||
|
||||
# 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-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=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=
|
||||
|
||||
# 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=
|
||||
|
||||
# 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=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
|
|
@ -503,32 +376,359 @@ known-third-party=enchant
|
|||
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
|
||||
|
||||
# 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
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format.
|
||||
logging-modules=logging
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "BaseException, Exception".
|
||||
overgeneral-exceptions=BaseException,
|
||||
Exception
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
[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
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ This is a list of all the people who are contributing financially to Panda3D. I
|
|||
* Maxwell Dreytser
|
||||
* SureBet
|
||||
* Gyedo Jeon
|
||||
* GameDev JONI
|
||||
|
||||
## Backers
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
dependency packages. You should determine which ones you want to include in
|
||||
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.
|
||||
|
||||
If you are on Ubuntu, this command should cover the most frequently
|
||||
used third-party packages:
|
||||
|
||||
```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
|
||||
|
|
@ -136,7 +136,7 @@ macOS
|
|||
-----
|
||||
|
||||
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,
|
||||
you may build Panda3D using a command like the following:
|
||||
|
|
|
|||
|
|
@ -99,8 +99,9 @@ Flock AIWorld::get_flock(unsigned int flock_id) {
|
|||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6,7 +6,29 @@ to learn more about loading animated models.
|
|||
|
||||
__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 direct.showbase.DirectObject import DirectObject
|
||||
from direct.showbase.Loader import Loader
|
||||
|
|
|
|||
|
|
@ -1,8 +1,26 @@
|
|||
"""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.showbase import DirectObject
|
||||
from direct.task import Task
|
||||
|
|
@ -95,7 +113,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
self.notify.debug('post startMoveCam')
|
||||
self.startMoveSelectedTask()
|
||||
|
||||
|
||||
def startReaderPollTask(self):
|
||||
""" Task to handle datagrams from server """
|
||||
# Run this task just after the listener poll task
|
||||
|
|
@ -112,7 +129,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
|
||||
return Task.cont
|
||||
|
||||
|
||||
def startControlObjectTask(self):
|
||||
self.notify.debug("moving control objects")
|
||||
taskMgr.add(self.controlObjectTask,"controlObjectTask",50)
|
||||
|
|
@ -134,7 +150,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
self.notify.debug('adding move cam')
|
||||
taskMgr.add(self.moveCameraTask, "moveCamTask", 49)
|
||||
|
||||
|
||||
def controlObjectTask(self, task):
|
||||
for pair in self.sortedControlMappings:
|
||||
object = pair[1]
|
||||
|
|
@ -153,8 +168,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
for server in serverList:
|
||||
self.serverList[server].sendNamedMovementDone()
|
||||
|
||||
|
||||
|
||||
def redoSortedPriorities(self):
|
||||
self.sortedControlMappings = []
|
||||
for key in self.controlMappings:
|
||||
|
|
@ -176,7 +189,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
for server in serverList:
|
||||
self.serverList[server].sendMoveNamedObject(xyz,hpr,scale,color,hidden,object)
|
||||
|
||||
|
||||
def moveCameraTask(self, task):
|
||||
self.moveCamera(
|
||||
base.camera.getPos(render),
|
||||
|
|
@ -203,7 +215,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
server.sendMoveSelected(xyz, hpr, scale)
|
||||
return Task.cont
|
||||
|
||||
|
||||
def addNamedObjectMapping(self, object, name, hasColor = True):
|
||||
if name not in self.objectMappings:
|
||||
self.objectMappings[name] = object
|
||||
|
|
@ -215,7 +226,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
if name in self.objectMappings:
|
||||
self.objectMappings.pop(name)
|
||||
|
||||
|
||||
def addControlMapping(self, objectName, controlledName, serverList = None,
|
||||
offset = None, priority = 0):
|
||||
if objectName not in self.controlMappings:
|
||||
|
|
@ -260,7 +270,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
self.controlPriorities.pop(name)
|
||||
self.redoSortedPriorities()
|
||||
|
||||
|
||||
def getNodePathFindCmd(self, nodePath):
|
||||
pathString = repr(nodePath)
|
||||
index = pathString.find('/')
|
||||
|
|
@ -280,7 +289,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
else:
|
||||
return pathString
|
||||
|
||||
|
||||
def addObjectTag(self,object,selectFunction,deselectFunction,selectArgs,deselectArgs):
|
||||
newTag = {}
|
||||
newTag["selectFunction"] = selectFunction
|
||||
|
|
@ -289,12 +297,10 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
newTag["deselectArgs"] = deselectArgs
|
||||
self.taggedObjects[object] = newTag
|
||||
|
||||
|
||||
def removeObjectTag(self,object):
|
||||
|
||||
self.taggedObjects.pop(object)
|
||||
|
||||
|
||||
def selectNodePath(self, nodePath):
|
||||
name = self.getNodePathName(nodePath)
|
||||
if name in self.taggedObjects:
|
||||
|
|
@ -307,7 +313,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
else:
|
||||
self(self.getNodePathFindCmd(nodePath) + '.select()', 0)
|
||||
|
||||
|
||||
def deselectNodePath(self, nodePath):
|
||||
name = self.getNodePathName(nodePath)
|
||||
if name in self.taggedObjects:
|
||||
|
|
@ -345,7 +350,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
# Execute locally
|
||||
exec(commandString, __builtins__)
|
||||
|
||||
|
||||
def handleDatagram(self,dgi,type,server):
|
||||
if type == CLUSTER_NONE:
|
||||
pass
|
||||
|
|
@ -370,7 +374,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
# clear the queue
|
||||
self.serverQueues[server] = []
|
||||
|
||||
|
||||
def handleNamedMovement(self, data):
|
||||
""" Update cameraJig position to reflect latest position """
|
||||
|
||||
|
|
@ -390,7 +393,6 @@ class ClusterClient(DirectObject.DirectObject):
|
|||
else:
|
||||
self.notify.debug("recieved unknown named object command: "+name)
|
||||
|
||||
|
||||
def exit(self):
|
||||
# Execute remotely
|
||||
for server in self.serverList:
|
||||
|
|
@ -457,8 +459,6 @@ class DisplayConnection:
|
|||
self.qcr.addConnection(self.tcpConn)
|
||||
self.cw=ConnectionWriter(qcm, 0)
|
||||
|
||||
|
||||
|
||||
def poll(self):
|
||||
""" Non blocking task to read all available datagrams """
|
||||
dataGrams = []
|
||||
|
|
@ -473,9 +473,6 @@ class DisplayConnection:
|
|||
|
||||
return dataGrams
|
||||
|
||||
|
||||
|
||||
|
||||
def sendCamOffset(self, xyz, hpr):
|
||||
ClusterClient.notify.debug("send cam offset...")
|
||||
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)" %
|
||||
(focalLength, filmSize[0], filmSize[1],
|
||||
filmOffset[0], filmOffset[1])))
|
||||
)
|
||||
)
|
||||
datagram = self.msgHandler.makeCamFrustumDatagram(
|
||||
focalLength, filmSize, filmOffset)
|
||||
self.cw.send(datagram, self.tcpConn)
|
||||
|
||||
|
||||
def sendNamedMovementDone(self):
|
||||
|
||||
datagram = self.msgHandler.makeNamedMovementDone()
|
||||
|
|
@ -566,6 +562,7 @@ class DisplayConnection:
|
|||
frameCount, frameTime, dt)
|
||||
self.cw.send(datagram, self.tcpConn)
|
||||
|
||||
|
||||
class ClusterConfigItem:
|
||||
def __init__(self, serverConfigName, serverName,
|
||||
serverDaemonPort, serverMsgPort):
|
||||
|
|
@ -581,9 +578,11 @@ class ClusterConfigItem:
|
|||
self.focalLength = None
|
||||
self.filmSize = None
|
||||
self.filmOffset = None
|
||||
|
||||
def setCamOffset(self, xyz, hpr):
|
||||
self.xyz = xyz
|
||||
self.hpr = hpr
|
||||
|
||||
def setCamFrustum(self, focalLength, filmSize, filmOffset):
|
||||
self.fFrustum = 1
|
||||
self.focalLength = focalLength
|
||||
|
|
@ -671,6 +670,7 @@ def createClusterClient():
|
|||
class DummyClusterClient(DirectObject.DirectObject):
|
||||
""" Dummy class to handle command strings when not in cluster mode """
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory("DummyClusterClient")
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
from .ClusterClient import *
|
||||
from panda3d.core import Vec3
|
||||
|
||||
#: A dictionary of information for various cluster configurations.
|
||||
#: Dictionary is keyed on cluster-config string
|
||||
|
|
@ -26,7 +26,7 @@ ClientConfigs = {
|
|||
'display mode': 'client',
|
||||
'pos': Vec3(0),
|
||||
'hpr': Vec3(0)}
|
||||
],
|
||||
],
|
||||
'two-server': [{'display name': 'master',
|
||||
'display mode': 'client',
|
||||
'pos': Vec3(0),
|
||||
|
|
@ -35,7 +35,7 @@ ClientConfigs = {
|
|||
'pos': Vec3(0),
|
||||
'hpr': Vec3(0)
|
||||
}
|
||||
],
|
||||
],
|
||||
'three-server': [{'display name': 'master',
|
||||
'display mode': 'client',
|
||||
'pos': Vec3(0),
|
||||
|
|
@ -48,14 +48,14 @@ ClientConfigs = {
|
|||
'pos': Vec3(0),
|
||||
'hpr': Vec3(0)
|
||||
}
|
||||
],
|
||||
],
|
||||
'mono-cave': [{'display name': 'la',
|
||||
'pos': Vec3(-0.105, -0.020, 5.000),
|
||||
'hpr': Vec3(51.213, 0.000, 0.000),
|
||||
'focal length': 0.809,
|
||||
'film size': (1.000, 0.831),
|
||||
'film offset': (0.000, 0.173),
|
||||
},
|
||||
},
|
||||
{'display name': 'lb',
|
||||
'display mode': 'client',
|
||||
'pos': Vec3(-0.105, -0.020, 5.000),
|
||||
|
|
@ -71,7 +71,7 @@ ClientConfigs = {
|
|||
'film size': (1.000, 0.830),
|
||||
'film offset': (-0.000, 0.173),
|
||||
},
|
||||
],
|
||||
],
|
||||
'seamless-cave': [{'display name': 'master',
|
||||
'display mode': 'client',
|
||||
'pos': Vec3(-0.105, -0.020, 5.000),
|
||||
|
|
@ -79,7 +79,7 @@ ClientConfigs = {
|
|||
'focal length': 0.815,
|
||||
'film size': (1.000, 0.831),
|
||||
'film offset': (0.000, 0.173),
|
||||
},
|
||||
},
|
||||
{'display name': 'la',
|
||||
'pos': Vec3(-0.105, -0.020, 5.000),
|
||||
'hpr': Vec3(51.213, 0.000, 0.000),
|
||||
|
|
@ -122,12 +122,12 @@ ClientConfigs = {
|
|||
'film size': (1.000, 0.831),
|
||||
'film offset': (-0.000, 0.173),
|
||||
},
|
||||
],
|
||||
],
|
||||
'ursula': [{'display name': 'master',
|
||||
'display mode': 'client',
|
||||
'pos': Vec3(0),
|
||||
'hpr': Vec3(0),
|
||||
},
|
||||
},
|
||||
{'display name': 'l',
|
||||
'pos': Vec3(-.105, 0, 0),
|
||||
'hpr': Vec3(0, 0, 0),
|
||||
|
|
@ -144,11 +144,11 @@ ClientConfigs = {
|
|||
#'film offset': (-0.105, -2),
|
||||
'film offset': (-0.105, -1),
|
||||
}
|
||||
],
|
||||
],
|
||||
'composite': [{'display name': 'master',
|
||||
'display mode': 'client',
|
||||
'pos': Vec3(0),
|
||||
},
|
||||
},
|
||||
{'display name': 'left',
|
||||
'pos': Vec3(-0.105, -0.020, 5.000),
|
||||
'hpr': Vec3(-0.370, 0.000, 0.000),
|
||||
|
|
@ -163,5 +163,5 @@ ClientConfigs = {
|
|||
'film size': (1.000, 0.831),
|
||||
'film offset': (0.000, 0.173),
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# This module is intended to supply routines and dataformats common to
|
||||
# both ClusterClient and ClusterServer.
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import NetDatagram
|
||||
from direct.distributed.PyDatagram import PyDatagram
|
||||
from direct.distributed.PyDatagramIterator import PyDatagramIterator
|
||||
import time
|
||||
|
|
|
|||
|
|
@ -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.showbase import DirectObject
|
||||
from direct.task import Task
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
import builtins
|
||||
|
||||
# NOTE: This assumes the following variables are set via bootstrap command line
|
||||
# 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
|
||||
# cluster system.
|
||||
|
||||
|
||||
class ClusterServer(DirectObject.DirectObject):
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory("ClusterServer")
|
||||
MSG_NUM = 2000000
|
||||
|
|
@ -76,8 +102,6 @@ class ClusterServer(DirectObject.DirectObject):
|
|||
clusterDaemonPort = CLUSTER_DAEMON_PORT
|
||||
self.daemon.serverReady(clusterDaemonClient, clusterDaemonPort)
|
||||
|
||||
|
||||
|
||||
def startListenerPollTask(self):
|
||||
# Run this task near the start of frame, sometime after the dataLoop
|
||||
taskMgr.add(self.listenerPollTask, "serverListenerPollTask", -40)
|
||||
|
|
@ -100,7 +124,6 @@ class ClusterServer(DirectObject.DirectObject):
|
|||
self.notify.warning("getNewConnection returned false")
|
||||
return Task.cont
|
||||
|
||||
|
||||
def addNamedObjectMapping(self, object, name, hasColor = True,
|
||||
priority = 0):
|
||||
if name not in self.objectMappings:
|
||||
|
|
@ -113,7 +136,6 @@ class ClusterServer(DirectObject.DirectObject):
|
|||
if name in self.objectMappings:
|
||||
self.objectMappings.pop(name)
|
||||
|
||||
|
||||
def redoSortedPriorities(self):
|
||||
|
||||
self.sortedControlMappings = []
|
||||
|
|
@ -123,7 +145,6 @@ class ClusterServer(DirectObject.DirectObject):
|
|||
|
||||
self.sortedControlMappings.sort()
|
||||
|
||||
|
||||
def addControlMapping(self, objectName, controlledName, offset = None,
|
||||
priority = 0):
|
||||
if objectName not in self.controlMappings:
|
||||
|
|
@ -134,20 +155,18 @@ class ClusterServer(DirectObject.DirectObject):
|
|||
self.controlPriorities[objectName] = priority
|
||||
self.redoSortedPriorities()
|
||||
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):
|
||||
if objectName in self.controlMappings:
|
||||
self.controlOffsets[objectName] = offset
|
||||
|
||||
|
||||
def removeControlMapping(self, name):
|
||||
if name in self.controlMappings:
|
||||
self.controlMappings.pop(name)
|
||||
self.controlPriorities.pop(name)
|
||||
self.redoSortedPriorities()
|
||||
|
||||
|
||||
def startControlObjectTask(self):
|
||||
self.notify.debug("moving control objects")
|
||||
taskMgr.add(self.controlObjectTask,"controlObjectTask",50)
|
||||
|
|
@ -164,7 +183,6 @@ class ClusterServer(DirectObject.DirectObject):
|
|||
self.sendNamedMovementDone()
|
||||
return Task.cont
|
||||
|
||||
|
||||
def sendNamedMovementDone(self):
|
||||
self.notify.debug("named movement done")
|
||||
datagram = self.msgHandler.makeNamedMovementDone()
|
||||
|
|
@ -308,12 +326,10 @@ class ClusterServer(DirectObject.DirectObject):
|
|||
else:
|
||||
self.notify.debug("recieved unknown named object command: "+name)
|
||||
|
||||
|
||||
def handleMessageQueue(self):
|
||||
|
||||
#print self.messageQueue
|
||||
#print(self.messageQueue)
|
||||
for data in self.messageQueue:
|
||||
#print "in queue",dgi
|
||||
#print("in queue", dgi)
|
||||
self.handleNamedMovement(data)
|
||||
|
||||
self.messageQueue = []
|
||||
|
|
@ -328,8 +344,8 @@ class ClusterServer(DirectObject.DirectObject):
|
|||
""" Update cameraJig position to reflect latest position """
|
||||
(x, y, z, h, p, r, sx, sy, sz) = self.msgHandler.parseSelectedMovementDatagram(
|
||||
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):
|
||||
""" Update cameraJig position to reflect latest position """
|
||||
|
|
@ -345,5 +361,5 @@ class ClusterServer(DirectObject.DirectObject):
|
|||
command = self.msgHandler.parseCommandStringDatagram(dgi)
|
||||
try:
|
||||
exec(command, __builtins__)
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
from direct.showbase.InputStateGlobal import inputState
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
from direct.task.Task import Task
|
||||
from panda3d.core import *
|
||||
from panda3d.core import ClockObject, Mat3, Point3, Vec3
|
||||
from . import GravityWalker
|
||||
|
||||
BattleStrafe = 0
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ class ControlManager:
|
|||
#self.monitorTask = taskMgr.add(self.monitor, "ControlManager-%s"%(id(self)), priority=-1)
|
||||
self.forceAvJumpToken = None
|
||||
|
||||
|
||||
|
||||
if self.passMessagesThrough: # for not breaking toontown
|
||||
ist=self.inputStateTokens
|
||||
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("turnRight", "arrow_right", inputSource=inputState.ArrowKeys))
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return 'ControlManager: using \'%s\'' % self.currentControlsName
|
||||
|
||||
|
|
@ -325,7 +322,7 @@ class ControlManager:
|
|||
self.WASDTurnTokens = (
|
||||
inputState.watchWithModifiers("turnLeft", "a", inputSource=inputState.WASD),
|
||||
inputState.watchWithModifiers("turnRight", "d", inputSource=inputState.WASD),
|
||||
)
|
||||
)
|
||||
|
||||
inputState.set("turnLeft", slideLeftWASDSet, inputSource=inputState.WASD)
|
||||
inputState.set("turnRight", slideRightWASDSet, inputSource=inputState.WASD)
|
||||
|
|
@ -337,7 +334,7 @@ class ControlManager:
|
|||
self.WASDTurnTokens = (
|
||||
inputState.watchWithModifiers("slideLeft", "a", inputSource=inputState.WASD),
|
||||
inputState.watchWithModifiers("slideRight", "d", inputSource=inputState.WASD),
|
||||
)
|
||||
)
|
||||
|
||||
inputState.set("slideLeft", turnLeftWASDSet, inputSource=inputState.WASD)
|
||||
inputState.set("slideRight", turnRightWASDSet, inputSource=inputState.WASD)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ from direct.showbase import DirectObject
|
|||
from direct.showbase.MessengerGlobal import messenger
|
||||
from direct.task.Task import Task
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from panda3d.core import *
|
||||
from panda3d.core import ClockObject, ConfigVariableBool, ConfigVariableDouble, Mat3, Point3, Vec3
|
||||
|
||||
|
||||
class DevWalker(DirectObject.DirectObject):
|
||||
|
|
|
|||
|
|
@ -22,9 +22,24 @@ from direct.showbase.InputStateGlobal import inputState
|
|||
from direct.showbase.MessengerGlobal import messenger
|
||||
from direct.task.Task import Task
|
||||
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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,36 +8,47 @@ from direct.showbase.MessengerGlobal import messenger
|
|||
class InputStateToken:
|
||||
_SerialGen = SerialNumGen()
|
||||
Inval = 'invalidatedToken'
|
||||
|
||||
def __init__(self, inputState):
|
||||
self._id = InputStateToken._SerialGen.next()
|
||||
self._hash = self._id
|
||||
self._inputState = inputState
|
||||
|
||||
def release(self):
|
||||
# subclasses will override
|
||||
assert False
|
||||
|
||||
def isValid(self):
|
||||
return self._id != InputStateToken.Inval
|
||||
|
||||
def invalidate(self):
|
||||
self._id = InputStateToken.Inval
|
||||
|
||||
def __hash__(self):
|
||||
return self._hash
|
||||
|
||||
#snake_case alias:
|
||||
is_valid = isValid
|
||||
|
||||
|
||||
class InputStateWatchToken(InputStateToken, DirectObject.DirectObject):
|
||||
def release(self):
|
||||
self._inputState._ignore(self)
|
||||
self.ignoreAll()
|
||||
|
||||
|
||||
class InputStateForceToken(InputStateToken):
|
||||
def release(self):
|
||||
self._inputState._unforce(self)
|
||||
|
||||
|
||||
class InputStateTokenGroup:
|
||||
def __init__(self):
|
||||
self._tokens = []
|
||||
|
||||
def addToken(self, token):
|
||||
self._tokens.append(token)
|
||||
|
||||
def release(self):
|
||||
for token in self._tokens:
|
||||
token.release()
|
||||
|
|
@ -46,6 +57,7 @@ class InputStateTokenGroup:
|
|||
#snake_case alias:
|
||||
add_token = addToken
|
||||
|
||||
|
||||
class InputState(DirectObject.DirectObject):
|
||||
"""
|
||||
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.
|
||||
# self.set(name, False, inputSource)
|
||||
|
||||
|
||||
def force(self, name, value, inputSource):
|
||||
"""
|
||||
Force isSet(name) to return 'value'.
|
||||
|
|
@ -213,7 +224,7 @@ class InputState(DirectObject.DirectObject):
|
|||
self.notify.error(
|
||||
"%s is trying to force '%s' to ON, but '%s' is already being forced OFF by %s" %
|
||||
(inputSource, name, name, self._forcingOff[name])
|
||||
)
|
||||
)
|
||||
self._forcingOn.setdefault(name, set())
|
||||
self._forcingOn[name].add(inputSource)
|
||||
else:
|
||||
|
|
@ -221,7 +232,7 @@ class InputState(DirectObject.DirectObject):
|
|||
self.notify.error(
|
||||
"%s is trying to force '%s' to OFF, but '%s' is already being forced ON by %s" %
|
||||
(inputSource, name, name, self._forcingOn[name])
|
||||
)
|
||||
)
|
||||
self._forcingOff.setdefault(name, set())
|
||||
self._forcingOff[name].add(inputSource)
|
||||
return token
|
||||
|
|
|
|||
|
|
@ -23,7 +23,20 @@ from direct.showbase.InputStateGlobal import inputState
|
|||
from direct.showbase.MessengerGlobal import messenger
|
||||
from direct.task.Task import Task
|
||||
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):
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory("NonPhysicsWalker")
|
||||
|
|
|
|||
|
|
@ -16,7 +16,13 @@ although it does send messages that allow a listener to play sounds or
|
|||
animations based on walker events.
|
||||
"""
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import (
|
||||
BitMask32,
|
||||
CollisionHandlerPusher,
|
||||
CollisionNode,
|
||||
CollisionSphere,
|
||||
CollisionTraverser,
|
||||
)
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
from . import NonPhysicsWalker
|
||||
|
||||
|
|
|
|||
|
|
@ -23,15 +23,39 @@ from direct.showbase.InputStateGlobal import inputState
|
|||
from direct.showbase.MessengerGlobal import messenger
|
||||
from direct.task.Task import Task
|
||||
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 LineStream
|
||||
|
||||
|
||||
class PhysicsWalker(DirectObject.DirectObject):
|
||||
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory("PhysicsWalker")
|
||||
|
|
@ -523,7 +547,7 @@ class PhysicsWalker(DirectObject.DirectObject):
|
|||
onScreenDebug.add("highMark", "% 10.4f"%(self.highMark,))
|
||||
#if airborneHeight < 0.1: #contact!=Vec3.zero():
|
||||
if (airborneHeight > self.avatarRadius*0.5
|
||||
or physObject.getVelocity().getZ() > 0.0
|
||||
or physObject.getVelocity().getZ() > 0.0
|
||||
): # Check stair angles before changing this.
|
||||
# ...the avatar is airborne (maybe a lot or a tiny amount).
|
||||
self.isAirborne = 1
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@
|
|||
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 panda3d.core import ConfigVariableBool
|
||||
from direct.task.Task import Task
|
||||
from panda3d.core import ConfigVariableBool, Vec3
|
||||
|
||||
|
||||
class TwoDWalker(GravityWalker):
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ PUBLISHED:
|
|||
const DCClass *get_class() const;
|
||||
|
||||
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,
|
||||
const std::string &name, const std::string &postname) const;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
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
|
||||
base = ShowBase.ShowBase()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
|
||||
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
|
||||
|
||||
base = ThreeUpShow.ThreeUpShow()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
"""Class used to create and control VRPN devices."""
|
||||
|
||||
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_MAX = 0.95
|
||||
|
|
@ -52,7 +59,7 @@ class DirectButtons(ButtonNode, DirectObject):
|
|||
# Attach node to data graph
|
||||
try:
|
||||
self._base = base
|
||||
except:
|
||||
except NameError:
|
||||
self._base = simbase
|
||||
self.nodePath = self._base.dataRoot.attachNewNode(self)
|
||||
|
||||
|
|
@ -101,7 +108,7 @@ class DirectAnalogs(AnalogNode, DirectObject):
|
|||
# Attach node to data graph
|
||||
try:
|
||||
self._base = base
|
||||
except:
|
||||
except NameError:
|
||||
self._base = simbase
|
||||
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):
|
||||
try:
|
||||
return self.normalize(self[chan], minVal, maxVal, sfx)
|
||||
return self.normalize(self[chan], minVal, maxVal, sf)
|
||||
except IndexError:
|
||||
return 0.0
|
||||
|
||||
|
|
@ -199,7 +206,7 @@ class DirectTracker(TrackerNode, DirectObject):
|
|||
# Attach node to data graph
|
||||
try:
|
||||
self._base = base
|
||||
except:
|
||||
except NameError:
|
||||
self._base = simbase
|
||||
self.nodePath = self._base.dataRoot.attachNewNode(self)
|
||||
|
||||
|
|
@ -231,7 +238,7 @@ class DirectDials(DialNode, DirectObject):
|
|||
# Attach node to data graph
|
||||
try:
|
||||
self._base = base
|
||||
except:
|
||||
except NameError:
|
||||
self._base = simbase
|
||||
self.nodePath = self._base.dataRoot.attachNewNode(self)
|
||||
|
||||
|
|
@ -282,7 +289,7 @@ class DirectTimecodeReader(AnalogNode, DirectObject):
|
|||
# Attach node to data graph
|
||||
try:
|
||||
self._base = base
|
||||
except:
|
||||
except NameError:
|
||||
self._base = simbase
|
||||
self.nodePath = self._base.dataRoot.attachNewNode(self)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
""" Class used to create and control radamec device """
|
||||
from panda3d.core import Vec3
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
from direct.task.Task import Task
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from .DirectDeviceManager import *
|
||||
from .DirectDeviceManager import DirectDeviceManager
|
||||
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
""" Class used to create and control joybox device """
|
||||
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.task import Task
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from panda3d.core import ClockObject
|
||||
from panda3d.core import ButtonRegistry, ButtonThrower, ClockObject, NodePath, VBase3, Vec3
|
||||
|
||||
import math
|
||||
|
||||
|
|
@ -35,6 +35,7 @@ JOYBOX_RANGE = JOYBOX_MAX - JOYBOX_MIN
|
|||
|
||||
JOYBOX_TREAD_SEPERATION = 1.0
|
||||
|
||||
|
||||
class DirectJoybox(DirectObject):
|
||||
joyboxCount = 0
|
||||
xyzMultiplier = 1.0
|
||||
|
|
@ -87,12 +88,10 @@ class DirectJoybox(DirectObject):
|
|||
# Spawn update task
|
||||
self.enable()
|
||||
|
||||
|
||||
def setHeadingNodePath(self,np):
|
||||
|
||||
self.headingNP = np
|
||||
|
||||
|
||||
def enable(self):
|
||||
# Kill existing task
|
||||
self.disable()
|
||||
|
|
@ -126,18 +125,25 @@ class DirectJoybox(DirectObject):
|
|||
|
||||
def getNodePath(self):
|
||||
return self.nodePath
|
||||
|
||||
def setRefCS(self, refCS):
|
||||
self.refCS = refCS
|
||||
|
||||
def getRefCS(self):
|
||||
return self.refCS
|
||||
|
||||
def getEventName(self, index):
|
||||
return self.name + '-button-' + repr(index)
|
||||
|
||||
def setXyzMultiplier(self, multiplier):
|
||||
DirectJoybox.xyzMultiplier = multiplier
|
||||
|
||||
def getXyzMultiplier(self):
|
||||
return DirectJoybox.xyzMultiplier
|
||||
|
||||
def setHprMultiplier(self, multiplier):
|
||||
DirectJoybox.hprMultiplier = multiplier
|
||||
|
||||
def getHprMultiplier(self):
|
||||
return DirectJoybox.hprMultiplier
|
||||
|
||||
|
|
@ -193,6 +199,7 @@ class DirectJoybox(DirectObject):
|
|||
|
||||
def acceptSwitchModeEvent(self, button = R_UPPER):
|
||||
self.accept(self.getEventName(button), self.switchMode)
|
||||
|
||||
def ignoreSwitchModeEvent(self, button = R_UPPER):
|
||||
self.ignore(self.getEventName(button))
|
||||
|
||||
|
|
@ -208,7 +215,7 @@ class DirectJoybox(DirectObject):
|
|||
pass
|
||||
|
||||
def showMode(self, modeText):
|
||||
def hideText(state, s = self):
|
||||
def hideText(state, s=self):
|
||||
s.readout.setText('')
|
||||
return Task.done
|
||||
taskMgr.remove(self.name + '-showMode')
|
||||
|
|
@ -220,6 +227,7 @@ class DirectJoybox(DirectObject):
|
|||
def acceptUprightCameraEvent(self, button = L_UPPER):
|
||||
self.accept(self.getEventName(button),
|
||||
base.direct.cameraControl.orbitUprightCam)
|
||||
|
||||
def ignoreUprightCameraEvent(self, button = L_UPPER):
|
||||
self.ignore(self.getEventName(button))
|
||||
|
||||
|
|
@ -230,29 +238,29 @@ class DirectJoybox(DirectObject):
|
|||
self.showMode(self.modeName)
|
||||
self.enable()
|
||||
|
||||
|
||||
def setUseHeadingNP(self,enabled):
|
||||
|
||||
def setUseHeadingNP(self, enabled):
|
||||
self.useHeadingNP = enabled
|
||||
|
||||
def setRotateInPlace(self,enabled):
|
||||
|
||||
def setRotateInPlace(self, enabled):
|
||||
self.rotateInPlace = enabled
|
||||
|
||||
def joyboxFly(self):
|
||||
# Do nothing if no nodePath selected
|
||||
if self.nodePath is None:
|
||||
return
|
||||
|
||||
hprScale = ((self.aList[L_SLIDE] + 1.0) *
|
||||
50.0 * DirectJoybox.hprMultiplier)
|
||||
posScale = ((self.aList[R_SLIDE] + 1.0) *
|
||||
50.0 * DirectJoybox.xyzMultiplier)
|
||||
def getAxisVal(index, s = self):
|
||||
|
||||
def getAxisVal(index, s=self):
|
||||
try:
|
||||
return s.aList[s.mapping[index]]
|
||||
except IndexError:
|
||||
# If it is a null axis return 0
|
||||
return 0.0
|
||||
|
||||
x = getAxisVal(0) * self.modifier[0]
|
||||
y = getAxisVal(1) * self.modifier[1]
|
||||
z = getAxisVal(2) * self.modifier[2]
|
||||
|
|
@ -262,13 +270,13 @@ class DirectJoybox(DirectObject):
|
|||
p = getAxisVal(4) * self.modifier[4]
|
||||
r = getAxisVal(5) * self.modifier[5]
|
||||
hpr = Vec3(h, p, r) * (hprScale * self.deltaTime)
|
||||
|
||||
# if we are using a heading nodepath, we want
|
||||
# to drive in the direction we are facing,
|
||||
# however, we don't want the z component to change
|
||||
if self.useHeadingNP and self.headingNP is not None:
|
||||
oldZ = pos.getZ()
|
||||
pos = self.nodePath.getRelativeVector(self.headingNP,
|
||||
pos)
|
||||
pos = self.nodePath.getRelativeVector(self.headingNP, pos)
|
||||
pos.setZ(oldZ)
|
||||
# if we are using a heading NP we might want to rotate
|
||||
# in place around that NP
|
||||
|
|
@ -282,7 +290,6 @@ class DirectJoybox(DirectObject):
|
|||
self.nodePath.wrtReparentTo(parent)
|
||||
hpr = Vec3(0,0,0)
|
||||
|
||||
|
||||
self.nodePath.setPosHpr(self.nodePath, pos, hpr)
|
||||
|
||||
def joeMode(self):
|
||||
|
|
@ -291,25 +298,23 @@ class DirectJoybox(DirectObject):
|
|||
self.modifier = [1, 1, 1, -1, -1, 0]
|
||||
self.setMode(self.joyboxFly, 'Joe Mode')
|
||||
|
||||
|
||||
def basicMode(self):
|
||||
self.mapping = [NULL_AXIS, R_FWD_BACK, 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):
|
||||
self.mapping = [L_LEFT_RIGHT,R_FWD_BACK,L_FWD_BACK,
|
||||
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):
|
||||
self.setMode(self.tankFly,'Tank Mode')
|
||||
self.setMode(self.tankFly, 'Tank Mode')
|
||||
|
||||
def nullMode(self):
|
||||
self.setMode(self.nullFly,'Null Mode')
|
||||
|
||||
self.setMode(self.nullFly, 'Null Mode')
|
||||
|
||||
def lucMode(self):
|
||||
self.mapping = [R_LEFT_RIGHT, R_FWD_BACK, L_FWD_BACK,
|
||||
|
|
@ -362,7 +367,6 @@ class DirectJoybox(DirectObject):
|
|||
def spaceMode(self):
|
||||
self.setMode(self.spaceFly, 'Space Mode')
|
||||
|
||||
|
||||
def nullFly(self):
|
||||
return
|
||||
|
||||
|
|
@ -384,10 +388,6 @@ class DirectJoybox(DirectObject):
|
|||
self.nodePath.setH(self.nodePath,dh)
|
||||
self.nodePath.setY(self.nodePath,dy)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def spaceFly(self):
|
||||
# Do nothing if no nodePath selected
|
||||
if self.nodePath is None:
|
||||
|
|
@ -498,9 +498,9 @@ class DirectJoybox(DirectObject):
|
|||
# Restore the original hpr of the orbiter
|
||||
self.nodePath.setHpr(self.tempCS, 0, 0, 0)
|
||||
|
||||
|
||||
# We need to override the DirectAnalog normalizeChannel to
|
||||
# correct the ranges of the two twist axes of the joybox.
|
||||
|
||||
def normalizeChannel(self, chan, minVal = -1, maxVal = 1):
|
||||
try:
|
||||
if chan == L_TWIST or chan == R_TWIST:
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
""" Class used to create and control radamec device """
|
||||
from math import *
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
from direct.task.Task import Task
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from .DirectDeviceManager import *
|
||||
from .DirectDeviceManager import DirectDeviceManager
|
||||
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ DirectNotify module: this module contains the DirectNotify class
|
|||
from . import Notifier
|
||||
from . import Logger
|
||||
|
||||
|
||||
class DirectNotify:
|
||||
"""
|
||||
DirectNotify class: this class contains methods for creating
|
||||
|
|
@ -15,7 +16,7 @@ class DirectNotify:
|
|||
"""
|
||||
DirectNotify class keeps a dictionary of Notfiers
|
||||
"""
|
||||
self.__categories = { }
|
||||
self.__categories = {}
|
||||
# create a default log file
|
||||
self.logger = Logger.Logger()
|
||||
|
||||
|
|
@ -100,7 +101,6 @@ class DirectNotify:
|
|||
print("DirectNotify: unknown notify level: " + str(level)
|
||||
+ " for category: " + str(categoryName))
|
||||
|
||||
|
||||
def setDconfigLevels(self):
|
||||
for categoryName in self.getCategories():
|
||||
self.setDconfigLevel(categoryName)
|
||||
|
|
|
|||
|
|
@ -126,10 +126,10 @@ class Notifier:
|
|||
Exception: error
|
||||
"""
|
||||
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:
|
||||
string = (str(exception) + ": " + self.__name + "(error): " + message)
|
||||
string = f'{exception!s}: {self.__name}(error): {message}'
|
||||
self.__log(string)
|
||||
raise exception(errorString)
|
||||
|
||||
|
|
@ -140,10 +140,10 @@ class Notifier:
|
|||
"""
|
||||
if self.__warning:
|
||||
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:
|
||||
string = (":" + self.__name + '(warning): ' + message)
|
||||
string = f':{self.__name}(warning): {message}'
|
||||
self.__log(string)
|
||||
self.__print(string)
|
||||
return 1 # to allow assert myNotify.warning("blah")
|
||||
|
|
@ -167,10 +167,10 @@ class Notifier:
|
|||
"""
|
||||
if self.__debug:
|
||||
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:
|
||||
string = (':' + self.__name + '(debug): ' + message)
|
||||
string = f':{self.__name}(debug): {message}'
|
||||
self.__log(string)
|
||||
self.__print(string)
|
||||
return 1 # to allow assert myNotify.debug("blah")
|
||||
|
|
@ -194,10 +194,10 @@ class Notifier:
|
|||
"""
|
||||
if self.__info:
|
||||
message = str(infoString)
|
||||
if Notifier.showTime.getValue():
|
||||
string = (self.getTime() + self.__name + ': ' + message)
|
||||
if Notifier.showTime:
|
||||
string = f'{self.getTime()}{self.__name}: {message}'
|
||||
else:
|
||||
string = (':' + self.__name + ': ' + message)
|
||||
string = f':{self.__name}: {message}'
|
||||
self.__log(string)
|
||||
self.__print(string)
|
||||
return 1 # to allow assert myNotify.info("blah")
|
||||
|
|
@ -271,7 +271,7 @@ class Notifier:
|
|||
state = "%s, %s"%(state, stateObj.getName())
|
||||
|
||||
if hasattr(obj, 'doId'):
|
||||
doId = " doId:%s"%(obj.doId,)
|
||||
doId = f" doId:{obj.doId}"
|
||||
#if type(obj) == types.ClassType:
|
||||
# name = "%s."%(obj.__class__.__name__,)
|
||||
string = ":%s:%s [%-7s] id(%s)%s %s"%(
|
||||
|
|
|
|||
|
|
@ -11,7 +11,15 @@
|
|||
import os
|
||||
import sys
|
||||
import gc
|
||||
from panda3d.core import *
|
||||
from panda3d.core import (
|
||||
BamCache,
|
||||
ExecutionEnvironment,
|
||||
Filename,
|
||||
Loader,
|
||||
LoaderOptions,
|
||||
ModelPool,
|
||||
TexturePool,
|
||||
)
|
||||
|
||||
class EggCacher:
|
||||
def __init__(self, args):
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ from panda3d.interrogatedb import *
|
|||
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
|
@ -65,6 +65,7 @@ def comment(code):
|
|||
else:
|
||||
return ''
|
||||
|
||||
|
||||
def block_comment(code):
|
||||
code = code.strip()
|
||||
|
||||
|
|
@ -77,6 +78,7 @@ def block_comment(code):
|
|||
|
||||
return code
|
||||
|
||||
|
||||
def translateFunctionName(name):
|
||||
if name.startswith("__"):
|
||||
return name
|
||||
|
|
@ -93,6 +95,7 @@ def translateFunctionName(name):
|
|||
new += i[0].upper() + i[1:]
|
||||
return new
|
||||
|
||||
|
||||
def translateTypeName(name, mangle=True):
|
||||
# Equivalent to C++ classNameFromCppName
|
||||
class_name = ""
|
||||
|
|
@ -115,6 +118,7 @@ def translateTypeName(name, mangle=True):
|
|||
|
||||
return class_name
|
||||
|
||||
|
||||
def translated_type_name(type, scoped=True):
|
||||
while interrogate_type_is_wrapped(type):
|
||||
if interrogate_type_is_const(type):
|
||||
|
|
@ -205,7 +209,7 @@ def processFunction(handle, function, isConstructor = False):
|
|||
|
||||
def processType(handle, type):
|
||||
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):
|
||||
print(block_comment(interrogate_type_comment(type)), file=handle)
|
||||
|
|
@ -258,6 +262,7 @@ def processType(handle, type):
|
|||
|
||||
print("};", file=handle)
|
||||
|
||||
|
||||
def processModule(handle, package):
|
||||
print("Processing module %s" % (package))
|
||||
print("namespace %s {" % package, file=handle)
|
||||
|
|
|
|||
|
|
@ -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 .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 direct.interval.IntervalGlobal import Sequence, Func
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
|
|
@ -12,6 +14,7 @@ CAM_MOVE_DURATION = 1.2
|
|||
COA_MARKER_SF = 0.0075
|
||||
Y_AXIS = Vec3(0, 1, 0)
|
||||
|
||||
|
||||
class DirectCameraControl(DirectObject):
|
||||
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory('DirectCameraControl')
|
||||
|
|
@ -48,7 +51,7 @@ class DirectCameraControl(DirectObject):
|
|||
['DIRECT-mouse2Up', self.mouseFlyStop],
|
||||
['DIRECT-mouse3', self.mouseDollyStart],
|
||||
['DIRECT-mouse3Up', self.mouseDollyStop],
|
||||
]
|
||||
]
|
||||
|
||||
# [gjeon] moved all of the hotkeys to single place for easy remapping
|
||||
## self.keyEvents = [
|
||||
|
|
@ -99,7 +102,7 @@ class DirectCameraControl(DirectObject):
|
|||
['DIRECT-removeManipulateCameraTask', self.removeManipulateCameraTask],
|
||||
['DIRECT-zoomInCam', self.zoomCam, 0.5, t],
|
||||
['DIRECT-zoomOutCam', self.zoomCam, -2.0, t],
|
||||
]
|
||||
]
|
||||
# set this to true to prevent the camera from rolling
|
||||
self.lockRoll = False
|
||||
# NIK - flag to determine whether to use maya camera controls
|
||||
|
|
@ -218,9 +221,9 @@ class DirectCameraControl(DirectObject):
|
|||
# Allow intersection with unpickable objects
|
||||
# And then spawn task to determine mouse mode
|
||||
# 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
|
||||
skipFlags |= SKIP_CAMERA * (1 - base.getControl())
|
||||
skipFlags |= DG.SKIP_CAMERA * (1 - base.getControl())
|
||||
self.computeCOA(base.direct.iRay.pickGeom(skipFlags = skipFlags))
|
||||
# Record reference point
|
||||
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):
|
||||
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,
|
||||
(-0.5 * base.direct.dr.mouseDeltaX *
|
||||
base.direct.dr.nearWidth *
|
||||
|
|
@ -349,7 +352,7 @@ class DirectCameraControl(DirectObject):
|
|||
else:
|
||||
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)
|
||||
* state.zoomSF))
|
||||
hVal = 0.0
|
||||
|
|
@ -422,7 +425,7 @@ class DirectCameraControl(DirectObject):
|
|||
|
||||
# Set at markers position in render coordinates
|
||||
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)
|
||||
if abs(base.direct.dr.mouseX) > 0.9:
|
||||
t.constrainedDir = 'y'
|
||||
|
|
@ -454,7 +457,7 @@ class DirectCameraControl(DirectObject):
|
|||
# flatten roll
|
||||
base.direct.camera.setR(0)
|
||||
self.camManipRef.setPos(self.coaMarkerPos)
|
||||
self.camManipRef.setHpr(base.direct.camera, ZERO_POINT)
|
||||
self.camManipRef.setHpr(base.direct.camera, DG.ZERO_POINT)
|
||||
else:
|
||||
if base.direct.camera.getPos().getZ() >=0 or not self.switchDirBelowZero:
|
||||
dirX = -1
|
||||
|
|
@ -478,7 +481,7 @@ class DirectCameraControl(DirectObject):
|
|||
self.__stopManipulateCamera()
|
||||
# Set at markers position in render coordinates
|
||||
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.coaCenter = getScreenXY(self.coaMarker)
|
||||
t.lastAngle = getCrankAngle(t.coaCenter)
|
||||
|
|
@ -565,7 +568,7 @@ class DirectCameraControl(DirectObject):
|
|||
base.direct.message('COA Distance: ' + repr(dist))
|
||||
coa.set(0, dist, 0)
|
||||
# Compute COA Dist
|
||||
coaDist = Vec3(coa - ZERO_POINT).length()
|
||||
coaDist = Vec3(coa - DG.ZERO_POINT).length()
|
||||
if coaDist < (1.1 * dr.near):
|
||||
coa.set(0, 100, 0)
|
||||
coaDist = 100
|
||||
|
|
@ -575,7 +578,7 @@ class DirectCameraControl(DirectObject):
|
|||
def updateCoa(self, ref2point, coaDist = None, ref = None):
|
||||
self.coa.set(ref2point[0], ref2point[1], ref2point[2])
|
||||
if not coaDist:
|
||||
coaDist = Vec3(self.coa - ZERO_POINT).length()
|
||||
coaDist = Vec3(self.coa - DG.ZERO_POINT).length()
|
||||
# Place the marker in render space
|
||||
if ref is None:
|
||||
# KEH: use the current display region
|
||||
|
|
@ -611,7 +614,7 @@ class DirectCameraControl(DirectObject):
|
|||
startColor = Vec4(1, 0, 0, 1),
|
||||
blendType = 'easeInOut'),
|
||||
Func(self.coaMarker.stash)
|
||||
)
|
||||
)
|
||||
self.coaMarkerColorIval.start()
|
||||
|
||||
def homeCam(self):
|
||||
|
|
@ -642,19 +645,19 @@ class DirectCameraControl(DirectObject):
|
|||
# Transform camera z axis to render space
|
||||
mCam2Render = Mat4(Mat4.identMat()) # [gjeon] fixed to give required argument
|
||||
mCam2Render.assign(base.direct.camera.getMat(render))
|
||||
zAxis = Vec3(mCam2Render.xformVec(Z_AXIS))
|
||||
zAxis = Vec3(mCam2Render.xformVec(DG.Z_AXIS))
|
||||
zAxis.normalize()
|
||||
# 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
|
||||
if orbitAngle < 0.1:
|
||||
# Already upright
|
||||
return
|
||||
# Compute orthogonal axis of rotation
|
||||
rotAxis = Vec3(zAxis.cross(Z_AXIS))
|
||||
rotAxis = Vec3(zAxis.cross(DG.Z_AXIS))
|
||||
rotAxis.normalize()
|
||||
# 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
|
||||
if rotAxis[1] < 0:
|
||||
rotAngle *= -1
|
||||
|
|
@ -685,7 +688,7 @@ class DirectCameraControl(DirectObject):
|
|||
base.direct.pushUndo([base.direct.camera])
|
||||
# Determine marker location
|
||||
markerToCam = self.coaMarker.getPos(base.direct.camera)
|
||||
dist = Vec3(markerToCam - ZERO_POINT).length()
|
||||
dist = Vec3(markerToCam - DG.ZERO_POINT).length()
|
||||
scaledCenterVec = Y_AXIS * dist
|
||||
delta = markerToCam - scaledCenterVec
|
||||
self.camManipRef.setPosHpr(base.direct.camera, Point3(0), Point3(0))
|
||||
|
|
@ -697,7 +700,6 @@ class DirectCameraControl(DirectObject):
|
|||
name = 'manipulateCamera')
|
||||
self.__startManipulateCamera(ival = ival)
|
||||
|
||||
|
||||
def zoomCam(self, zoomFactor, t):
|
||||
self.__stopManipulateCamera()
|
||||
# Record undo point
|
||||
|
|
@ -709,7 +711,7 @@ class DirectCameraControl(DirectObject):
|
|||
self.camManipRef.setPos(base.direct.camera, zoomPtToCam)
|
||||
# Move to that point
|
||||
ival = base.direct.camera.posInterval(CAM_MOVE_DURATION,
|
||||
ZERO_POINT,
|
||||
DG.ZERO_POINT,
|
||||
other = self.camManipRef,
|
||||
blendType = 'easeInOut')
|
||||
ival = Sequence(ival, Func(self.updateCoaMarkerSizeOnDeath),
|
||||
|
|
@ -746,20 +748,20 @@ class DirectCameraControl(DirectObject):
|
|||
elif view == 7:
|
||||
hprOffset.set(135., -35.264, 0.)
|
||||
# Position target
|
||||
self.camManipRef.setPosHpr(self.coaMarker, ZERO_VEC,
|
||||
self.camManipRef.setPosHpr(self.coaMarker, DG.ZERO_VEC,
|
||||
hprOffset)
|
||||
# Scale center vec by current distance to target
|
||||
offsetDistance = Vec3(base.direct.camera.getPos(self.camManipRef) -
|
||||
ZERO_POINT).length()
|
||||
DG.ZERO_POINT).length()
|
||||
scaledCenterVec = Y_AXIS * (-1.0 * offsetDistance)
|
||||
# Now put the camManipRef at that point
|
||||
self.camManipRef.setPosHpr(self.camManipRef,
|
||||
scaledCenterVec,
|
||||
ZERO_VEC)
|
||||
DG.ZERO_VEC)
|
||||
# Record view for next time around
|
||||
self.lastView = view
|
||||
ival = base.direct.camera.posHprInterval(CAM_MOVE_DURATION,
|
||||
pos = ZERO_POINT,
|
||||
pos = DG.ZERO_POINT,
|
||||
hpr = VBase3(0, 0, self.orthoViewRoll),
|
||||
other = self.camManipRef,
|
||||
blendType = 'easeInOut')
|
||||
|
|
@ -767,7 +769,6 @@ class DirectCameraControl(DirectObject):
|
|||
name = 'manipulateCamera')
|
||||
self.__startManipulateCamera(ival = ival)
|
||||
|
||||
|
||||
def swingCamAboutWidget(self, degrees, t):
|
||||
# Remove existing camera manipulation task
|
||||
self.__stopManipulateCamera()
|
||||
|
|
@ -776,9 +777,9 @@ class DirectCameraControl(DirectObject):
|
|||
base.direct.pushUndo([base.direct.camera])
|
||||
|
||||
# Coincident with widget
|
||||
self.camManipRef.setPos(self.coaMarker, ZERO_POINT)
|
||||
self.camManipRef.setPos(self.coaMarker, DG.ZERO_POINT)
|
||||
# But aligned with render space
|
||||
self.camManipRef.setHpr(ZERO_POINT)
|
||||
self.camManipRef.setHpr(DG.ZERO_POINT)
|
||||
|
||||
parent = base.direct.camera.getParent()
|
||||
base.direct.camera.wrtReparentTo(self.camManipRef)
|
||||
|
|
@ -820,7 +821,8 @@ class DirectCameraControl(DirectObject):
|
|||
try:
|
||||
self.camManipRef.setPos(base.direct.camera, deltaMove)
|
||||
except Exception:
|
||||
self.notify.debug
|
||||
#self.notify.debug
|
||||
pass
|
||||
|
||||
parent = base.direct.camera.getParent()
|
||||
base.direct.camera.wrtReparentTo(self.camManipRef)
|
||||
|
|
@ -831,7 +833,6 @@ class DirectCameraControl(DirectObject):
|
|||
name = 'manipulateCamera')
|
||||
self.__startManipulateCamera(ival = ival)
|
||||
|
||||
|
||||
def moveToFit(self):
|
||||
# How big is the active widget?
|
||||
widgetScale = base.direct.widget.scalingNode.getScale(render)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
class LineNodePath(NodePath):
|
||||
def __init__(self, parent = None, name = None,
|
||||
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
|
||||
## 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
|
||||
offset = planeOrigin - lineOrigin
|
||||
t = offset.dot(normal) / lineDir.dot(normal)
|
||||
hitPt = lineDir * t
|
||||
return hitPt + lineOrigin
|
||||
|
||||
|
||||
def getNearProjectionPoint(nodePath):
|
||||
# Find the position of the projection of the specified node path
|
||||
# on the near plane
|
||||
|
|
@ -144,6 +162,7 @@ def getNearProjectionPoint(nodePath):
|
|||
# Object is coplaner with camera, just return something reasonable
|
||||
return Point3(0, base.direct.dr.near, 0)
|
||||
|
||||
|
||||
def getScreenXY(nodePath):
|
||||
# Where does the node path's projection fall on the near plane
|
||||
nearVec = getNearProjectionPoint(nodePath)
|
||||
|
|
@ -158,6 +177,7 @@ def getScreenXY(nodePath):
|
|||
# Return the resulting value
|
||||
return screenXY
|
||||
|
||||
|
||||
def getCrankAngle(center):
|
||||
# Used to compute current angle of mouse (relative to the coa's
|
||||
# origin) in screen space
|
||||
|
|
@ -165,6 +185,7 @@ def getCrankAngle(center):
|
|||
y = base.direct.dr.mouseY - center[2]
|
||||
return 180 + rad2Deg(math.atan2(y, x))
|
||||
|
||||
|
||||
def relHpr(nodePath, base, h, p, r):
|
||||
# Compute nodePath2newNodePath relative to base coordinate system
|
||||
# nodePath2base
|
||||
|
|
@ -188,6 +209,8 @@ def relHpr(nodePath, base, h, p, r):
|
|||
nodePath.setHpr(hpr)
|
||||
|
||||
# Quaternion interpolation
|
||||
|
||||
|
||||
def qSlerp(startQuat, endQuat, t):
|
||||
startQ = Quat(startQuat)
|
||||
destQuat = Quat(Quat.identQuat())
|
||||
|
|
|
|||
|
|
@ -51,11 +51,11 @@ LE_CAM_MASKS = {'persp':LE_PERSP_CAM_MASK,
|
|||
'top':LE_TOP_CAM_MASK}
|
||||
|
||||
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):
|
||||
LE_showInAllCam(nodePath)
|
||||
for camName in LE_CAM_MASKS:
|
||||
for camName, mask in LE_CAM_MASKS.items():
|
||||
if camName != thisCamName:
|
||||
nodePath.hide(LE_CAM_MASKS[camName])
|
||||
nodePath.hide(mask)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
from panda3d.core import *
|
||||
import math
|
||||
from panda3d.core import NodePath, Point3, VBase4
|
||||
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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.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 direct.task import Task
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
|
|
@ -50,8 +72,8 @@ class DirectManipulationControl(DirectObject):
|
|||
['DIRECT-widgetScaleDown', self.scaleWidget, 0.5],
|
||||
['shift-f', self.objectHandles.growToFit],
|
||||
['i', self.plantSelectedNodePath],
|
||||
]
|
||||
self.defaultSkipFlags = SKIP_HIDDEN | SKIP_BACKFACE
|
||||
]
|
||||
self.defaultSkipFlags = DG.SKIP_HIDDEN | DG.SKIP_BACKFACE
|
||||
self.optionalSkipFlags = 0
|
||||
self.unmovableTagList = []
|
||||
|
||||
|
|
@ -115,7 +137,7 @@ class DirectManipulationControl(DirectObject):
|
|||
self.fScaling3D == 0:
|
||||
|
||||
# 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?
|
||||
if entry:
|
||||
# Yes!
|
||||
|
|
@ -137,7 +159,7 @@ class DirectManipulationControl(DirectObject):
|
|||
if entry:
|
||||
# Check to see if we are moving the object
|
||||
# We are moving the object if we either wait long enough
|
||||
taskMgr.doMethodLater(MANIPULATION_MOVE_DELAY,
|
||||
taskMgr.doMethodLater(DG.MANIPULATION_MOVE_DELAY,
|
||||
self.switchToMoveMode,
|
||||
'manip-move-wait')
|
||||
# Or we move far enough
|
||||
|
|
@ -170,8 +192,8 @@ class DirectManipulationControl(DirectObject):
|
|||
return Task.done
|
||||
|
||||
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')
|
||||
self.mode = 'move'
|
||||
self.manipulateObject()
|
||||
|
|
@ -199,8 +221,8 @@ class DirectManipulationControl(DirectObject):
|
|||
endX = base.direct.dr.mouseX
|
||||
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
|
||||
|
||||
self.marquee = LineNodePath(base.render2d, 'marquee', 0.5, VBase4(.8, .6, .6, 1))
|
||||
|
|
@ -213,7 +235,7 @@ class DirectManipulationControl(DirectObject):
|
|||
self.marquee.create()
|
||||
|
||||
if self.fMultiView:
|
||||
LE_showInOneCam(self.marquee, base.direct.camera.getName())
|
||||
DG.LE_showInOneCam(self.marquee, base.direct.camera.getName())
|
||||
|
||||
def manipulationStop(self):
|
||||
taskMgr.remove('manipulateObject')
|
||||
|
|
@ -227,7 +249,7 @@ class DirectManipulationControl(DirectObject):
|
|||
# optionally specified things
|
||||
skipFlags = self.defaultSkipFlags | self.optionalSkipFlags
|
||||
# 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:
|
||||
self.marquee.removeNode()
|
||||
|
|
@ -269,18 +291,18 @@ class DirectManipulationControl(DirectObject):
|
|||
|
||||
selectionList = []
|
||||
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
|
||||
continue
|
||||
## elif (skipFlags & SKIP_BACKFACE) and base.direct.iRay.isEntryBackfacing():
|
||||
## elif (skipFlags & DG.SKIP_BACKFACE) and base.direct.iRay.isEntryBackfacing():
|
||||
## # Skip, if backfacing poly
|
||||
## pass
|
||||
elif (skipFlags & SKIP_CAMERA) and \
|
||||
elif (skipFlags & DG.SKIP_CAMERA) and \
|
||||
(base.camera in geom.getAncestors()):
|
||||
# Skip if parented to a camera.
|
||||
continue
|
||||
# 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):
|
||||
# Skip if in unpickable list
|
||||
continue
|
||||
|
|
@ -500,7 +522,7 @@ class DirectManipulationControl(DirectObject):
|
|||
selectedList = base.direct.selected.getSelectedAsList()
|
||||
# See if any of the selected are completely uneditable
|
||||
editTypes = self.getEditTypes(selectedList)
|
||||
if (editTypes & EDIT_TYPE_UNEDITABLE) == EDIT_TYPE_UNEDITABLE:
|
||||
if (editTypes & DG.EDIT_TYPE_UNEDITABLE) == DG.EDIT_TYPE_UNEDITABLE:
|
||||
return
|
||||
self.currEditTypes = editTypes
|
||||
if selectedList:
|
||||
|
|
@ -568,13 +590,13 @@ class DirectManipulationControl(DirectObject):
|
|||
if self.constraint:
|
||||
type = self.constraint[2:]
|
||||
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)
|
||||
elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
elif type == 'disc' and not self.currEditTypes & DG.EDIT_TYPE_UNMOVABLE:
|
||||
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)
|
||||
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:
|
||||
self.fScaling3D = 1
|
||||
self.scale3D(state)
|
||||
|
|
@ -582,7 +604,7 @@ class DirectManipulationControl(DirectObject):
|
|||
self.fScaling1D = 1
|
||||
self.scale1D(state)
|
||||
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':
|
||||
# [gjeon] non-uniform scaling
|
||||
self.fScaling1D = 1
|
||||
|
|
@ -592,11 +614,11 @@ class DirectManipulationControl(DirectObject):
|
|||
self.fScaling3D = 1
|
||||
self.scale3D(state)
|
||||
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)
|
||||
elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
elif type == 'disc' and not self.currEditTypes & DG.EDIT_TYPE_UNMOVABLE:
|
||||
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)
|
||||
# No widget interaction, determine free manip mode
|
||||
elif self.fFreeManip and not self.useSeparateScaleHandles:
|
||||
|
|
@ -610,17 +632,17 @@ class DirectManipulationControl(DirectObject):
|
|||
self.fScaling1D = 0
|
||||
self.fScaling3D = 0
|
||||
# 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.scale3D(state)
|
||||
# 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
|
||||
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
|
||||
self.rotate2D(state)
|
||||
elif not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
elif not self.currEditTypes & DG.EDIT_TYPE_UNMOVABLE:
|
||||
# Mouse started in central region, xlate
|
||||
# Mode depends on shift key
|
||||
if base.direct.fShift or base.direct.fControl:
|
||||
|
|
@ -805,11 +827,11 @@ class DirectManipulationControl(DirectObject):
|
|||
widgetDir.normalize()
|
||||
# Convert specified widget axis to view space
|
||||
if axis == 'x':
|
||||
widgetAxis = Vec3(mWidget2Cam.xformVec(X_AXIS))
|
||||
widgetAxis = Vec3(mWidget2Cam.xformVec(DG.X_AXIS))
|
||||
elif axis == 'y':
|
||||
widgetAxis = Vec3(mWidget2Cam.xformVec(Y_AXIS))
|
||||
widgetAxis = Vec3(mWidget2Cam.xformVec(DG.Y_AXIS))
|
||||
elif axis == 'z':
|
||||
widgetAxis = Vec3(mWidget2Cam.xformVec(Z_AXIS))
|
||||
widgetAxis = Vec3(mWidget2Cam.xformVec(DG.Z_AXIS))
|
||||
widgetAxis.normalize()
|
||||
if type == 'top?':
|
||||
# Check sign of angle between two vectors
|
||||
|
|
@ -868,7 +890,7 @@ class DirectManipulationControl(DirectObject):
|
|||
moveDir.assign(moveDir * -1)
|
||||
moveDir.normalize()
|
||||
else:
|
||||
moveDir = Vec3(Y_AXIS)
|
||||
moveDir = Vec3(DG.Y_AXIS)
|
||||
# Move selected objects
|
||||
dr = base.direct.dr
|
||||
# Scale move dir
|
||||
|
|
@ -1034,8 +1056,8 @@ class DirectManipulationControl(DirectObject):
|
|||
self.initScale *
|
||||
(self.objectHandles.getWidgetIntersectPt(
|
||||
self.manipRef, 'y').length() /
|
||||
self.initScaleMag)
|
||||
)
|
||||
self.initScaleMag)
|
||||
)
|
||||
base.direct.widget.setScale(currScale)
|
||||
|
||||
## Utility functions ##
|
||||
|
|
@ -1043,7 +1065,7 @@ class DirectManipulationControl(DirectObject):
|
|||
""" Move selected object to intersection point of cursor on scene """
|
||||
# Check for intersection
|
||||
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
|
||||
if entry is not None and base.direct.selected.last is not None:
|
||||
# Record undo point
|
||||
|
|
@ -1060,6 +1082,7 @@ class DirectManipulationControl(DirectObject):
|
|||
messenger.send('DIRECT_manipulateObjectCleanup',
|
||||
[base.direct.selected.getSelectedAsList()])
|
||||
|
||||
|
||||
class ObjectHandles(NodePath, DirectObject):
|
||||
def __init__(self, name='objectHandles'):
|
||||
# Initialize the superclass
|
||||
|
|
@ -1642,32 +1665,32 @@ class ObjectHandles(NodePath, DirectObject):
|
|||
# by comparing lineDir with plane normals. The plane with the
|
||||
# largest dotProduct is most "normal"
|
||||
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(
|
||||
planeIntersect(lineOrigin, lineDir, ORIGIN, Y_AXIS))
|
||||
planeIntersect(lineOrigin, lineDir, DG.ORIGIN, DG.Y_AXIS))
|
||||
else:
|
||||
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
|
||||
self.hitPt.setY(0)
|
||||
self.hitPt.setZ(0)
|
||||
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(
|
||||
planeIntersect(lineOrigin, lineDir, ORIGIN, X_AXIS))
|
||||
planeIntersect(lineOrigin, lineDir, DG.ORIGIN, DG.X_AXIS))
|
||||
else:
|
||||
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
|
||||
self.hitPt.setX(0)
|
||||
self.hitPt.setZ(0)
|
||||
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(
|
||||
planeIntersect(lineOrigin, lineDir, ORIGIN, X_AXIS))
|
||||
planeIntersect(lineOrigin, lineDir, DG.ORIGIN, DG.X_AXIS))
|
||||
else:
|
||||
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
|
||||
self.hitPt.setX(0)
|
||||
self.hitPt.setY(0)
|
||||
|
|
@ -1722,16 +1745,17 @@ class ObjectHandles(NodePath, DirectObject):
|
|||
# Find the hit point
|
||||
if plane == 'x':
|
||||
self.hitPt.assign(planeIntersect(
|
||||
lineOrigin, lineDir, ORIGIN, X_AXIS))
|
||||
lineOrigin, lineDir, DG.ORIGIN, DG.X_AXIS))
|
||||
elif plane == 'y':
|
||||
self.hitPt.assign(planeIntersect(
|
||||
lineOrigin, lineDir, ORIGIN, Y_AXIS))
|
||||
lineOrigin, lineDir, DG.ORIGIN, DG.Y_AXIS))
|
||||
elif plane == 'z':
|
||||
self.hitPt.assign(planeIntersect(
|
||||
lineOrigin, lineDir, ORIGIN, Z_AXIS))
|
||||
lineOrigin, lineDir, DG.ORIGIN, DG.Z_AXIS))
|
||||
|
||||
return self.hitPt
|
||||
|
||||
|
||||
def drawBox(lines, center, sideLength):
|
||||
l = sideLength * 0.5
|
||||
lines.moveTo(center[0] + l, center[1] + l, center[2] + l)
|
||||
|
|
|
|||
|
|
@ -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.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_CENTER = 1
|
||||
|
||||
# MRM: To do: handle broken node paths in selected and deselected dicts
|
||||
|
||||
|
||||
class DirectNodePath(NodePath):
|
||||
# A node path augmented with info, bounding box, and utility methods
|
||||
def __init__(self, nodePath, bboxColor=None):
|
||||
|
|
@ -47,6 +67,7 @@ class DirectNodePath(NodePath):
|
|||
def getMax(self):
|
||||
return self.bbox.getMax()
|
||||
|
||||
|
||||
class SelectedNodePaths(DirectObject):
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
|
@ -427,7 +448,7 @@ class DirectBoundingBox:
|
|||
'Max:\t\t%s\n' % self.vecAsString(self.max) +
|
||||
'Center:\t\t%s\n' % self.vecAsString(self.center) +
|
||||
'Radius:\t\t%.2f' % self.radius
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class SelectionQueue(CollisionHandlerQueue):
|
||||
|
|
@ -439,7 +460,7 @@ class SelectionQueue(CollisionHandlerQueue):
|
|||
# Current index and entry in collision queue
|
||||
self.index = -1
|
||||
self.entry = None
|
||||
self.skipFlags = SKIP_NONE
|
||||
self.skipFlags = DG.SKIP_NONE
|
||||
# Create a collision node path attached to the given NP
|
||||
self.collisionNodePath = NodePath(CollisionNode("collisionNP"))
|
||||
self.setParentNP(parentNP)
|
||||
|
|
@ -454,7 +475,7 @@ class SelectionQueue(CollisionHandlerQueue):
|
|||
# Let the traverser know about the collision node and the queue
|
||||
self.ct.addCollider(self.collisionNodePath, self)
|
||||
# List of objects that can't be selected
|
||||
self.unpickable = UNPICKABLE
|
||||
self.unpickable = DG.UNPICKABLE
|
||||
# Derived class must add Collider to complete initialization
|
||||
|
||||
def setParentNP(self, parentNP):
|
||||
|
|
@ -548,10 +569,10 @@ class SelectionQueue(CollisionHandlerQueue):
|
|||
v.normalize()
|
||||
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)
|
||||
|
||||
def findCollisionEntry(self, skipFlags = SKIP_NONE, startIndex = 0):
|
||||
def findCollisionEntry(self, skipFlags = DG.SKIP_NONE, startIndex = 0):
|
||||
# Init self.index and self.entry
|
||||
self.setCurrentIndex(-1)
|
||||
self.setCurrentEntry(None)
|
||||
|
|
@ -559,29 +580,29 @@ class SelectionQueue(CollisionHandlerQueue):
|
|||
for i in range(startIndex, self.getNumEntries()):
|
||||
entry = self.getEntry(i)
|
||||
nodePath = entry.getIntoNodePath()
|
||||
if (skipFlags & SKIP_HIDDEN) and nodePath.isHidden():
|
||||
if (skipFlags & DG.SKIP_HIDDEN) and nodePath.isHidden():
|
||||
# Skip if hidden node
|
||||
pass
|
||||
elif (skipFlags & SKIP_BACKFACE) and self.isEntryBackfacing(entry):
|
||||
elif (skipFlags & DG.SKIP_BACKFACE) and self.isEntryBackfacing(entry):
|
||||
# Skip, if backfacing poly
|
||||
pass
|
||||
elif (skipFlags & SKIP_CAMERA) and \
|
||||
elif (skipFlags & DG.SKIP_CAMERA) and \
|
||||
(base.camera in nodePath.getAncestors()):
|
||||
# Skip if parented to a camera.
|
||||
pass
|
||||
# Can pick unpickable, use the first visible node
|
||||
elif (skipFlags & SKIP_UNPICKABLE) and\
|
||||
elif (skipFlags & DG.SKIP_UNPICKABLE) and \
|
||||
(nodePath.getName() in self.unpickable):
|
||||
# Skip if in unpickable list
|
||||
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
|
||||
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
|
||||
pass
|
||||
else:
|
||||
|
|
@ -590,6 +611,7 @@ class SelectionQueue(CollisionHandlerQueue):
|
|||
break
|
||||
return self.getCurrentEntry()
|
||||
|
||||
|
||||
class SelectionRay(SelectionQueue):
|
||||
def __init__(self, parentNP = None):
|
||||
if parentNP is None:
|
||||
|
|
@ -623,7 +645,7 @@ class SelectionRay(SelectionQueue):
|
|||
|
||||
def pickBitMask(self, bitMask = BitMask32.allOff(),
|
||||
targetNodePath = None,
|
||||
skipFlags = SKIP_ALL):
|
||||
skipFlags = DG.SKIP_ALL):
|
||||
if targetNodePath is None:
|
||||
targetNodePath = render
|
||||
self.collideWithBitMask(bitMask)
|
||||
|
|
@ -631,7 +653,7 @@ class SelectionRay(SelectionQueue):
|
|||
# Determine collision entry
|
||||
return self.findCollisionEntry(skipFlags)
|
||||
|
||||
def pickGeom(self, targetNodePath = None, skipFlags = SKIP_ALL,
|
||||
def pickGeom(self, targetNodePath = None, skipFlags = DG.SKIP_ALL,
|
||||
xy = None):
|
||||
if targetNodePath is None:
|
||||
targetNodePath = render
|
||||
|
|
@ -640,7 +662,7 @@ class SelectionRay(SelectionQueue):
|
|||
# Determine collision entry
|
||||
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:
|
||||
targetNodePath = render
|
||||
self.collideWithWidget()
|
||||
|
|
@ -657,7 +679,7 @@ class SelectionRay(SelectionQueue):
|
|||
|
||||
def pickGeom3D(self, targetNodePath = None,
|
||||
origin = Point3(0), dir = Vec3(0, 0, -1),
|
||||
skipFlags = SKIP_HIDDEN | SKIP_CAMERA):
|
||||
skipFlags = DG.SKIP_HIDDEN | DG.SKIP_CAMERA):
|
||||
if targetNodePath is None:
|
||||
targetNodePath = render
|
||||
self.collideWithGeom()
|
||||
|
|
@ -668,7 +690,7 @@ class SelectionRay(SelectionQueue):
|
|||
def pickBitMask3D(self, bitMask = BitMask32.allOff(),
|
||||
targetNodePath = None,
|
||||
origin = Point3(0), dir = Vec3(0, 0, -1),
|
||||
skipFlags = SKIP_ALL):
|
||||
skipFlags = DG.SKIP_ALL):
|
||||
if targetNodePath is None:
|
||||
targetNodePath = render
|
||||
self.collideWithBitMask(bitMask)
|
||||
|
|
@ -698,7 +720,7 @@ class SelectionSegment(SelectionQueue):
|
|||
self.numColliders += 1
|
||||
|
||||
def pickGeom(self, targetNodePath = None, endPointList = [],
|
||||
skipFlags = SKIP_HIDDEN | SKIP_CAMERA):
|
||||
skipFlags = DG.SKIP_HIDDEN | DG.SKIP_CAMERA):
|
||||
if targetNodePath is None:
|
||||
targetNodePath = render
|
||||
self.collideWithGeom()
|
||||
|
|
@ -713,7 +735,7 @@ class SelectionSegment(SelectionQueue):
|
|||
|
||||
def pickBitMask(self, bitMask = BitMask32.allOff(),
|
||||
targetNodePath = None, endPointList = [],
|
||||
skipFlags = SKIP_HIDDEN | SKIP_CAMERA):
|
||||
skipFlags = DG.SKIP_HIDDEN | DG.SKIP_CAMERA):
|
||||
if targetNodePath is None:
|
||||
targetNodePath = render
|
||||
self.collideWithBitMask(bitMask)
|
||||
|
|
@ -781,7 +803,7 @@ class SelectionSphere(SelectionQueue):
|
|||
return self.findCollisionEntry(skipFlags)
|
||||
|
||||
def pickGeom(self, targetNodePath = None,
|
||||
skipFlags = SKIP_HIDDEN | SKIP_CAMERA):
|
||||
skipFlags = DG.SKIP_HIDDEN | DG.SKIP_CAMERA):
|
||||
if targetNodePath is None:
|
||||
targetNodePath = render
|
||||
self.collideWithGeom()
|
||||
|
|
@ -789,7 +811,7 @@ class SelectionSphere(SelectionQueue):
|
|||
|
||||
def pickBitMask(self, bitMask = BitMask32.allOff(),
|
||||
targetNodePath = None,
|
||||
skipFlags = SKIP_HIDDEN | SKIP_CAMERA):
|
||||
skipFlags = DG.SKIP_HIDDEN | DG.SKIP_CAMERA):
|
||||
if targetNodePath is None:
|
||||
targetNodePath = render
|
||||
self.collideWithBitMask(bitMask)
|
||||
|
|
|
|||
|
|
@ -1,26 +1,41 @@
|
|||
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.BulletinBoardGlobal import bulletinBoard as bboard
|
||||
from direct.task import Task
|
||||
|
||||
from .DirectGlobals import DIRECT_NO_MOD
|
||||
from . import DirectGlobals as DG
|
||||
from .DirectCameraControl import DirectCameraControl
|
||||
from .DirectManipulation import DirectManipulationControl
|
||||
from .DirectSelection import SelectionRay, COA_ORIGIN, SelectedNodePaths
|
||||
from .DirectGrid import DirectGrid
|
||||
#from DirectGeometry import *
|
||||
from .DirectLights import DirectLights
|
||||
from direct.cluster.ClusterClient import createClusterClient, DummyClusterClient
|
||||
from direct.cluster.ClusterServer import ClusterServer
|
||||
## from direct.tkpanels import Placer
|
||||
## from direct.tkwidgets import Slider
|
||||
## from direct.tkwidgets import SceneGraphExplorer
|
||||
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):
|
||||
|
||||
|
|
@ -117,7 +132,6 @@ class DirectSession(DirectObject):
|
|||
for i in range(len(fastrak))[1:]:
|
||||
self.fastrak.append(DirectFastrak.DirectFastrak(fastrak[0] + ':' + fastrak[i]))
|
||||
|
||||
|
||||
self.fControl = 0
|
||||
self.fAlt = 0
|
||||
self.fShift = 0
|
||||
|
|
@ -179,7 +193,7 @@ class DirectSession(DirectObject):
|
|||
['DIRECT-doWrtReparent', self.doWrtReparent],
|
||||
['DIRECT-doReparent', self.doReparent],
|
||||
['DIRECT-doSelect', self.doSelect],
|
||||
]
|
||||
]
|
||||
|
||||
if base.wantTk:
|
||||
from direct.tkpanels import Placer
|
||||
|
|
@ -248,7 +262,7 @@ class DirectSession(DirectObject):
|
|||
'shift-[': ('DIRECT-Undo', 'DIRECT-Undo'),
|
||||
']': ('DIRECT-Redo', 'DIRECT-Redo'),
|
||||
'shift-]': ('DIRECT-Redo', 'DIRECT-Redo'),
|
||||
}
|
||||
}
|
||||
|
||||
self.hotKeyMap = {
|
||||
'c': ('Center Camera', 'DIRECT-centerCamIn'),
|
||||
|
|
@ -276,14 +290,14 @@ class DirectSession(DirectObject):
|
|||
'shift-a': ('Toggle Vis all', 'DIRECT-toggleVisAll'),
|
||||
'w': ('Toggle Wireframe', 'DIRECT-toggleWireframe'),
|
||||
'control-z': ('Undo', 'LE-Undo'),
|
||||
'shift-z' : ('Redo', 'LE-Redo'),
|
||||
'shift-z': ('Redo', 'LE-Redo'),
|
||||
'control-d': ('Duplicate', 'LE-Duplicate'),
|
||||
'control-l': ('Make Live', 'LE-MakeLive'),
|
||||
'control-n': ('New Scene', 'LE-NewScene'),
|
||||
'control-s': ('Save Scene', 'LE-SaveScene'),
|
||||
'control-o': ('Open Scene', 'LE-OpenScene'),
|
||||
'control-q': ('Quit', 'LE-Quit'),
|
||||
}
|
||||
}
|
||||
|
||||
self.speicalKeyMap = {
|
||||
'enter': 'DIRECT-enter',
|
||||
|
|
@ -303,14 +317,16 @@ class DirectSession(DirectObject):
|
|||
self.clusterMode = ConfigVariableString("cluster-mode", '').value
|
||||
|
||||
if self.clusterMode == 'client':
|
||||
from direct.cluster.ClusterClient import createClusterClient
|
||||
self.cluster = createClusterClient()
|
||||
elif self.clusterMode == 'server':
|
||||
from direct.cluster.ClusterServer import ClusterServer
|
||||
self.cluster = ClusterServer(base.camera, base.cam)
|
||||
else:
|
||||
from direct.cluster.ClusterClient import DummyClusterClient
|
||||
self.cluster = DummyClusterClient()
|
||||
__builtins__['cluster'] = self.cluster
|
||||
|
||||
|
||||
def addPassThroughKey(self,key):
|
||||
|
||||
self.passThroughKeys.append(key)
|
||||
|
|
@ -541,7 +557,7 @@ class DirectSession(DirectObject):
|
|||
base.mouseWatcher = winCtrl.mouseWatcher
|
||||
base.mouseWatcherNode = winCtrl.mouseWatcher.node()
|
||||
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))]
|
||||
|
||||
input = input[8:] # get rid of camera prefix
|
||||
|
|
@ -590,8 +606,8 @@ class DirectSession(DirectObject):
|
|||
self.fControl = 1
|
||||
# [gjeon] to update control key information while mouse1 is pressed
|
||||
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])
|
||||
elif input == 'control-up':
|
||||
self.fControl = 0
|
||||
|
|
@ -601,16 +617,16 @@ class DirectSession(DirectObject):
|
|||
self.fAlt = 1
|
||||
# [gjeon] to update alt key information while mouse1 is pressed
|
||||
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])
|
||||
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])
|
||||
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])
|
||||
elif input == 'alt-up':
|
||||
self.fAlt = 0
|
||||
|
|
@ -637,24 +653,24 @@ class DirectSession(DirectObject):
|
|||
self.select(self.selected.last)
|
||||
|
||||
def getModifiers(self, input, base):
|
||||
modifiers = DIRECT_NO_MOD
|
||||
modifiers = DG.DIRECT_NO_MOD
|
||||
modifierString = input[: input.find(base)]
|
||||
if modifierString.find('shift') != -1:
|
||||
modifiers |= DIRECT_SHIFT_MOD
|
||||
modifiers |= DG.DIRECT_SHIFT_MOD
|
||||
if modifierString.find('control') != -1:
|
||||
modifiers |= DIRECT_CONTROL_MOD
|
||||
modifiers |= DG.DIRECT_CONTROL_MOD
|
||||
if modifierString.find('alt') != -1:
|
||||
modifiers |= DIRECT_ALT_MOD
|
||||
modifiers |= DG.DIRECT_ALT_MOD
|
||||
return modifiers
|
||||
|
||||
def gotShift(self, modifiers):
|
||||
return modifiers & DIRECT_SHIFT_MOD
|
||||
return modifiers & DG.DIRECT_SHIFT_MOD
|
||||
|
||||
def gotControl(self, modifiers):
|
||||
return modifiers & DIRECT_CONTROL_MOD
|
||||
return modifiers & DG.DIRECT_CONTROL_MOD
|
||||
|
||||
def gotAlt(self, modifiers):
|
||||
return modifiers & DIRECT_ALT_MOD
|
||||
return modifiers & DG.DIRECT_ALT_MOD
|
||||
|
||||
def setFScaleWidgetByCam(self, flag):
|
||||
self.fScaleWidgetByCam = flag
|
||||
|
|
@ -708,7 +724,7 @@ class DirectSession(DirectObject):
|
|||
else:
|
||||
self.widget.showWidget()
|
||||
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()
|
||||
else:
|
||||
self.manipulationControl.enableWidgetMove()
|
||||
|
|
@ -831,7 +847,7 @@ class DirectSession(DirectObject):
|
|||
# Temporarily set node path color
|
||||
nodePath.setColor(flashColor)
|
||||
# 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
|
||||
self.flashDummy,
|
||||
'flashNodePath',)
|
||||
|
|
@ -859,6 +875,7 @@ class DirectSession(DirectObject):
|
|||
# If nothing specified, try selected node path
|
||||
nodePath = self.selected.last
|
||||
base.direct.select(nodePath)
|
||||
|
||||
def fitTask(state, self = self):
|
||||
self.cameraControl.fitOnWidget()
|
||||
return Task.done
|
||||
|
|
@ -1203,12 +1220,13 @@ class DisplayRegionContext(DirectObject):
|
|||
self.near,
|
||||
(self.nearHeight*0.5) * self.mouseY)
|
||||
|
||||
|
||||
class DisplayRegionList(DirectObject):
|
||||
def __init__(self):
|
||||
self.displayRegionList = []
|
||||
i = 0
|
||||
# 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
|
||||
drc = DisplayRegionContext(base.cam)
|
||||
self.displayRegionList.append(drc)
|
||||
|
|
@ -1224,10 +1242,9 @@ class DisplayRegionList(DirectObject):
|
|||
# a display region for each real display region, and then
|
||||
# keep track of which are currently active (e.g. use a flag)
|
||||
# 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)
|
||||
self.displayRegionList.append(drc)
|
||||
|
||||
|
|
@ -1272,7 +1289,7 @@ class DisplayRegionList(DirectObject):
|
|||
for dr in self.displayRegionList:
|
||||
dr.setVfov(fov)
|
||||
|
||||
def mouseUpdate(self, modifiers = DIRECT_NO_MOD):
|
||||
def mouseUpdate(self, modifiers = DG.DIRECT_NO_MOD):
|
||||
for dr in self.displayRegionList:
|
||||
dr.mouseUpdate()
|
||||
#base.direct.dr = self.getCurrentDr()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
from .DirectGlobals import *
|
||||
from panda3d.core import VBase4
|
||||
from direct.task.Task import Task
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ ChunkSize = 100
|
|||
FilePattern = 'largeBlob.%s'
|
||||
|
||||
def getLargeBlobPath():
|
||||
from panda3d.core import ConfigVariableString, ConfigFlags
|
||||
|
||||
# this folder needs to be accessible by everyone that is going to level edit
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,8 +1,20 @@
|
|||
from direct.showbase.DirectObject import DirectObject
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
from direct.directtools.DirectGeometry import *
|
||||
from direct.directtools.DirectUtil import CLAMP
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
|
||||
from panda3d.core import NodePath, LineSegs, ClockObject
|
||||
from panda3d.core import (
|
||||
PCTHPR,
|
||||
PCTNONE,
|
||||
PCTT,
|
||||
PCTXYZ,
|
||||
ClockObject,
|
||||
LineSegs,
|
||||
NodePath,
|
||||
ParametricCurve,
|
||||
Point3,
|
||||
Vec3,
|
||||
)
|
||||
|
||||
|
||||
class Mopath(DirectObject):
|
||||
|
|
@ -11,7 +23,7 @@ class Mopath(DirectObject):
|
|||
|
||||
def __init__(self, name = None, fluid = 1, objectToLoad = None, upVectorNodePath = None, reverseUpVector = False):
|
||||
if name is None:
|
||||
name = 'mopath%d' % self.nameIndex
|
||||
name = f'mopath{self.nameIndex}'
|
||||
self.nameIndex = self.nameIndex + 1
|
||||
self.name = name
|
||||
self.fluid = fluid
|
||||
|
|
@ -26,12 +38,12 @@ class Mopath(DirectObject):
|
|||
self.upVectorNodePath = upVectorNodePath
|
||||
self.reverseUpVector = reverseUpVector
|
||||
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:
|
||||
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):
|
||||
return self.maxT * self.timeScale
|
||||
|
|
@ -49,7 +61,7 @@ class Mopath(DirectObject):
|
|||
self.reset()
|
||||
|
||||
self.__extractCurves(nodePath)
|
||||
if self.tNurbsCurve != []:
|
||||
if self.tNurbsCurve:
|
||||
self.maxT = self.tNurbsCurve[-1].getMaxT()
|
||||
elif self.xyzNurbsCurve is not None:
|
||||
self.maxT = self.xyzNurbsCurve.getMaxT()
|
||||
|
|
@ -58,7 +70,6 @@ class Mopath(DirectObject):
|
|||
else:
|
||||
print('Mopath: no valid curves in nodePath: %s' % nodePath)
|
||||
|
||||
|
||||
def reset(self):
|
||||
self.maxT = 0.0
|
||||
self.loop = 0
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
"""
|
||||
|
||||
__all__ = ["verify"]
|
||||
|
||||
from panda3d.core import ConfigVariableBool
|
||||
|
||||
# Set to true to load pdb on failure.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import imp
|
|||
import platform
|
||||
import struct
|
||||
import io
|
||||
import distutils.sysconfig as sysconf
|
||||
import sysconfig
|
||||
import zipfile
|
||||
import importlib
|
||||
import warnings
|
||||
|
|
@ -22,7 +22,7 @@ try:
|
|||
except ImportError:
|
||||
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
|
||||
# debug build, and we have to build the module with debug options.
|
||||
|
|
@ -83,10 +83,13 @@ defaultHiddenImports = {
|
|||
'plyer': ['plyer.platforms'],
|
||||
'scipy.linalg': ['scipy.linalg.cython_blas', 'scipy.linalg.cython_lapack'],
|
||||
'scipy.sparse.csgraph': ['scipy.sparse.csgraph._validation'],
|
||||
'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.special._ufuncs': ['scipy.special._ufuncs_cxx'],
|
||||
'scipy.stats._stats': ['scipy.special.cython_special'],
|
||||
'setuptools.monkey': ['setuptools.msvc'],
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -139,6 +142,11 @@ def updatecache(filename, module_globals=None):
|
|||
def lazycache(filename, module_globals):
|
||||
pass
|
||||
""",
|
||||
|
||||
# Used by setuptools to redirect distutils to setuptools' vendored copy.
|
||||
# This causes problems because it makes assumptions about __file__, so we
|
||||
# simply implement the logic ourselves.
|
||||
'_distutils_hack.override': '',
|
||||
}
|
||||
|
||||
# These are missing modules that we've reported already this session.
|
||||
|
|
@ -168,8 +176,8 @@ class CompilationEnvironment:
|
|||
|
||||
# Paths to Python stuff.
|
||||
self.Python = None
|
||||
self.PythonIPath = sysconf.get_python_inc()
|
||||
self.PythonVersion = sysconf.get_config_var("LDVERSION") or sysconf.get_python_version()
|
||||
self.PythonIPath = sysconfig.get_path('include')
|
||||
self.PythonVersion = sysconfig.get_config_var("LDVERSION") or sysconfig.get_python_version()
|
||||
|
||||
# The VC directory of Microsoft Visual Studio (if relevant)
|
||||
self.MSVC = None
|
||||
|
|
@ -273,32 +281,32 @@ class CompilationEnvironment:
|
|||
|
||||
def compileExe(self, filename, basename, extraLink=[]):
|
||||
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')
|
||||
if os.system(compile) != 0:
|
||||
raise Exception('failed to compile %s.' % basename)
|
||||
|
||||
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)
|
||||
sys.stderr.write(link + '\n')
|
||||
if os.system(link) != 0:
|
||||
|
|
@ -306,38 +314,39 @@ class CompilationEnvironment:
|
|||
|
||||
def compileDll(self, filename, basename, extraLink=[]):
|
||||
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')
|
||||
if os.system(compile) != 0:
|
||||
raise Exception('failed to compile %s.' % basename)
|
||||
|
||||
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)
|
||||
sys.stderr.write(link + '\n')
|
||||
if os.system(link) != 0:
|
||||
raise Exception('failed to link %s.' % basename)
|
||||
|
||||
|
||||
# The code from frozenmain.c in the Python source repository.
|
||||
frozenMainCode = """
|
||||
/* Python interpreter main program for frozen scripts */
|
||||
|
|
@ -361,6 +370,8 @@ extern PyAPI_FUNC(int) PyImport_ExtendInittab(struct _inittab *newtab);
|
|||
|
||||
/* Main program */
|
||||
|
||||
EXTRA_INIT_FUNC_DECLS
|
||||
|
||||
int
|
||||
Py_FrozenMain(int argc, char **argv)
|
||||
{
|
||||
|
|
@ -440,6 +451,8 @@ Py_FrozenMain(int argc, char **argv)
|
|||
PySys_SetArgv(argc, argv);
|
||||
#endif
|
||||
|
||||
EXTRA_INIT_FUNC_CALLS
|
||||
|
||||
n = PyImport_ImportFrozenModule("__main__");
|
||||
if (n == 0)
|
||||
Py_FatalError("__main__ not frozen");
|
||||
|
|
@ -673,7 +686,7 @@ okMissing = [
|
|||
'direct.extensions_native.extensions_darwin', '_manylinux',
|
||||
'collections.Iterable', 'collections.Mapping', 'collections.MutableMapping',
|
||||
'collections.Sequence', 'numpy_distutils', '_winapi',
|
||||
]
|
||||
]
|
||||
|
||||
# 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
|
||||
|
|
@ -720,6 +733,7 @@ lc_indices_to_slide = {
|
|||
LC_DATA_IN_CODE: [2],
|
||||
}
|
||||
|
||||
|
||||
class Freezer:
|
||||
class ModuleDef:
|
||||
def __init__(self, moduleName, filename = None,
|
||||
|
|
@ -829,6 +843,12 @@ class Freezer:
|
|||
# modules.
|
||||
self.extras = []
|
||||
|
||||
# This is a list of init functions that must be called after
|
||||
# Py_Initialize(), but before importing __main__. This is a
|
||||
# tuple of (return type, name). They should use C calling
|
||||
# convention.
|
||||
self.extraInitFuncs = []
|
||||
|
||||
# Set this to true if extension modules should be linked in to
|
||||
# the resulting executable.
|
||||
self.linkExtensionModules = False
|
||||
|
|
@ -1139,7 +1159,7 @@ class Freezer:
|
|||
if mdef.implicit and '.' in newName:
|
||||
# For implicit modules, check if the parent is excluded.
|
||||
parentName, baseName = newName.rsplit('.', 1)
|
||||
if parentName in excludeDict :
|
||||
if parentName in excludeDict:
|
||||
mdef = excludeDict[parentName]
|
||||
|
||||
if mdef.exclude:
|
||||
|
|
@ -1180,7 +1200,7 @@ class Freezer:
|
|||
self.__loadModule(mdef)
|
||||
# Since it successfully loaded, it's no longer a guess.
|
||||
mdef.guess = False
|
||||
except:
|
||||
except Exception:
|
||||
# Something went wrong, guess it's not an importable
|
||||
# module.
|
||||
pass
|
||||
|
|
@ -1197,13 +1217,16 @@ class Freezer:
|
|||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
self.__loadModule(self.ModuleDef(modname, implicit = True))
|
||||
try:
|
||||
self.__loadModule(self.ModuleDef(modname, implicit = True))
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Special case for sysconfig, which depends on a platform-specific
|
||||
# sysconfigdata module on POSIX systems.
|
||||
missing = []
|
||||
if 'sysconfig' in self.mf.modules and \
|
||||
('linux' in self.platform or 'mac' in self.platform):
|
||||
('linux' in self.platform or 'mac' in self.platform or 'emscripten' in self.platform):
|
||||
modname = '_sysconfigdata'
|
||||
if sys.version_info >= (3, 6):
|
||||
modname += '_'
|
||||
|
|
@ -1215,10 +1238,16 @@ class Freezer:
|
|||
modname += '_linux_' + arch + '-linux-gnu'
|
||||
elif 'mac' in self.platform:
|
||||
modname += '_darwin_darwin'
|
||||
elif 'emscripten' in self.platform:
|
||||
if '_' in self.platform:
|
||||
arch = self.platform.split('_', 1)[1]
|
||||
else:
|
||||
arch = 'wasm32'
|
||||
modname += '_emscripten_' + arch + '-emscripten'
|
||||
|
||||
try:
|
||||
self.__loadModule(self.ModuleDef(modname, implicit=True))
|
||||
except:
|
||||
except Exception:
|
||||
missing.append(modname)
|
||||
|
||||
# Now, any new modules we found get added to the export list.
|
||||
|
|
@ -1594,7 +1623,7 @@ class Freezer:
|
|||
text = programFile % {
|
||||
'moduleDefs': '\n'.join(moduleDefs),
|
||||
'moduleList': '\n'.join(moduleList),
|
||||
}
|
||||
}
|
||||
|
||||
if self.linkExtensionModules and self.extras:
|
||||
# Should we link in extension modules? If so, we write out a new
|
||||
|
|
@ -1692,14 +1721,26 @@ class Freezer:
|
|||
|
||||
if compileToExe:
|
||||
code = self.frozenMainCode
|
||||
|
||||
decls = ''
|
||||
calls = ''
|
||||
for func in self.extraInitFuncs:
|
||||
if isinstance(func, str):
|
||||
func = ('void', func)
|
||||
decls += f'extern {func[0]} {func[1]}();\n'
|
||||
calls += f' {func[1]}();\n';
|
||||
|
||||
code = code.replace('EXTRA_INIT_FUNC_DECLS', decls)
|
||||
code = code.replace('EXTRA_INIT_FUNC_CALLS', calls)
|
||||
|
||||
if self.platform.startswith('win'):
|
||||
code += self.frozenDllMainCode
|
||||
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'):
|
||||
target = basename + '.exe'
|
||||
else:
|
||||
|
|
@ -1714,10 +1755,10 @@ class Freezer:
|
|||
target = basename + '.so'
|
||||
|
||||
initCode = dllInitCode % {
|
||||
'moduleName' : os.path.basename(basename),
|
||||
'dllexport' : dllexport,
|
||||
'dllimport' : dllimport,
|
||||
}
|
||||
'moduleName': os.path.basename(basename),
|
||||
'dllexport': dllexport,
|
||||
'dllimport': dllimport,
|
||||
}
|
||||
compileFunc = self.cenv.compileDll
|
||||
|
||||
self.writeCode(filename, initCode=initCode)
|
||||
|
|
@ -2333,17 +2374,8 @@ class Freezer:
|
|||
return blob_offset
|
||||
|
||||
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):
|
||||
size = len(code)
|
||||
|
|
@ -2355,7 +2387,6 @@ class Freezer:
|
|||
def makeForbiddenModuleListEntry(self, moduleName):
|
||||
return ' {"%s", NULL, 0},' % (moduleName)
|
||||
|
||||
|
||||
def __writingModule(self, moduleName):
|
||||
""" Returns true if we are outputting the named module in this
|
||||
pass, false if we have already output in a previous pass, or
|
||||
|
|
@ -2384,6 +2415,8 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
|
|||
:param debug: an integer indicating the level of verbosity
|
||||
"""
|
||||
|
||||
self.builtin_module_names = kw.pop('builtin_module_names', sys.builtin_module_names)
|
||||
|
||||
self.suffixes = kw.pop('suffixes', imp.get_suffixes())
|
||||
self.optimize = kw.pop('optimize', -1)
|
||||
|
||||
|
|
@ -2708,11 +2741,12 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
|
|||
if fullname in overrideModules:
|
||||
return (None, '', ('.py', 'r', imp.PY_SOURCE))
|
||||
|
||||
# It's built into the interpreter.
|
||||
if fullname in self.builtin_module_names:
|
||||
return (None, None, ('', '', imp.C_BUILTIN))
|
||||
|
||||
# If no search path is given, look for a built-in module.
|
||||
if path is None:
|
||||
if name in sys.builtin_module_names:
|
||||
return (None, None, ('', '', imp.C_BUILTIN))
|
||||
|
||||
path = self.path
|
||||
|
||||
if fullname == 'distutils' and hasattr(sys, 'real_prefix'):
|
||||
|
|
@ -2726,6 +2760,22 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
|
|||
except ImportError:
|
||||
pass
|
||||
|
||||
elif (fullname == 'distutils' and 'setuptools' in self.modules and
|
||||
'_distutils_hack.override' in self.modules):
|
||||
# Redirect to setuptools' vendored copy.
|
||||
setuptools = self.modules['setuptools']
|
||||
return self.find_module('_distutils', setuptools.__path__, parent=setuptools)
|
||||
|
||||
elif parent is not None and parent.__name__ in ('setuptools.extern', 'pkg_resources.extern'):
|
||||
# Look for vendored versions of these libraries.
|
||||
root = self.modules[parent.__name__.split('.', 1)[0]]
|
||||
try:
|
||||
fp, fn, stuff = self.find_module('_vendor', root.__path__, parent=root)
|
||||
vendor = self.load_module(root.__name__ + '._vendor', fp, fn, stuff)
|
||||
return self.find_module(name, vendor.__path__, parent=vendor)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Look for the module on the search path.
|
||||
ns_dirs = []
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
import xml.etree.ElementTree as ET
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ on how to use these commands.
|
|||
|
||||
import os
|
||||
import plistlib
|
||||
import pkg_resources
|
||||
import sys
|
||||
import subprocess
|
||||
import zipfile
|
||||
|
|
@ -58,6 +57,7 @@ def _register_python_loaders():
|
|||
|
||||
registry = p3d.LoaderFileTypeRegistry.getGlobalPtr()
|
||||
|
||||
import pkg_resources
|
||||
for entry_point in pkg_resources.iter_entry_points('panda3d.loaders'):
|
||||
registry.register_deferred_type(entry_point)
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ PACKAGE_LIB_DIRS = {
|
|||
'PyQt5': [('PyQt5/Qt5/bin', 'PyQt5_Qt5')],
|
||||
}
|
||||
|
||||
SITE_PY = u"""
|
||||
SITE_PY = """
|
||||
import sys
|
||||
from _frozen_importlib import _imp, FrozenImporter
|
||||
|
||||
|
|
@ -592,7 +592,7 @@ class build_apps(setuptools.Command):
|
|||
|
||||
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:
|
||||
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
|
||||
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:]
|
||||
basename = '.'.join(parts)
|
||||
|
||||
|
|
@ -1494,7 +1494,8 @@ class build_apps(setuptools.Command):
|
|||
for idx in string_tables.keys():
|
||||
elf.seek(shoff + idx * 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)
|
||||
string_tables[idx] = elf.read(size)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from direct.directnotify.DirectNotifyGlobal import *
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from panda3d.core import PNMImage, Filename, PNMFileTypeRegistry, StringStream
|
||||
import struct
|
||||
|
||||
|
|
@ -114,9 +114,6 @@ class Icon:
|
|||
for x in range(size):
|
||||
pixel = image2.get_pixel(x, size - y - 1)
|
||||
index = colors.index(pixel)
|
||||
if index >= 256:
|
||||
# Find closest pixel instead.
|
||||
index = closest_indices[index - 256]
|
||||
fp.write(struct.pack('<B', index))
|
||||
fp.write(rowalign)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ def create_aab(command, basename, build_dir):
|
|||
bundle.add_subfile('base/manifest/AndroidManifest.xml', p3d.StringStream(axml.dumps()), 9)
|
||||
|
||||
# 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.
|
||||
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
|
||||
# must request it on the command-line.
|
||||
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(
|
||||
p3d.Filename.from_os_specific(command.signing_certificate),
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ def _unpack_zstring(mem, offs=0):
|
|||
c = mem[offs]
|
||||
return str
|
||||
|
||||
|
||||
def _unpack_wstring(mem, offs=0):
|
||||
"Read a UCS-2 string from memory."
|
||||
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]))
|
||||
return name
|
||||
|
||||
|
||||
def _padded(n, boundary):
|
||||
align = n % boundary
|
||||
if align:
|
||||
|
|
@ -250,11 +252,11 @@ class VersionInfoResource(object):
|
|||
self.struct_version = dwords[1]
|
||||
if len(dwords) > 3:
|
||||
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))
|
||||
if len(dwords) > 5:
|
||||
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))
|
||||
if len(dwords) > 7:
|
||||
self.file_flags_mask = dwords[6]
|
||||
|
|
@ -302,7 +304,7 @@ class VersionInfoResource(object):
|
|||
# It contains a value.
|
||||
if type:
|
||||
# It's a wchar array value.
|
||||
value = u""
|
||||
value = ""
|
||||
c, = unpack('<H', data[offset:offset+2])
|
||||
offset += 2
|
||||
while c:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
from direct.directnotify import DirectNotifyGlobal
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
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
|
||||
|
||||
ASYNC_REQUEST_DEFAULT_TIMEOUT_IN_SECONDS = 8.0
|
||||
|
|
@ -266,4 +267,4 @@ def cleanupAsyncRequests():
|
|||
"""
|
||||
for asyncRequest in AsyncRequest._asyncRequests:
|
||||
asyncRequest.delete()
|
||||
assert AsyncRequest._asyncRequests == {}
|
||||
assert not AsyncRequest._asyncRequests
|
||||
|
|
|
|||
|
|
@ -3,7 +3,19 @@
|
|||
from .ClientRepositoryBase import ClientRepositoryBase
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
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 .PyDatagramIterator import PyDatagramIterator
|
||||
from panda3d.core import UniqueIdAllocator, Notify, ClockObject
|
||||
|
|
|
|||
|
|
@ -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.TaskManagerGlobal import taskMgr
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
|
|
@ -7,11 +12,10 @@ from direct.distributed.CRDataCache import CRDataCache
|
|||
from direct.distributed.ConnectionRepository import ConnectionRepository
|
||||
from direct.showbase.PythonUtil import safeRepr, itype, makeList
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
from .MsgTypes import *
|
||||
from .MsgTypes import CLIENT_ENTER_OBJECT_REQUIRED_OTHER, MsgId2Names
|
||||
from . import CRCache
|
||||
from . import ParentMgr
|
||||
from . import RelatedObjectMgr
|
||||
from .ClockDelta import *
|
||||
import time
|
||||
|
||||
|
||||
|
|
@ -106,7 +110,7 @@ class ClientRepositoryBase(ConnectionRepository):
|
|||
## self.flush()
|
||||
|
||||
def specialName(self, label):
|
||||
name = ("SpecialName %s %s" % (self.specialNameNumber, label))
|
||||
name = f"SpecialName {self.specialNameNumber} {label}"
|
||||
self.specialNameNumber += 1
|
||||
return name
|
||||
|
||||
|
|
@ -118,7 +122,7 @@ class ClientRepositoryBase(ConnectionRepository):
|
|||
|
||||
def _getMsgName(self, msgId):
|
||||
# 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):
|
||||
self.context+=1
|
||||
|
|
@ -157,7 +161,7 @@ class ClientRepositoryBase(ConnectionRepository):
|
|||
# Look up the dclass
|
||||
assert parentId == self.GameGlobalsId or parentId in self.doId2do
|
||||
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()
|
||||
# Create a new distributed object, and put it in the dictionary
|
||||
distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
|
||||
|
|
@ -358,7 +362,6 @@ class ClientRepositoryBase(ConnectionRepository):
|
|||
# updateRequiredOtherFields calls announceGenerate
|
||||
return distObj
|
||||
|
||||
|
||||
def disableDoId(self, doId, ownerView=False):
|
||||
table, cache = self.getTables(ownerView)
|
||||
# Make sure the object exists
|
||||
|
|
@ -442,7 +445,6 @@ class ClientRepositoryBase(ConnectionRepository):
|
|||
# This object has been fully generated. It's OK to update.
|
||||
self.__doUpdate(doId, di, ovUpdated)
|
||||
|
||||
|
||||
def __doUpdate(self, doId, di, ovUpdated):
|
||||
# Find the DO
|
||||
do = self.doId2do.get(doId)
|
||||
|
|
@ -463,13 +465,12 @@ class ClientRepositoryBase(ConnectionRepository):
|
|||
if handle:
|
||||
dclass = self.dclassesByName[handle.dclassName]
|
||||
dclass.receiveUpdate(handle, di)
|
||||
|
||||
else:
|
||||
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(
|
||||
"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):
|
||||
ovObj = self.doId2ownerView.get(doId)
|
||||
|
|
@ -488,7 +489,7 @@ class ClientRepositoryBase(ConnectionRepository):
|
|||
self.bootedText = di.getString()
|
||||
|
||||
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:
|
||||
self.bootedIndex = None
|
||||
self.bootedText = None
|
||||
|
|
@ -536,7 +537,6 @@ class ClientRepositoryBase(ConnectionRepository):
|
|||
doDict[doId] = do
|
||||
return doDict
|
||||
|
||||
|
||||
def considerHeartbeat(self):
|
||||
"""Send a heartbeat message if we haven't sent one recently."""
|
||||
if not self.heartbeatStarted:
|
||||
|
|
@ -566,7 +566,7 @@ class ClientRepositoryBase(ConnectionRepository):
|
|||
|
||||
def waitForNextHeartBeat(self):
|
||||
taskMgr.doMethodLater(self.heartbeatInterval, self.sendHeartbeatTask,
|
||||
"heartBeat", taskChain = 'net')
|
||||
"heartBeat", taskChain='net')
|
||||
|
||||
def replaceMethod(self, oldMethod, newFunction):
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -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.TaskManagerGlobal import taskMgr
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
|
|
@ -13,6 +13,7 @@ import gc
|
|||
|
||||
__all__ = ["ConnectionRepository", "GCTrigger"]
|
||||
|
||||
|
||||
class ConnectionRepository(
|
||||
DoInterestManager, DoCollectionManager, CConnectionRepository):
|
||||
"""
|
||||
|
|
@ -233,7 +234,7 @@ class ConnectionRepository(
|
|||
distObj.parentId = 0
|
||||
distObj.zoneId = 0
|
||||
# updateRequiredFields calls announceGenerate
|
||||
return distObj
|
||||
return distObj
|
||||
|
||||
def readDCFile(self, dcFileNames = None):
|
||||
"""
|
||||
|
|
@ -382,7 +383,7 @@ class ConnectionRepository(
|
|||
# in the DC file.
|
||||
for i in range(dcFile.getNumClasses()):
|
||||
dclass = dcFile.getClass(i)
|
||||
if (dclass.getName()+ownerDcSuffix) in ownerImportSymbols:
|
||||
if dclass.getName() + ownerDcSuffix in ownerImportSymbols:
|
||||
number = dclass.getNumber()
|
||||
className = dclass.getName() + ownerDcSuffix
|
||||
|
||||
|
|
@ -466,7 +467,7 @@ class ConnectionRepository(
|
|||
hasProxy = 0
|
||||
if self.checkHttp():
|
||||
proxies = self.http.getProxiesForUrl(serverList[0])
|
||||
hasProxy = (proxies != 'DIRECT')
|
||||
hasProxy = proxies != 'DIRECT'
|
||||
|
||||
if hasProxy:
|
||||
self.notify.info("Connecting to gameserver via proxy list: %s" % (proxies))
|
||||
|
|
@ -589,7 +590,7 @@ class ConnectionRepository(
|
|||
if self.http is None:
|
||||
try:
|
||||
self.http = HTTPClient()
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return self.http
|
||||
|
|
@ -667,6 +668,7 @@ class ConnectionRepository(
|
|||
def uniqueName(self, idString):
|
||||
return "%s-%s" % (idString, self.uniqueId)
|
||||
|
||||
|
||||
class GCTrigger:
|
||||
# used to trigger garbage collection
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -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.interval.IntervalGlobal import *
|
||||
from direct.interval.IntervalGlobal import LerpScaleInterval, Sequence
|
||||
from direct.distributed.DistributedObject import DistributedObject
|
||||
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
|
||||
_camera_id = ConfigVariableInt('camera-id', -1)
|
||||
_aware_of_cameras = ConfigVariableInt('aware-of-cameras', 0)
|
||||
|
|
|
|||
|
|
@ -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.distributed.DistributedNode import DistributedNode
|
||||
from direct.task import Task
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from direct.gui import DirectGuiGlobals
|
||||
from direct.showbase.EventGroup import EventGroup
|
||||
from direct.showbase.PythonUtil import report
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
from direct.distributed.GridParent import GridParent
|
||||
|
||||
if __debug__:
|
||||
# For grid drawing
|
||||
from direct.directtools.DirectGeometry import *
|
||||
from direct.directtools.DirectGeometry import LineNodePath
|
||||
from direct.showbase.PythonUtil import randFloat
|
||||
|
||||
from .CartesianGridBase import CartesianGridBase
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
|
||||
from panda3d.core import *
|
||||
from panda3d.direct import *
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from direct.task import Task
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""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.directnotify.DirectNotifyGlobal import directNotify
|
||||
from direct.distributed.DistributedObjectBase import DistributedObjectBase
|
||||
|
|
@ -25,7 +24,7 @@ ESNum2Str = {
|
|||
ESDisabled: 'ESDisabled',
|
||||
ESGenerating: 'ESGenerating',
|
||||
ESGenerated: 'ESGenerated',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DistributedObject(DistributedObjectBase):
|
||||
|
|
@ -241,7 +240,6 @@ class DistributedObject(DistributedObjectBase):
|
|||
"""
|
||||
assert self.notify.debug('announceGenerate(): %s' % (self.doId))
|
||||
|
||||
|
||||
def _deactivateDO(self):
|
||||
# after this is called, the object is no longer an active DistributedObject
|
||||
# and it may be placed in the cache
|
||||
|
|
@ -330,9 +328,9 @@ class DistributedObject(DistributedObjectBase):
|
|||
"""
|
||||
return self.doId
|
||||
|
||||
|
||||
#This message was moved out of announce generate
|
||||
#to avoid ordering issues.
|
||||
|
||||
def postGenerateMessage(self):
|
||||
if self.activeState != ESGenerated:
|
||||
self.activeState = ESGenerated
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ from direct.directnotify.DirectNotifyGlobal import directNotify
|
|||
from direct.distributed.DistributedObjectBase import DistributedObjectBase
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
from direct.showbase import PythonUtil
|
||||
from panda3d.core import *
|
||||
from panda3d.direct import *
|
||||
#from PyDatagram import PyDatagram
|
||||
#from PyDatagramIterator import PyDatagramIterator
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
"""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 DistributedSmoothNodeBase
|
||||
from direct.task.Task import cont
|
||||
|
|
@ -35,6 +36,8 @@ PredictionLag = ConfigVariableDouble("smooth-prediction-lag", 0.0)
|
|||
|
||||
GlobalSmoothing = 0
|
||||
GlobalPrediction = 0
|
||||
|
||||
|
||||
def globalActivateSmoothing(smoothing, prediction):
|
||||
""" Globally activates or deactivates smoothing and prediction on
|
||||
all DistributedSmoothNodes currently in existence, or yet to be
|
||||
|
|
@ -47,6 +50,7 @@ def globalActivateSmoothing(smoothing, prediction):
|
|||
for obj in base.cr.getAllOfType(DistributedSmoothNode):
|
||||
obj.activateSmoothing(smoothing, prediction)
|
||||
|
||||
|
||||
# For historical reasons, we temporarily define
|
||||
# DistributedSmoothNode.activateSmoothing() to be the global function.
|
||||
# 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):
|
||||
self._smoothWrtReparents = flag
|
||||
|
||||
def getSmoothWrtReparents(self):
|
||||
return self._smoothWrtReparents
|
||||
|
||||
|
|
@ -212,42 +217,50 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
|
|||
def setSmStop(self, timestamp=None):
|
||||
self.setComponentTLive(timestamp)
|
||||
self.stopped = True
|
||||
|
||||
def setSmH(self, h, timestamp=None):
|
||||
self._checkResume(timestamp)
|
||||
self.setComponentH(h)
|
||||
self.setComponentTLive(timestamp)
|
||||
|
||||
def setSmZ(self, z, timestamp=None):
|
||||
self._checkResume(timestamp)
|
||||
self.setComponentZ(z)
|
||||
self.setComponentTLive(timestamp)
|
||||
|
||||
def setSmXY(self, x, y, timestamp=None):
|
||||
self._checkResume(timestamp)
|
||||
self.setComponentX(x)
|
||||
self.setComponentY(y)
|
||||
self.setComponentTLive(timestamp)
|
||||
|
||||
def setSmXZ(self, x, z, timestamp=None):
|
||||
self._checkResume(timestamp)
|
||||
self.setComponentX(x)
|
||||
self.setComponentZ(z)
|
||||
self.setComponentTLive(timestamp)
|
||||
|
||||
def setSmPos(self, x, y, z, timestamp=None):
|
||||
self._checkResume(timestamp)
|
||||
self.setComponentX(x)
|
||||
self.setComponentY(y)
|
||||
self.setComponentZ(z)
|
||||
self.setComponentTLive(timestamp)
|
||||
|
||||
def setSmHpr(self, h, p, r, timestamp=None):
|
||||
self._checkResume(timestamp)
|
||||
self.setComponentH(h)
|
||||
self.setComponentP(p)
|
||||
self.setComponentR(r)
|
||||
self.setComponentTLive(timestamp)
|
||||
|
||||
def setSmXYH(self, x, y, h, timestamp):
|
||||
self._checkResume(timestamp)
|
||||
self.setComponentX(x)
|
||||
self.setComponentY(y)
|
||||
self.setComponentH(h)
|
||||
self.setComponentTLive(timestamp)
|
||||
|
||||
def setSmXYZH(self, x, y, z, h, timestamp=None):
|
||||
self._checkResume(timestamp)
|
||||
self.setComponentX(x)
|
||||
|
|
@ -255,6 +268,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
|
|||
self.setComponentZ(z)
|
||||
self.setComponentH(h)
|
||||
self.setComponentTLive(timestamp)
|
||||
|
||||
def setSmPosHpr(self, x, y, z, h, p, r, timestamp=None):
|
||||
self._checkResume(timestamp)
|
||||
self.setComponentX(x)
|
||||
|
|
@ -284,26 +298,33 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
|
|||
@report(types = ['args'], dConfigParam = 'smoothnode')
|
||||
def setComponentX(self, x):
|
||||
self.smoother.setX(x)
|
||||
|
||||
@report(types = ['args'], dConfigParam = 'smoothnode')
|
||||
def setComponentY(self, y):
|
||||
self.smoother.setY(y)
|
||||
|
||||
@report(types = ['args'], dConfigParam = 'smoothnode')
|
||||
def setComponentZ(self, z):
|
||||
self.smoother.setZ(z)
|
||||
|
||||
@report(types = ['args'], dConfigParam = 'smoothnode')
|
||||
def setComponentH(self, h):
|
||||
self.smoother.setH(h)
|
||||
|
||||
@report(types = ['args'], dConfigParam = 'smoothnode')
|
||||
def setComponentP(self, p):
|
||||
self.smoother.setP(p)
|
||||
|
||||
@report(types = ['args'], dConfigParam = 'smoothnode')
|
||||
def setComponentR(self, r):
|
||||
self.smoother.setR(r)
|
||||
|
||||
@report(types = ['args'], dConfigParam = 'smoothnode')
|
||||
def setComponentL(self, l):
|
||||
if l != self.zoneId:
|
||||
# only perform set location if location is different
|
||||
self.setLocation(self.parentId,l)
|
||||
|
||||
@report(types = ['args'], dConfigParam = 'smoothnode')
|
||||
def setComponentT(self, timestamp):
|
||||
# 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.
|
||||
def getComponentL(self):
|
||||
return self.zoneId
|
||||
|
||||
def getComponentX(self):
|
||||
return self.getX()
|
||||
|
||||
def getComponentY(self):
|
||||
return self.getY()
|
||||
|
||||
def getComponentZ(self):
|
||||
return self.getZ()
|
||||
|
||||
def getComponentH(self):
|
||||
return self.getH()
|
||||
|
||||
def getComponentP(self):
|
||||
return self.getP()
|
||||
|
||||
def getComponentR(self):
|
||||
return self.getR()
|
||||
|
||||
def getComponentT(self):
|
||||
return 0
|
||||
|
||||
|
|
@ -408,7 +436,6 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
|
|||
#printStack()
|
||||
self.smoother.clearPositions(1)
|
||||
|
||||
|
||||
@report(types = ['args'], dConfigParam = 'smoothnode')
|
||||
def wrtReparentTo(self, parent):
|
||||
# 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))
|
||||
elif hasattr(other, "d_returnResync") and \
|
||||
hasattr(self.cr, 'localAvatarDoId'):
|
||||
globalClock = ClockObject.getGlobalClock()
|
||||
realTime = globalClock.getRealTime()
|
||||
serverTime = realTime - globalClockDelta.getDelta()
|
||||
assert self.notify.info(
|
||||
|
|
@ -474,7 +502,6 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
|
|||
serverTime,
|
||||
globalClockDelta.getUncertainty())
|
||||
|
||||
|
||||
def d_returnResync(self, avId, timestampB, serverTime, uncertainty):
|
||||
serverTimeSec = math.floor(serverTime)
|
||||
serverTimeUSec = (serverTime - serverTimeSec) * 10000.0
|
||||
|
|
@ -482,7 +509,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode,
|
|||
avId, timestampB, serverTimeSec, serverTimeUSec, uncertainty])
|
||||
|
||||
def returnResync(self, avId, timestampB, serverTimeSec, serverTimeUSec,
|
||||
uncertainty):
|
||||
uncertainty):
|
||||
"""
|
||||
A reply sent by a client whom we recently sent suggestResync
|
||||
to, this reports the client's new delta information so we can
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"""DistributedSmoothNodeBase module: contains the DistributedSmoothNodeBase class"""
|
||||
|
||||
from .ClockDelta import *
|
||||
from .ClockDelta import globalClockDelta
|
||||
from direct.task import Task
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from direct.showbase.PythonUtil import randFloat
|
||||
|
|
@ -13,8 +13,10 @@ class DummyTaskClass:
|
|||
def setDelay(self, blah):
|
||||
pass
|
||||
|
||||
|
||||
DummyTask = DummyTaskClass()
|
||||
|
||||
|
||||
class DistributedSmoothNodeBase:
|
||||
"""common base class for DistributedSmoothNode and DistributedSmoothNodeAI
|
||||
"""
|
||||
|
|
@ -43,6 +45,7 @@ class DistributedSmoothNodeBase:
|
|||
def b_clearSmoothing(self):
|
||||
self.d_clearSmoothing()
|
||||
self.clearSmoothing()
|
||||
|
||||
def d_clearSmoothing(self):
|
||||
self.sendUpdate("clearSmoothing", [0])
|
||||
|
||||
|
|
@ -85,7 +88,7 @@ class DistributedSmoothNodeBase:
|
|||
BT.FULL: self.cnode.broadcastPosHprFull,
|
||||
BT.XYH: self.cnode.broadcastPosHprXyh,
|
||||
BT.XY: self.cnode.broadcastPosHprXy,
|
||||
}
|
||||
}
|
||||
# this comment is here so it will show up in a grep for 'def d_broadcastPosHpr'
|
||||
self.d_broadcastPosHpr = broadcastFuncs[self.broadcastType]
|
||||
|
||||
|
|
|
|||
|
|
@ -7,15 +7,22 @@ zone, remove interest in that zone.
|
|||
p.s. A great deal of this code is just code moved from ClientRepository.py.
|
||||
"""
|
||||
|
||||
from panda3d.core 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.MessengerGlobal import messenger
|
||||
from .PyDatagram import PyDatagram
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
import types
|
||||
from direct.showbase.PythonUtil import report
|
||||
from direct.showbase.PythonUtil import (
|
||||
FrameDelayedCall,
|
||||
ScratchPad,
|
||||
SerialNumGen,
|
||||
report,
|
||||
serialNum,
|
||||
uniqueElements,
|
||||
uniqueName,
|
||||
)
|
||||
|
||||
class InterestState:
|
||||
StateActive = 'Active'
|
||||
|
|
@ -649,6 +656,7 @@ class DoInterestManager(DirectObject.DirectObject):
|
|||
|
||||
if __debug__:
|
||||
import unittest
|
||||
import time
|
||||
|
||||
class AsyncTestCase(unittest.TestCase):
|
||||
def setCompleted(self):
|
||||
|
|
@ -663,7 +671,7 @@ if __debug__:
|
|||
suiteClass = AsyncTestSuite
|
||||
|
||||
class AsyncTextTestRunner(unittest.TextTestRunner):
|
||||
def run(self, testCase):
|
||||
def run(self, test):
|
||||
result = self._makeResult()
|
||||
startTime = time.time()
|
||||
test(result)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from direct.distributed.DistributedSmoothNodeBase import DistributedSmoothNodeBase
|
||||
from direct.distributed.GridParent import GridParent
|
||||
from direct.showbase.PythonUtil import report
|
||||
from direct.showbase.PythonUtil import report, getBase
|
||||
|
||||
|
||||
class GridChild:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from panda3d.core import NodePath
|
||||
|
||||
#
|
||||
# GridParent.py
|
||||
# Any object that can be parented to the ocean grid
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ if ConfigVariableBool('astron-support', True):
|
|||
'CLIENTAGENT_ADD_INTEREST': 1200,
|
||||
'CLIENTAGENT_ADD_INTEREST_MULTIPLE': 1201,
|
||||
'CLIENTAGENT_REMOVE_INTEREST': 1203,
|
||||
}
|
||||
}
|
||||
else:
|
||||
MsgName2Id = {
|
||||
# 2 new params: passwd, char bool 0/1 1 = new account
|
||||
|
|
@ -241,7 +241,7 @@ else:
|
|||
'STATESERVER_OBJECT_CREATE_WITH_REQUIRED_CONTEXT': 2050,
|
||||
'STATESERVER_OBJECT_CREATE_WITH_REQUIR_OTHER_CONTEXT': 2051,
|
||||
'STATESERVER_BOUNCE_MESSAGE': 2086,
|
||||
}
|
||||
}
|
||||
|
||||
# create id->name table for debugging
|
||||
MsgId2Names = invertDictLossless(MsgName2Id)
|
||||
|
|
@ -261,7 +261,7 @@ QUIET_ZONE_IGNORED_LIST = [
|
|||
#CLIENT_CREATE_OBJECT_REQUIRED,
|
||||
#CLIENT_CREATE_OBJECT_REQUIRED_OTHER,
|
||||
|
||||
]
|
||||
]
|
||||
|
||||
# The following is a different set of numbers from above.
|
||||
# These are the sub-message types for CLIENT_LOGIN_2.
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ MsgName2Id = {
|
|||
'OBJECT_SET_ZONE_CMU' : 9010,
|
||||
'CLIENT_HEARTBEAT_CMU' : 9011,
|
||||
'CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU' : 9011,
|
||||
}
|
||||
}
|
||||
|
||||
if ConfigVariableBool('astron-support', True):
|
||||
MsgName2Id['CLIENT_OBJECT_UPDATE_FIELD'] = 120 # Matches MsgTypes.CLIENT_OBJECT_SET_FIELD
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ MESSAGE_TYPES=(
|
|||
|
||||
# This is the reverse look up for the recipient of the
|
||||
# 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 OTPNetMessenger(Messenger):
|
||||
|
|
|
|||
|
|
@ -4,10 +4,30 @@
|
|||
# of the file rather than every time we call the putArg function.
|
||||
|
||||
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
|
||||
|
||||
from direct.distributed.MsgTypes import *
|
||||
from direct.distributed.MsgTypes import CONTROL_CHANNEL
|
||||
|
||||
|
||||
class PyDatagram(Datagram):
|
||||
|
|
@ -28,7 +48,7 @@ class PyDatagram(Datagram):
|
|||
STString: (Datagram.addString, None),
|
||||
STBlob: (Datagram.addBlob, None),
|
||||
STBlob32: (Datagram.addBlob32, None),
|
||||
}
|
||||
}
|
||||
|
||||
addChannel = Datagram.addUint64
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,28 @@
|
|||
# class variable FuncDict and so we can import DCSubatomicType at the top
|
||||
# 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
|
||||
|
||||
|
||||
|
|
@ -26,7 +46,7 @@ class PyDatagramIterator(DatagramIterator):
|
|||
STString: DatagramIterator.getString,
|
||||
STBlob: DatagramIterator.getBlob,
|
||||
STBlob32: DatagramIterator.getBlob32,
|
||||
}
|
||||
}
|
||||
|
||||
getChannel = DatagramIterator.getUint64
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"""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):
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,38 @@
|
|||
"""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.TaskManagerGlobal import taskMgr
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
|
|
|
|||
|
|
@ -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.TaskManagerGlobal import taskMgr
|
||||
from direct.distributed import DistributedObject
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
from direct.distributed.ClockDelta import globalClockDelta
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
|
||||
|
||||
class TimeManager(DistributedObject.DistributedObject):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from direct.distributed.ClockDelta import *
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
from direct.distributed.ClockDelta import globalClockDelta
|
||||
from direct.distributed import DistributedObjectAI
|
||||
|
||||
class TimeManagerAI(DistributedObjectAI.DistributedObjectAI):
|
||||
|
|
|
|||
|
|
@ -61,66 +61,66 @@ del privPostEvent
|
|||
#####################################################################
|
||||
|
||||
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)
|
||||
del popupControls
|
||||
|
|
|
|||
|
|
@ -8,22 +8,22 @@ from .extension_native_helpers import Dtool_funcToMethod
|
|||
|
||||
|
||||
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'):
|
||||
Dtool_funcToMethod(spawnTask, core.HTTPChannel)
|
||||
|
|
@ -31,12 +31,12 @@ del spawnTask
|
|||
#####################################################################
|
||||
|
||||
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'):
|
||||
Dtool_funcToMethod(doTask, core.HTTPChannel)
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ def remove(self):
|
|||
warnings.warn("NodePath.remove() is deprecated. Use remove_node() instead.", DeprecationWarning, stacklevel=2)
|
||||
# Send message in case anyone needs to do something
|
||||
# before node is deleted
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
messenger.send('preRemoveNodePath', [self])
|
||||
# Remove nodePath
|
||||
self.removeNode()
|
||||
|
|
@ -493,7 +494,7 @@ def showCS(self, mask = None):
|
|||
npc = self.findAllMatches('**/+CollisionNode')
|
||||
for p in range(0, npc.getNumPaths()):
|
||||
np = npc[p]
|
||||
if (mask == None or (np.node().getIntoCollideMask() & mask).getWord()):
|
||||
if mask is None or (np.node().getIntoCollideMask() & mask).getWord():
|
||||
np.show()
|
||||
|
||||
Dtool_funcToMethod(showCS, NodePath)
|
||||
|
|
@ -512,7 +513,7 @@ def hideCS(self, mask = None):
|
|||
npc = self.findAllMatches('**/+CollisionNode')
|
||||
for p in range(0, npc.getNumPaths()):
|
||||
np = npc[p]
|
||||
if (mask == None or (np.node().getIntoCollideMask() & mask).getWord()):
|
||||
if mask is None or (np.node().getIntoCollideMask() & mask).getWord():
|
||||
np.hide()
|
||||
|
||||
Dtool_funcToMethod(hideCS, NodePath)
|
||||
|
|
@ -667,40 +668,40 @@ del attachCollisionRay
|
|||
#####################################################################
|
||||
def flattenMultitex(self, stateFrom = None, target = 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)
|
||||
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 win is None:
|
||||
win = base.win
|
||||
|
||||
if stateFrom is None:
|
||||
mr.scan(self)
|
||||
else:
|
||||
mr.scan(self, stateFrom)
|
||||
mr.flatten(win)
|
||||
if stateFrom is None:
|
||||
mr.scan(self)
|
||||
else:
|
||||
mr.scan(self, stateFrom)
|
||||
mr.flatten(win)
|
||||
Dtool_funcToMethod(flattenMultitex, NodePath)
|
||||
del flattenMultitex
|
||||
#####################################################################
|
||||
def getNumDescendants(self):
|
||||
return len(self.findAllMatches('**')) - 1
|
||||
return len(self.findAllMatches('**')) - 1
|
||||
Dtool_funcToMethod(getNumDescendants, NodePath)
|
||||
del getNumDescendants
|
||||
#####################################################################
|
||||
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)
|
||||
del removeNonCollisions
|
||||
#####################################################################
|
||||
|
|
@ -729,130 +730,130 @@ def subdivideCollisions(self, numSolidsInLeaves):
|
|||
colNp.stash()
|
||||
|
||||
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
|
||||
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])
|
||||
# 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:
|
||||
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])
|
||||
if z < midZ:
|
||||
xYzSolids.append(solids[i])
|
||||
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])
|
||||
else:
|
||||
if y < midY:
|
||||
if z < midZ:
|
||||
XyzSolids.append(solids[i])
|
||||
else:
|
||||
XyZSolids.append(solids[i])
|
||||
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
|
||||
|
||||
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(r_subdivideCollisions, NodePath)
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ class CommonFilters:
|
|||
text += "{\n"
|
||||
text += " o_color = tex2D(k_txcolor, %s);\n" % (texcoords["color"])
|
||||
if "CartoonInk" in configuration:
|
||||
text += CARTOON_BODY % {"texcoord" : texcoords["aux"]}
|
||||
text += CARTOON_BODY % {"texcoord": texcoords["aux"]}
|
||||
if "AmbientOcclusion" in configuration:
|
||||
text += " o_color *= tex2D(k_txssao2, %s).r;\n" % (texcoords["ssao2"])
|
||||
if "BlurSharpen" in configuration:
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ from panda3d.core import Camera
|
|||
from panda3d.core import OrthographicLens
|
||||
from panda3d.core import AuxBitplaneAttrib
|
||||
from panda3d.core import LightRampAttrib
|
||||
from direct.directnotify.DirectNotifyGlobal import *
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
|
||||
__all__ = ["FilterManager"]
|
||||
|
|
@ -348,10 +348,10 @@ class FilterManager(DirectObject):
|
|||
|
||||
def resizeBuffers(self):
|
||||
""" 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]
|
||||
(xsize, ysize) = self.getScaledSize(mul, div, align)
|
||||
self.buffers[i].setSize(xsize, ysize)
|
||||
buffer.setSize(xsize, ysize)
|
||||
|
||||
def cleanup(self):
|
||||
""" Restore everything to its original state, deleting any
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ if __debug__:
|
|||
_debugFsms = {}
|
||||
|
||||
def printDebugFsmList():
|
||||
global _debugFsms
|
||||
for k in sorted(_debugFsms.keys()):
|
||||
print("%s %s" % (k, _debugFsms[k]()))
|
||||
__builtins__['debugFsmList'] = printDebugFsmList
|
||||
|
|
@ -83,7 +82,6 @@ class ClassicFSM(DirectObject):
|
|||
# doing this.
|
||||
self.__internalStateInFlux = 0
|
||||
if __debug__:
|
||||
global _debugFsms
|
||||
_debugFsms[name] = weakref.ref(self)
|
||||
|
||||
# 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
|
||||
"""
|
||||
name = self.getName()
|
||||
currentState = self.getCurrentState()
|
||||
if currentState:
|
||||
str = ("ClassicFSM " + self.getName() + ' in state "' +
|
||||
currentState.getName() + '"')
|
||||
str = f'ClassicFSM {name} in state "{currentState.getName()}"'
|
||||
else:
|
||||
str = ("ClassicFSM " + self.getName() + ' not in any state')
|
||||
str = f'ClassicFSM {name} not in any state'
|
||||
return str
|
||||
|
||||
def enterInitialState(self, argList=[]):
|
||||
|
|
@ -152,7 +150,6 @@ class ClassicFSM(DirectObject):
|
|||
def getCurrentState(self):
|
||||
return self.__currentState
|
||||
|
||||
|
||||
# lookup funcs
|
||||
|
||||
def getStateNamed(self, stateName):
|
||||
|
|
@ -317,7 +314,6 @@ class ClassicFSM(DirectObject):
|
|||
ClassicFSM.notify.warning(msg)
|
||||
return 0
|
||||
|
||||
|
||||
def forceTransition(self, aStateName, enterArgList=[], exitArgList=[]):
|
||||
"""
|
||||
force a transition -- for debugging ONLY
|
||||
|
|
@ -357,7 +353,7 @@ class ClassicFSM(DirectObject):
|
|||
self.__currentState.isTransitionDefined(aStateName) or
|
||||
aStateName in [self.__currentState.getName(),
|
||||
self.__finalState.getName()]
|
||||
)
|
||||
)
|
||||
|
||||
if transitionDefined:
|
||||
return self.request(aStateName, enterArgList, exitArgList)
|
||||
|
|
|
|||
|
|
@ -615,9 +615,8 @@ class FSM(DirectObject):
|
|||
try:
|
||||
className = self.__class__.__name__
|
||||
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:
|
||||
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:
|
||||
self.fsmLock.release()
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ class FourState:
|
|||
self.enterState4,
|
||||
self.exitState4,
|
||||
[names[1]]),
|
||||
}
|
||||
}
|
||||
self.fsm = ClassicFSM.ClassicFSM('FourState',
|
||||
list(self.states.values()),
|
||||
# Initial State
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class FourStateAI:
|
|||
self.enterState4,
|
||||
self.exitState4,
|
||||
[names[1]]),
|
||||
}
|
||||
}
|
||||
self.fsm = ClassicFSM.ClassicFSM('FourState',
|
||||
list(self.states.values()),
|
||||
# Initial State
|
||||
|
|
@ -145,6 +145,9 @@ class FourStateAI:
|
|||
assert self.__debugPrint("getState() returning %s"%(self.stateIndex,))
|
||||
return [self.stateIndex]
|
||||
|
||||
def sendUpdate(self, fieldName, args = [], sendToId = None):
|
||||
raise NotImplementedError
|
||||
|
||||
def sendState(self):
|
||||
assert self.__debugPrint("sendState()")
|
||||
self.sendUpdate('setState', self.getState())
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class ClassicStyle(FSM.FSM):
|
|||
'Red': ['Green'],
|
||||
'Yellow': ['Red'],
|
||||
'Green': ['Yellow'],
|
||||
}
|
||||
}
|
||||
|
||||
def enterRed(self):
|
||||
print("enterRed(self, '%s', '%s')" % (self.oldState, self.newState))
|
||||
|
|
|
|||
|
|
@ -251,12 +251,12 @@ class FunctionCall(ReceivesMultipleStateChanges, PushesStateChanges):
|
|||
|
||||
if __debug__:
|
||||
l = []
|
||||
def handler(value, l=l):
|
||||
def handler1(value, l=l):
|
||||
l.append(value)
|
||||
assert l == []
|
||||
assert not l
|
||||
sv = StateVar(0)
|
||||
fc = FunctionCall(handler, sv)
|
||||
assert l == []
|
||||
fc = FunctionCall(handler1, sv)
|
||||
assert not l
|
||||
fc.pushCurrentState()
|
||||
assert l == [0,]
|
||||
sv.set(1)
|
||||
|
|
@ -267,17 +267,17 @@ if __debug__:
|
|||
sv.destroy()
|
||||
del fc
|
||||
del sv
|
||||
del handler
|
||||
del handler1
|
||||
del l
|
||||
|
||||
l = []
|
||||
def handler(value, kDummy=None, kValue=None, l=l):
|
||||
def handler2(value, kDummy=None, kValue=None, l=l):
|
||||
l.append((value, kValue))
|
||||
assert l == []
|
||||
assert not l
|
||||
sv = StateVar(0)
|
||||
ksv = StateVar('a')
|
||||
fc = FunctionCall(handler, sv, kValue=ksv)
|
||||
assert l == []
|
||||
fc = FunctionCall(handler2, sv, kValue=ksv)
|
||||
assert not l
|
||||
fc.pushCurrentState()
|
||||
assert l == [(0,'a',),]
|
||||
sv.set(1)
|
||||
|
|
@ -288,7 +288,7 @@ if __debug__:
|
|||
sv.destroy()
|
||||
del fc
|
||||
del sv
|
||||
del handler
|
||||
del handler2
|
||||
del l
|
||||
|
||||
class EnterExit(StateChangeNode):
|
||||
|
|
@ -323,7 +323,7 @@ if __debug__:
|
|||
sv = StateVar(0)
|
||||
ee = EnterExit(sv, enter, exit)
|
||||
sv.set(0)
|
||||
assert l == []
|
||||
assert not l
|
||||
sv.set(1)
|
||||
assert l == [1,]
|
||||
sv.set(2)
|
||||
|
|
@ -357,7 +357,7 @@ if __debug__:
|
|||
l.append(value)
|
||||
p = Pulse()
|
||||
fc = FunctionCall(handler, p)
|
||||
assert l == []
|
||||
assert not l
|
||||
fc.pushCurrentState()
|
||||
assert l == [False, ]
|
||||
p.sendPulse()
|
||||
|
|
|
|||
|
|
@ -6,15 +6,17 @@ in-depth explanation and an example of how to use this class.
|
|||
|
||||
__all__ = ['DirectButton']
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import Mat4, MouseButton, PGButton
|
||||
from . import DirectGuiGlobals as DGG
|
||||
from .DirectFrame import *
|
||||
from .DirectFrame import DirectFrame
|
||||
|
||||
|
||||
class DirectButton(DirectFrame):
|
||||
"""
|
||||
DirectButton(parent) - Create a DirectGuiWidget which responds
|
||||
to mouse clicks and execute a callback function if defined
|
||||
"""
|
||||
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Inherits from DirectFrame
|
||||
# A Direct Frame can have:
|
||||
|
|
@ -45,7 +47,7 @@ class DirectButton(DirectFrame):
|
|||
# Can only be specified at time of widget contruction
|
||||
# Do the text/graphics appear to move when the button is clicked
|
||||
('pressEffect', 1, DGG.INITOPT),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
@ -10,6 +10,7 @@ class DirectCheckBox(DirectButton):
|
|||
|
||||
Uses an image swap rather than a text change to indicate state.
|
||||
"""
|
||||
|
||||
def __init__(self, parent = None, **kw):
|
||||
|
||||
optiondefs = (
|
||||
|
|
@ -33,7 +34,7 @@ class DirectCheckBox(DirectButton):
|
|||
('uncheckedImage', None, None),
|
||||
('checkedImage', None, None),
|
||||
('isChecked', False, None),
|
||||
)
|
||||
)
|
||||
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
|
@ -42,7 +43,6 @@ class DirectCheckBox(DirectButton):
|
|||
|
||||
self.initialiseoptions(DirectCheckBox)
|
||||
|
||||
|
||||
def commandFunc(self, event):
|
||||
self['isChecked'] = not self['isChecked']
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ in-depth explanation and an example of how to use this class.
|
|||
|
||||
__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):
|
||||
"""
|
||||
|
|
@ -18,6 +19,7 @@ class DirectCheckButton(DirectButton):
|
|||
to mouse clicks by setting a state of on or off and execute a callback
|
||||
function (passing that state through) if defined
|
||||
"""
|
||||
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Inherits from DirectButton
|
||||
# A Direct Frame can have:
|
||||
|
|
@ -42,7 +44,7 @@ class DirectCheckButton(DirectButton):
|
|||
('boxImageScale', 1, None),
|
||||
('boxImageColor', None, None),
|
||||
('boxRelief', 'sunken', None),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
# Initialize superclasses
|
||||
|
|
@ -167,7 +169,6 @@ class DirectCheckButton(DirectButton):
|
|||
|
||||
self.indicator.setPos(newpos[0], newpos[1], newpos[2])
|
||||
|
||||
|
||||
def commandFunc(self, event):
|
||||
self['indicatorValue'] = 1 - self['indicatorValue']
|
||||
if self.colors is not None:
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ __all__ = [
|
|||
'OkCancelDialog', 'YesNoDialog', 'YesNoCancelDialog', 'RetryCancelDialog',
|
||||
]
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import NodePath, Point3, TextNode, VBase3
|
||||
from direct.showbase import ShowBaseGlobal
|
||||
from . import DirectGuiGlobals as DGG
|
||||
from .DirectFrame import *
|
||||
from .DirectButton import *
|
||||
from .DirectFrame import DirectFrame
|
||||
from .DirectButton import DirectButton
|
||||
|
||||
|
||||
def findDialog(uniqueName):
|
||||
|
|
@ -120,7 +120,7 @@ class DirectDialog(DirectFrame):
|
|||
('command', None, None),
|
||||
('extraArgs', [], None),
|
||||
('sortOrder', DGG.NO_FADE_SORT_INDEX, None),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs, dynamicGroups = ("button",))
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ class DirectDialog(DirectFrame):
|
|||
suppressKeys = self['suppressKeys'],
|
||||
frameSize = self['buttonSize'],
|
||||
command = lambda s = self, v = value: s.buttonCommand(v)
|
||||
)
|
||||
)
|
||||
self.buttonList.append(button)
|
||||
|
||||
# Update dialog when everything has been initialised
|
||||
|
|
@ -356,6 +356,7 @@ class DirectDialog(DirectFrame):
|
|||
button.destroy()
|
||||
DirectFrame.destroy(self)
|
||||
|
||||
|
||||
class OkDialog(DirectDialog):
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Inherits from DirectFrame
|
||||
|
|
@ -363,12 +364,13 @@ class OkDialog(DirectDialog):
|
|||
# Define type of DirectGuiWidget
|
||||
('buttonTextList', ['OK'], DGG.INITOPT),
|
||||
('buttonValueList', [DGG.DIALOG_OK], DGG.INITOPT),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
DirectDialog.__init__(self, parent)
|
||||
self.initialiseoptions(OkDialog)
|
||||
|
||||
|
||||
class OkCancelDialog(DirectDialog):
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Inherits from DirectFrame
|
||||
|
|
@ -376,12 +378,13 @@ class OkCancelDialog(DirectDialog):
|
|||
# Define type of DirectGuiWidget
|
||||
('buttonTextList', ['OK','Cancel'], DGG.INITOPT),
|
||||
('buttonValueList', [DGG.DIALOG_OK, DGG.DIALOG_CANCEL], DGG.INITOPT),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
DirectDialog.__init__(self, parent)
|
||||
self.initialiseoptions(OkCancelDialog)
|
||||
|
||||
|
||||
class YesNoDialog(DirectDialog):
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Inherits from DirectFrame
|
||||
|
|
@ -389,12 +392,13 @@ class YesNoDialog(DirectDialog):
|
|||
# Define type of DirectGuiWidget
|
||||
('buttonTextList', ['Yes', 'No'], DGG.INITOPT),
|
||||
('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO], DGG.INITOPT),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
DirectDialog.__init__(self, parent)
|
||||
self.initialiseoptions(YesNoDialog)
|
||||
|
||||
|
||||
class YesNoCancelDialog(DirectDialog):
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Inherits from DirectFrame
|
||||
|
|
@ -403,12 +407,13 @@ class YesNoCancelDialog(DirectDialog):
|
|||
('buttonTextList', ['Yes', 'No', 'Cancel'], DGG.INITOPT),
|
||||
('buttonValueList', [DGG.DIALOG_YES, DGG.DIALOG_NO, DGG.DIALOG_CANCEL],
|
||||
DGG.INITOPT),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
DirectDialog.__init__(self, parent)
|
||||
self.initialiseoptions(YesNoCancelDialog)
|
||||
|
||||
|
||||
class RetryCancelDialog(DirectDialog):
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Inherits from DirectFrame
|
||||
|
|
@ -416,7 +421,7 @@ class RetryCancelDialog(DirectDialog):
|
|||
# Define type of DirectGuiWidget
|
||||
('buttonTextList', ['Retry','Cancel'], DGG.INITOPT),
|
||||
('buttonValueList', [DGG.DIALOG_RETRY, DGG.DIALOG_CANCEL], DGG.INITOPT),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
DirectDialog.__init__(self, parent)
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ explanation and an example of how to use this class.
|
|||
|
||||
__all__ = ['DirectEntry']
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import ConfigVariableBool, PGEntry, Point3, TextNode, Vec3
|
||||
from direct.showbase import ShowBaseGlobal
|
||||
from . import DirectGuiGlobals as DGG
|
||||
from .DirectFrame import *
|
||||
from .DirectFrame import DirectFrame
|
||||
from .OnscreenText import OnscreenText
|
||||
# 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
|
||||
|
||||
# DirectEntry States:
|
||||
|
|
@ -21,6 +21,7 @@ ENTRY_FOCUS_STATE = PGEntry.SFocus # 0
|
|||
ENTRY_NO_FOCUS_STATE = PGEntry.SNoFocus # 1
|
||||
ENTRY_INACTIVE_STATE = PGEntry.SInactive # 2
|
||||
|
||||
|
||||
class DirectEntry(DirectFrame):
|
||||
"""
|
||||
DirectEntry(parent) - Create a DirectGuiWidget which responds
|
||||
|
|
@ -82,7 +83,7 @@ class DirectEntry(DirectFrame):
|
|||
('autoCapitalize', 0, self.autoCapitalizeFunc),
|
||||
('autoCapitalizeAllowPrefixes', DirectEntry.AllowCapNamePrefixes, None),
|
||||
('autoCapitalizeForcePrefixes', DirectEntry.ForceCapNamePrefixes, None),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
||||
|
|
@ -215,15 +216,16 @@ class DirectEntry(DirectFrame):
|
|||
|
||||
def _handleTyping(self, guiEvent):
|
||||
self._autoCapitalize()
|
||||
|
||||
def _handleErasing(self, guiEvent):
|
||||
self._autoCapitalize()
|
||||
|
||||
def _autoCapitalize(self):
|
||||
name = self.guiItem.getWtext()
|
||||
# capitalize each word, allowing for things like McMutton
|
||||
capName = u''
|
||||
capName = ''
|
||||
# track each individual word to detect prefixes like Mc
|
||||
wordSoFar = u''
|
||||
wordSoFar = ''
|
||||
# track whether the previous character was part of a word or not
|
||||
wasNonWordChar = True
|
||||
for i, character in enumerate(name):
|
||||
|
|
@ -232,9 +234,9 @@ class DirectEntry(DirectFrame):
|
|||
# This assumes that string.lower and string.upper will return different
|
||||
# values for all unicode letters.
|
||||
# - 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
|
||||
wordSoFar = u''
|
||||
wordSoFar = ''
|
||||
wasNonWordChar = True
|
||||
else:
|
||||
capitalize = False
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
__all__ = ['DirectEntryScroll']
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import NodePath, OmniBoundingVolume, PGVirtualFrame
|
||||
from . import DirectGuiGlobals as DGG
|
||||
from .DirectScrolledFrame import *
|
||||
from .DirectFrame import *
|
||||
from .DirectEntry import *
|
||||
from .DirectFrame import DirectFrame
|
||||
|
||||
|
||||
class DirectEntryScroll(DirectFrame):
|
||||
def __init__(self, entry, parent = None, **kw):
|
||||
|
|
@ -12,7 +11,7 @@ class DirectEntryScroll(DirectFrame):
|
|||
('pgFunc', PGVirtualFrame, None),
|
||||
('relief', None, None),
|
||||
('clipSize', (-1, 1, -1, 1), self.setClipSize),
|
||||
)
|
||||
)
|
||||
|
||||
self.defineoptions(kw, optiondefs)
|
||||
DirectFrame.__init__(self, parent, **kw)
|
||||
|
|
@ -81,7 +80,6 @@ class DirectEntryScroll(DirectFrame):
|
|||
if abs(distanceToCenter) > (clipExtent * 0.5):
|
||||
self.moveToCenterCursor()
|
||||
|
||||
|
||||
def moveToCenterCursor(self):
|
||||
cursorX = self.entry.guiItem.getCursorX() * self.entry['text_scale'][0]
|
||||
canvasX = self.canvas.getX()
|
||||
|
|
@ -122,7 +120,6 @@ class DirectEntryScroll(DirectFrame):
|
|||
self.entry = None
|
||||
DirectFrame.destroy(self)
|
||||
|
||||
|
||||
def getCanvas(self):
|
||||
return self.canvas
|
||||
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ explanation and an example of how to use this class.
|
|||
|
||||
__all__ = ['DirectFrame']
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import Filename, NodePath, PGItem, Texture
|
||||
from . import DirectGuiGlobals as DGG
|
||||
from .DirectGuiBase import *
|
||||
from .DirectGuiBase import DirectGuiWidget
|
||||
from .OnscreenImage import OnscreenImage
|
||||
from .OnscreenGeom import OnscreenGeom
|
||||
from .OnscreenText import OnscreenText
|
||||
|
|
|
|||
|
|
@ -87,14 +87,21 @@ Code overview:
|
|||
__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.ShowBase import ShowBase
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
from . import DirectGuiGlobals as DGG
|
||||
from .OnscreenText import *
|
||||
from .OnscreenGeom import *
|
||||
from .OnscreenImage import *
|
||||
from direct.directtools.DirectUtil import ROUND_TO
|
||||
from direct.showbase import DirectObject
|
||||
from direct.task import Task
|
||||
|
|
@ -652,9 +659,11 @@ class DirectGuiBase(DirectObject.DirectObject):
|
|||
gEvent = event + self.guiId
|
||||
self.ignore(gEvent)
|
||||
|
||||
|
||||
def toggleGuiGridSnap():
|
||||
DirectGuiWidget.snapToGrid = 1 - DirectGuiWidget.snapToGrid
|
||||
|
||||
|
||||
def setGuiGridSpacing(spacing):
|
||||
DirectGuiWidget.gridSpacing = spacing
|
||||
|
||||
|
|
@ -715,7 +724,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
|
|||
('suppressMouse', 1, DGG.INITOPT),
|
||||
('suppressKeys', 0, DGG.INITOPT),
|
||||
('enableEdit', 1, DGG.INITOPT),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
||||
|
|
@ -822,7 +831,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
|
|||
vMouse2render2d = Point3(event.getMouse()[0], 0, event.getMouse()[1])
|
||||
editVec = Vec3(vWidget2render2d - vMouse2render2d)
|
||||
if base.mouseWatcherNode.getModifierButtons().isDown(
|
||||
KeyboardButton.control()):
|
||||
KeyboardButton.control()):
|
||||
t = taskMgr.add(self.guiScaleTask, 'guiEditTask')
|
||||
t.refPos = vWidget2render2d
|
||||
t.editVecLen = editVec.length()
|
||||
|
|
@ -904,7 +913,6 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
|
|||
self.bounds[2] - bw[1],
|
||||
self.bounds[3] + bw[1])
|
||||
|
||||
|
||||
def getBounds(self, state = 0):
|
||||
self.stateNodePath[state].calcTightBounds(self.ll, self.ur)
|
||||
# Scale bounds to give a pad around graphics
|
||||
|
|
|
|||
|
|
@ -5,7 +5,15 @@ that can be used during widget construction
|
|||
|
||||
__all__ = []
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import (
|
||||
KeyboardButton,
|
||||
MouseButton,
|
||||
PGButton,
|
||||
PGEntry,
|
||||
PGFrameStyle,
|
||||
PGSliderBar,
|
||||
TextNode,
|
||||
)
|
||||
|
||||
defaultFont = None
|
||||
defaultFontFunc = TextNode.getDefaultFont
|
||||
|
|
@ -138,11 +146,9 @@ def setDefaultFontFunc(newFontFunc):
|
|||
defaultFontFunc = newFontFunc
|
||||
|
||||
def getDefaultDialogGeom():
|
||||
global defaultDialogGeom
|
||||
return defaultDialogGeom
|
||||
|
||||
def getDefaultDialogRelief():
|
||||
global defaultDialogRelief
|
||||
return defaultDialogRelief
|
||||
|
||||
def setDefaultDialogGeom(newDialogGeom, relief=None):
|
||||
|
|
|
|||
|
|
@ -4,12 +4,13 @@ __all__ = []
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from panda3d.core import Point3
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from . import DirectGuiGlobals
|
||||
from .DirectGui import *
|
||||
from .DirectGui import DirectButton, DirectDialog, DirectEntry, DirectFrame, YesNoDialog
|
||||
#from whrandom import *
|
||||
from random import *
|
||||
from random import random
|
||||
|
||||
base = ShowBase()
|
||||
|
||||
|
|
|
|||
|
|
@ -6,14 +6,16 @@ explanation and an example of how to use this class.
|
|||
|
||||
__all__ = ['DirectLabel']
|
||||
|
||||
from panda3d.core import *
|
||||
from .DirectFrame import *
|
||||
from panda3d.core import PGItem
|
||||
from .DirectFrame import DirectFrame
|
||||
|
||||
|
||||
class DirectLabel(DirectFrame):
|
||||
"""
|
||||
DirectLabel(parent) - Create a DirectGuiWidget which has multiple
|
||||
states. User explicitly chooses a state to display
|
||||
"""
|
||||
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Inherits from DirectFrame
|
||||
# A Direct Frame can have:
|
||||
|
|
@ -32,7 +34,7 @@ class DirectLabel(DirectFrame):
|
|||
('numStates', 1, None),
|
||||
('state', self.inactiveInitState, None),
|
||||
('activeState', 0, self.setActiveState),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@ in-depth explanation and an example of how to use this class.
|
|||
|
||||
__all__ = ['DirectOptionMenu']
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import OmniBoundingVolume, TextNode, VBase3
|
||||
from direct.showbase import ShowBaseGlobal
|
||||
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):
|
||||
|
|
@ -22,6 +21,7 @@ class DirectOptionMenu(DirectButton):
|
|||
To cancel the popup menu click anywhere on the screen outside of the
|
||||
popup menu. No command is executed in this case.
|
||||
"""
|
||||
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Inherits from DirectButton
|
||||
optiondefs = (
|
||||
|
|
@ -43,7 +43,7 @@ class DirectOptionMenu(DirectButton):
|
|||
('text_align', TextNode.ALeft, None),
|
||||
# Remove press effect because it looks a bit funny
|
||||
('pressEffect', 0, DGG.INITOPT),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
# Initialize superclasses
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@ in-depth explanation and an example of how to use this class.
|
|||
|
||||
__all__ = ['DirectRadioButton']
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import PGFrameStyle, VBase4
|
||||
from . import DirectGuiGlobals as DGG
|
||||
from .DirectButton import *
|
||||
from .DirectLabel import *
|
||||
from .DirectButton import DirectButton
|
||||
from .DirectLabel import DirectLabel
|
||||
|
||||
|
||||
class DirectRadioButton(DirectButton):
|
||||
"""
|
||||
|
|
@ -20,6 +21,7 @@ class DirectRadioButton(DirectButton):
|
|||
to mouse clicks by setting given value to given variable and
|
||||
execute a callback function (passing that state through) if defined
|
||||
"""
|
||||
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Inherits from DirectButton
|
||||
# A Direct Frame can have:
|
||||
|
|
@ -54,7 +56,7 @@ class DirectRadioButton(DirectButton):
|
|||
('boxImageScale', 1.0, None),
|
||||
('boxImageColor', VBase4(1, 1, 1, 1), None),
|
||||
('boxRelief', None, None),
|
||||
)
|
||||
)
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
# Initialize superclasses
|
||||
|
|
@ -194,7 +196,6 @@ class DirectRadioButton(DirectButton):
|
|||
|
||||
self.indicator.setPos(newpos[0], newpos[1], newpos[2])
|
||||
|
||||
|
||||
def commandFunc(self, event):
|
||||
if len(self['value']) == len(self['variable']) != 0:
|
||||
for i in range(len(self['value'])):
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ in-depth explanation and an example of how to use this class.
|
|||
|
||||
__all__ = ['DirectScrollBar']
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import PGSliderBar, Vec3
|
||||
from . import DirectGuiGlobals as DGG
|
||||
from .DirectFrame import *
|
||||
from .DirectButton import *
|
||||
from .DirectFrame import DirectFrame
|
||||
from .DirectButton import DirectButton
|
||||
|
||||
|
||||
class DirectScrollBar(DirectFrame):
|
||||
|
|
@ -17,6 +17,7 @@ class DirectScrollBar(DirectFrame):
|
|||
DirectScrollBar -- a widget which represents a scroll bar the user can
|
||||
use for paging through a large document or panel.
|
||||
"""
|
||||
|
||||
def __init__(self, parent = None, **kw):
|
||||
optiondefs = (
|
||||
# Define type of DirectGuiWidget
|
||||
|
|
@ -35,18 +36,18 @@ class DirectScrollBar(DirectFrame):
|
|||
# Function to be called repeatedly as the bar is scrolled
|
||||
('command', None, None),
|
||||
('extraArgs', [], None),
|
||||
)
|
||||
)
|
||||
|
||||
if kw.get('orientation') in (DGG.VERTICAL, DGG.VERTICAL_INVERTED):
|
||||
# These are the default options for a vertical layout.
|
||||
optiondefs += (
|
||||
('frameSize', (-0.04, 0.04, -0.5, 0.5), None),
|
||||
)
|
||||
)
|
||||
else:
|
||||
# These are the default options for a horizontal layout.
|
||||
optiondefs += (
|
||||
('frameSize', (-0.5, 0.5, -0.04, 0.04), None),
|
||||
)
|
||||
)
|
||||
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ in-depth explanation and an example of how to use this class.
|
|||
|
||||
__all__ = ['DirectScrolledFrame']
|
||||
|
||||
from panda3d.core import *
|
||||
from panda3d.core import NodePath, PGScrollFrame
|
||||
from . import DirectGuiGlobals as DGG
|
||||
from .DirectFrame import *
|
||||
from .DirectScrollBar import *
|
||||
from .DirectFrame import DirectFrame
|
||||
from .DirectScrollBar import DirectScrollBar
|
||||
|
||||
|
||||
class DirectScrolledFrame(DirectFrame):
|
||||
|
|
@ -24,6 +24,7 @@ class DirectScrolledFrame(DirectFrame):
|
|||
0 and explicitly position and hide or show the scroll bars
|
||||
yourself.
|
||||
"""
|
||||
|
||||
def __init__(self, parent = None, **kw):
|
||||
optiondefs = (
|
||||
# Define type of DirectGuiWidget
|
||||
|
|
@ -35,7 +36,7 @@ class DirectScrolledFrame(DirectFrame):
|
|||
('autoHideScrollBars', 1, self.setAutoHideScrollBars),
|
||||
('scrollBarWidth', 0.08, self.setScrollBarWidth),
|
||||
('borderWidth', (0.01, 0.01), self.setBorderWidth),
|
||||
)
|
||||
)
|
||||
|
||||
# Merge keyword options with default options
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue