فهرست منبع

Merge branch 'master' into webgl-port

rdb 5 سال پیش
والد
کامیت
6084366946
100فایلهای تغییر یافته به همراه1630 افزوده شده و 1074 حذف شده
  1. 22 0
      .editorconfig
  2. 25 0
      .github/ISSUE_TEMPLATE/bug.md
  3. 15 0
      .github/ISSUE_TEMPLATE/enhancement.md
  4. 15 0
      .github/PULL_REQUEST_TEMPLATE.md
  5. 16 0
      .github/codecov.yml
  6. 3 32
      .github/workflows/ci.yml
  7. 1 0
      .gitignore
  8. 0 60
      .travis.yml
  9. 1 0
      CMakeLists.txt
  10. 55 0
      CONTRIBUTING.md
  11. 6 6
      README.md
  12. 50 0
      cmake/macros/PerConfigOption.cmake
  13. 7 0
      cmake/templates/METADATA.in
  14. 7 0
      contrib/src/contribbase/contribsymbols.h
  15. 21 21
      contrib/src/rplight/rpLight.I
  16. 0 0
      contrib/src/speedtree/config_speedtree.cxx
  17. 1 1
      contrib/src/speedtree/config_speedtree.h
  18. 0 0
      contrib/src/speedtree/loaderFileTypeSrt.cxx
  19. 1 1
      contrib/src/speedtree/loaderFileTypeSrt.h
  20. 0 0
      contrib/src/speedtree/loaderFileTypeStf.cxx
  21. 1 1
      contrib/src/speedtree/loaderFileTypeStf.h
  22. 0 0
      contrib/src/speedtree/pandaspeedtree_composite1.cxx
  23. 0 0
      contrib/src/speedtree/speedTreeNode.I
  24. 1 1
      contrib/src/speedtree/speedTreeNode.cxx
  25. 1 1
      contrib/src/speedtree/speedTreeNode.h
  26. 0 0
      contrib/src/speedtree/speedtree_api.cxx
  27. 0 0
      contrib/src/speedtree/speedtree_api.h
  28. 0 0
      contrib/src/speedtree/stBasicTerrain.I
  29. 0 0
      contrib/src/speedtree/stBasicTerrain.cxx
  30. 1 1
      contrib/src/speedtree/stBasicTerrain.h
  31. 0 0
      contrib/src/speedtree/stTerrain.I
  32. 0 0
      contrib/src/speedtree/stTerrain.cxx
  33. 1 1
      contrib/src/speedtree/stTerrain.h
  34. 0 0
      contrib/src/speedtree/stTransform.I
  35. 0 0
      contrib/src/speedtree/stTransform.cxx
  36. 1 1
      contrib/src/speedtree/stTransform.h
  37. 0 0
      contrib/src/speedtree/stTree.I
  38. 0 0
      contrib/src/speedtree/stTree.cxx
  39. 1 1
      contrib/src/speedtree/stTree.h
  40. 15 1
      direct/CMakeLists.txt
  41. 5 1
      direct/src/actor/Actor.py
  42. 3 0
      direct/src/actor/__init__.py
  43. 3 3
      direct/src/dcparser/dcClass.cxx
  44. 3 2
      direct/src/dcparser/dcClass.h
  45. 3 0
      direct/src/dcparser/dcLexer.cxx.prebuilt
  46. 3 1
      direct/src/dcparser/dcLexer.lxx
  47. 5 3
      direct/src/dcparser/dcPacker.I
  48. 1 1
      direct/src/dcparser/dcPacker.cxx
  49. 1 3
      direct/src/dcparser/dcPackerCatalog.cxx
  50. 1 3
      direct/src/dcparser/dcPackerInterface.cxx
  51. 3 9
      direct/src/dcparser/dcSwitch.cxx
  52. 2 0
      direct/src/dcparser/dcbase.h
  53. 1 1
      direct/src/directbase/DirectStart.py
  54. 1 0
      direct/src/directscripts/Doxyfile.cxx
  55. 1 1
      direct/src/directtools/DirectManipulation.py
  56. 0 10
      direct/src/directutil/DirectMySQLdb.py
  57. 0 117
      direct/src/directutil/DirectMySQLdbConnection.py
  58. 138 16
      direct/src/dist/FreezeTool.py
  59. 27 13
      direct/src/dist/commands.py
  60. 1 0
      direct/src/distributed/ConnectionRepository.py
  61. 3 2
      direct/src/distributed/ServerRepository.py
  62. 3 0
      direct/src/distributed/__init__.py
  63. 2 5
      direct/src/extensions_native/CInterval_extensions.py
  64. 119 3
      direct/src/filter/CommonFilters.py
  65. 7 1
      direct/src/filter/FilterManager.py
  66. 3 0
      direct/src/filter/__init__.py
  67. 2 19
      direct/src/fsm/State.py
  68. 16 0
      direct/src/gui/DirectGuiGlobals.py
  69. 1 2
      direct/src/interval/FunctionInterval.py
  70. 5 5
      direct/src/showbase/DirectObject.py
  71. 9 9
      direct/src/showbase/Loader.py
  72. 2 3
      direct/src/showbase/Messenger.py
  73. 3 3
      direct/src/showbase/OnScreenDebug.py
  74. 0 1
      direct/src/showbase/ProfileSession.py
  75. 4 3
      direct/src/showbase/PythonUtil.py
  76. 277 141
      direct/src/showbase/ShowBase.py
  77. 10 5
      direct/src/showbase/ShowBaseGlobal.py
  78. 3 0
      direct/src/showbase/__init__.py
  79. 6 3
      direct/src/showutil/TexMemWatcher.py
  80. 2 1
      direct/src/stdpy/__init__.py
  81. 1 3
      direct/src/task/Task.py
  82. 14 8
      direct/src/tkpanels/Inspector.py
  83. 71 0
      doc/ReleaseNotes
  84. 57 63
      dtool/Config.cmake
  85. 7 4
      dtool/LocalSetup.cmake
  86. 2 2
      dtool/Package.cmake
  87. 1 50
      dtool/PandaVersion.cmake
  88. 432 353
      dtool/src/cppparser/cppBison.cxx.prebuilt
  89. 6 2
      dtool/src/cppparser/cppBison.h.prebuilt
  90. 13 37
      dtool/src/cppparser/cppBison.yxx
  91. 47 9
      dtool/src/cppparser/cppExpression.cxx
  92. 3 1
      dtool/src/cppparser/cppExpression.h
  93. 11 1
      dtool/src/cppparser/cppInstance.cxx
  94. 1 1
      dtool/src/cppparser/cppInstanceIdentifier.cxx
  95. 2 2
      dtool/src/cppparser/cppInstanceIdentifier.h
  96. 1 3
      dtool/src/cppparser/cppManifest.cxx
  97. 2 2
      dtool/src/dtoolbase/cmath.I
  98. 6 2
      dtool/src/dtoolbase/deletedChain.h
  99. 6 2
      dtool/src/dtoolbase/memoryBase.h
  100. 0 10
      dtool/src/dtoolbase/pandaVersion.h.in

+ 22 - 0
.editorconfig

@@ -0,0 +1,22 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.{py,pyw}]
+indent_style = space
+indent_size = 4
+
+[*.{h,c,cxx,cpp,I,T}]
+indent_style = space
+indent_size = 2
+
+[{CMakeLists.txt,*.cmake}]
+indent_style = space
+indent_size = 2
+
+[*.bat]
+end_of_line = crlf

+ 25 - 0
.github/ISSUE_TEMPLATE/bug.md

@@ -0,0 +1,25 @@
+---
+name: Bug report
+about: Report a defect
+title:
+labels:
+assignees:
+---
+
+## Description
+<!-- Provide a clear and concise description of the bug: what you expected to
+     happen, and what actually happened instead.  If you have a log file or
+     crash report, please attach those! -->
+
+## Steps to Reproduce
+<!-- The most minimal but complete set of steps to reproduce the bug, with a
+     code snippet that clearly demonstrates the bug.  We must be able to run
+     the code, ie. you must include any required assets. -->
+
+## Environment
+ * Operating system:
+ * System architecture:
+ * Panda3D version: <!-- import panda3d; print(panda3d.__version__) -->
+ * Installation method: (eg. pip, wheel, SDK, built from source)
+ * Python version (if using Python):
+ * Compiler (if using C++):

+ 15 - 0
.github/ISSUE_TEMPLATE/enhancement.md

@@ -0,0 +1,15 @@
+---
+name: Enhancement request
+about: Request new functionality or improvement to existing functionality
+title:
+labels: enhancement
+assignees:
+---
+
+## Description
+<!-- Please clearly describe which change you want to be made. -->
+
+## Use Case
+<!-- Describe why you need this change, how it will help you, including any
+     other imagined scenarios in which it will be useful.  If this request is
+     urgent and you have no alternatives, please state so as well. -->

+ 15 - 0
.github/PULL_REQUEST_TEMPLATE.md

@@ -0,0 +1,15 @@
+## Issue description
+<!-- What is this change intended to accomplish?  What problem does it solve?
+     If this change resolves a GitHub issue, include the issue number. -->
+
+## Solution description
+<!-- Explain here how your PR solves the problem, what approach it takes. -->
+
+## Checklist
+I have done my best to ensure that…
+* [ ] …I have familiarized myself with the CONTRIBUTING.md file
+* [ ] …this change follows the coding style and design patterns of the codebase
+* [ ] …I own the intellectual property rights to this code
+* [ ] …the intent of this change is clearly explained
+* [ ] …existing uses of the Panda3D API are not broken
+* [ ] …the changed code is adequately covered by the test suite, where possible.

+ 16 - 0
.github/codecov.yml

@@ -0,0 +1,16 @@
+coverage:
+  status:
+    project:
+      default:
+        threshold: 0.1
+    patch:
+      default:
+        target: 0%
+codecov:
+  require_ci_to_pass: true
+  notify:
+    after_n_builds: 2
+    wait_for_ci: true
+comment:
+  require_changes: true
+  after_n_builds: 2

+ 3 - 32
.github/workflows/ci.yml

@@ -4,6 +4,7 @@ on: [push, pull_request]
 jobs:
 jobs:
   cmake:
   cmake:
     name: CMake Buildsystem
     name: CMake Buildsystem
+    if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')"
 
 
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
@@ -181,37 +182,6 @@ jobs:
       run: cmake --build . --config ${{ matrix.config }} --parallel 4
       run: cmake --build . --config ${{ matrix.config }} --parallel 4
       # END A
       # END A
 
 
-    - name: Setup Python (Python 3.5)
-      if: contains(matrix.python, 'YES')
-      uses: actions/setup-python@v1
-      with:
-        python-version: 3.5
-    - name: Configure (Python 3.5)
-      if: contains(matrix.python, 'YES')
-      working-directory: build
-      shell: bash
-      run: >
-        cmake -DWANT_PYTHON_VERSION=3.5
-        -DPython_FIND_REGISTRY=NEVER -DPython_ROOT=$pythonLocation .
-    - name: Build (Python 3.5)
-      if: contains(matrix.python, 'YES')
-      # BEGIN A
-      working-directory: build
-      run: cmake --build . --config ${{ matrix.config }} --parallel 4
-      # END A
-    - name: Test (Python 3.5)
-      # BEGIN B
-      if: contains(matrix.python, 'YES')
-      working-directory: build
-      shell: bash
-      env:
-        PYTHONPATH: ${{ matrix.config }}
-      run: |
-        PYTHON_EXECUTABLE=$(grep 'Python_EXECUTABLE:' CMakeCache.txt | sed 's/.*=//')
-        $PYTHON_EXECUTABLE -m pip install pytest
-        $PYTHON_EXECUTABLE -m pytest ../tests
-      # END B
-
     - name: Setup Python (Python 3.6)
     - name: Setup Python (Python 3.6)
       if: contains(matrix.python, 'YES')
       if: contains(matrix.python, 'YES')
       uses: actions/setup-python@v1
       uses: actions/setup-python@v1
@@ -323,9 +293,10 @@ jobs:
 
 
         llvm-profdata merge pid-*.profraw -o coverage.profdata
         llvm-profdata merge pid-*.profraw -o coverage.profdata
         llvm-cov show $(grep -Rl LLVM_PROFILE_FILE . | sed 's/^/-object /') -instr-profile=coverage.profdata > coverage.txt
         llvm-cov show $(grep -Rl LLVM_PROFILE_FILE . | sed 's/^/-object /') -instr-profile=coverage.profdata > coverage.txt
-        bash <(curl -s https://codecov.io/bash)
+        bash <(curl -s https://codecov.io/bash) -y ../.github/codecov.yml
 
 
   makepanda:
   makepanda:
+    if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')"
     strategy:
     strategy:
       matrix:
       matrix:
         os: [ubuntu-16.04, windows-2016, macOS-latest]
         os: [ubuntu-16.04, windows-2016, macOS-latest]

+ 1 - 0
.gitignore

@@ -3,6 +3,7 @@
 /thirdparty/
 /thirdparty/
 /targetroot/
 /targetroot/
 /dstroot/
 /dstroot/
+/sdks/
 
 
 # Core dumps and traces
 # Core dumps and traces
 core
 core

+ 0 - 60
.travis.yml

@@ -1,60 +0,0 @@
-language: cpp
-sudo: false
-matrix:
-  include:
-    - compiler: clang
-      env: PYTHONV=python3 FLAGS=--installer
-    - compiler: clang
-      env: PYTHONV=python3 FLAGS=--override=STDFLOAT_DOUBLE=1
-    - compiler: gcc
-      env: PYTHONV=python3 FLAGS=--optimize=4
-      before_install:
-        - export CC=gcc-4.7
-        - export CXX=g++-4.7
-    - compiler: clang
-      env: PYTHONV=python3 FLAGS=--no-python SKIP_TESTS=1
-addons:
-  apt:
-    sources:
-    - ubuntu-toolchain-r-test
-    packages:
-    - gcc-4.7
-    - g++-4.7
-    - 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
-    - python-dev
-    - python3-dev
-    - python-virtualenv
-    - zlib1g-dev
-    - fakeroot
-install:
-    - virtualenv --python=$PYTHONV venv && source venv/bin/activate
-    - $PYTHONV -m pip install pytest
-script:
-    - $PYTHONV makepanda/makepanda.py --everything --git-commit $TRAVIS_COMMIT $FLAGS --threads 4
-    - test -n "$SKIP_TESTS" || LD_LIBRARY_PATH=built/lib PYTHONPATH=built $PYTHONV -m pytest -v tests
-notifications:
-  irc:
-    channels:
-      - secure: "jfwHT9RHAVOGRGTMY8TpYKJI6rq8nFoIj41Y0soZdJQNWtSSFEK9AyzZeMY+2dHga7cR/X+/0NWZ2ehhedTnd9FvlzOnMWWC3K0I/b3XWbEdVEqIZnggFkKGqs82Gy3omguRC63yWupeJCcSCckIhoWbLzWy6xV8lF5WC80iXi8="
-    on_success: change
-    on_failure: always
-    use_notice: true
-    skip_join: false
-  webhooks:
-    urls:
-      - https://www.panda3d.org/webhooks/travis-ci.php
-    on_success: change
-    on_failure: always

+ 1 - 0
CMakeLists.txt

@@ -79,6 +79,7 @@ include(GNUInstallDirs)     # Defines CMAKE_INSTALL_<dir> variables
 
 
 # Include global modules needed for configure scripts
 # Include global modules needed for configure scripts
 include(PackageConfig)      # Defines package_option
 include(PackageConfig)      # Defines package_option
+include(PerConfigOption)    # Defines per_config_option
 
 
 # Configure Panda3D
 # Configure Panda3D
 include(dtool/CompilerFlags.cmake)
 include(dtool/CompilerFlags.cmake)

+ 55 - 0
CONTRIBUTING.md

@@ -0,0 +1,55 @@
+# Contributing to Panda3D
+
+Panda3D is an open-source, community-driven project, completely dependent on the
+contribution of volunteers.  As such we highly welcome you to contribute code to
+the project.  This document aims to outline some guidelines for doing so.
+
+If you would like to contribute but aren't sure where to start, please visit the
+[Get Involved](https://www.panda3d.org/get-involved/) page on our website, or
+the excellent [Open Source Guide](https://opensource.guide/how-to-contribute/).
+
+## Before implementing a change
+
+We highly recommend that you file issues before making a change.  Issues are
+used to track bugs and feature requests but also to get feedback from the other
+developers about design decisions or a specific implementation strategy.
+
+It is important for acceptance that the change is implemented in a way that fits
+the general design principles of the Panda3D API, and fits well with the general
+priorities of the team.  Therefore, prior discussion with other developers is
+critical.  Issues can be used to facilitate this, but we also invite you to
+visit the #development channel on Discord (or #panda3d-devel on FreeNode IRC).
+
+We also recommend that you familiarize yourself with the established coding
+style and design patterns of Panda3D, to reduce the amount of changes that have
+to be made during the review process.
+
+## Submitting a change
+
+All changes from non-core contributors are made via pull requests.  This
+requires you to fork the Panda3D repository, create a branch for your change,
+push your changes to this branch, and request that this branch is merged into
+the upstream branch.  Each pull request is reviewed by a maintainer and
+automatically tested for regressions and unit test coverage.  The maintainer
+will suggest any changes, which you can add by committing more code to the same
+branch (you can do a force push if necessary).  Once the change is deemed
+acceptable, the maintainer will merge your change into the appropriate branch of
+the repository.
+
+To make it easier for the maintainer to review your changes, we highly recommend
+that you give a clear and concise description of intent (linking to any issues
+that are resolved by the change), as well as the inclusion of unit tests, which
+contribute to a high level of confidence that this change does not break any
+existing behaviours.  We also recommend breaking up separate changes into
+separate PRs, rather than submitting one big PR with several unrelated changes.
+
+If your change is still a work in progress, please mark the PR as "draft".  This
+will prevent other contributors from receiving an email every time you push a
+new change to your branch.  Draft PRs can also be used to invite early feedback
+on your change, especially if you are uncertain about whether you are going in
+the right direction.
+
+The code in the Panda3D repository is copyrighted to Carnegie Mellon University
+and licensed under the Modified BSD License.  By submitting your changes, you
+accept that your code becomes placed under the same license.  Except in specific
+agreed-upon cases, we do not accept code contributions under alternate licenses.

+ 6 - 6
README.md

@@ -24,7 +24,7 @@ Installing Panda3D
 ==================
 ==================
 
 
 The latest Panda3D SDK can be downloaded from
 The latest Panda3D SDK can be downloaded from
-[this page](https://www.panda3d.org/download/sdk-1-10-6/).
+[this page](https://www.panda3d.org/download/sdk-1-10-7/).
 If you are familiar with installing Python packages, you can use
 If you are familiar with installing Python packages, you can use
 the following command:
 the following command:
 
 
@@ -64,8 +64,8 @@ depending on whether you are on a 32-bit or 64-bit system, or you can
 [click here](https://github.com/rdb/panda3d-thirdparty) for instructions on
 [click here](https://github.com/rdb/panda3d-thirdparty) for instructions on
 building them from source.
 building them from source.
 
 
-- https://www.panda3d.org/download/panda3d-1.10.6/panda3d-1.10.6-tools-win64.zip
-- https://www.panda3d.org/download/panda3d-1.10.6/panda3d-1.10.6-tools-win32.zip
+- https://www.panda3d.org/download/panda3d-1.10.7/panda3d-1.10.7-tools-win64.zip
+- https://www.panda3d.org/download/panda3d-1.10.7/panda3d-1.10.7-tools-win32.zip
 
 
 After acquiring these dependencies, you can build Panda3D from the command
 After acquiring these dependencies, you can build Panda3D from the command
 prompt using the following command.  Change the `--msvc-version` option based
 prompt using the following command.  Change the `--msvc-version` option based
@@ -100,7 +100,7 @@ for you to install, depending on your distribution).
 The following command illustrates how to build Panda3D with some common
 The following command illustrates how to build Panda3D with some common
 options:
 options:
 ```bash
 ```bash
-python makepanda/makepanda.py --everything --installer --no-egl --no-gles --no-gles2 --no-opencv
+python3 makepanda/makepanda.py --everything --installer --no-egl --no-gles --no-gles2 --no-opencv
 ```
 ```
 
 
 You will probably see some warnings saying that it's unable to find several
 You will probably see some warnings saying that it's unable to find several
@@ -113,7 +113,7 @@ If you are on Ubuntu, this command should cover the most frequently
 used third-party packages:
 used third-party packages:
 
 
 ```bash
 ```bash
-sudo apt-get install build-essential pkg-config fakeroot python-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 libgtk2.0-dev libassimp-dev libopenexr-dev
 ```
 ```
 
 
 Once Panda3D has built, you can either install the .deb or .rpm package that
 Once Panda3D has built, you can either install the .deb or .rpm package that
@@ -136,7 +136,7 @@ macOS
 -----
 -----
 
 
 On macOS, you will need to download a set of precompiled thirdparty packages in order to
 On macOS, you will need to download a set of precompiled thirdparty packages in order to
-compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.6/panda3d-1.10.6-tools-mac.tar.gz).
+compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.7/panda3d-1.10.7-tools-mac.tar.gz).
 
 
 After placing the thirdparty directory inside the panda3d source directory,
 After placing the thirdparty directory inside the panda3d source directory,
 you may build Panda3D using a command like the following:
 you may build Panda3D using a command like the following:

+ 50 - 0
cmake/macros/PerConfigOption.cmake

@@ -0,0 +1,50 @@
+# Filename: PerConfigOption.cmake
+#
+# This contains a convenience function for defining per-config options.
+# In single-config generators, it will set the option based on the defined
+# CMAKE_BUILD_TYPE.  In multi-config generators, it will create separate
+# options, one per config.
+#
+# Function: per_config_option
+# Usage:
+#   option(name "help string" [Config1] [Config2] [...ConfigN])
+#
+# Example:
+#   per_config_option(DO_DEBUGGING "Enables debugging." Debug Standard)
+
+set(_PER_CONFIG_OPTIONS CACHE INTERNAL "Internal variable")
+
+function(per_config_option name help)
+  set(_configs ${ARGN})
+
+  # In single-config generatotrs, we simply create one config.
+  if(NOT IS_MULTICONFIG)
+    list(FIND _configs "${CMAKE_BUILD_TYPE}" _index)
+    if(${_index} GREATER -1)
+      option("${name}" "${help}" ON)
+    else()
+      option("${name}" "${help}" OFF)
+    endif()
+
+  elseif(DEFINED "${name}")
+    # It's been explicitly defined, so that makes it not a multi-configuration
+    # variable anymore.
+    option("${name}" "${help}")
+    return()
+
+  else()
+    foreach(_config ${CMAKE_CONFIGURATION_TYPES})
+      string(TOUPPER "${_config}" _config_upper)
+      list(FIND _configs "${_config}" _index)
+      if(${_index} GREATER -1)
+        option("${name}_${_config_upper}" "${help}" ON)
+      else()
+        option("${name}_${_config_upper}" "${help}" OFF)
+      endif()
+    endforeach()
+
+  endif()
+
+  list(APPEND _PER_CONFIG_OPTIONS "${name}")
+  set(_PER_CONFIG_OPTIONS "${_PER_CONFIG_OPTIONS}" CACHE INTERNAL "Internal variable")
+endfunction(per_config_option)

+ 7 - 0
cmake/templates/METADATA.in

@@ -0,0 +1,7 @@
+Metadata-Version: 2.0
+Name: Panda3D
+Version: ${PROJECT_VERSION}
+License: BSD
+Home-page: https://www.panda3d.org/
+Author: Panda3D Team
+Author-email: [email protected]

+ 7 - 0
contrib/src/contribbase/contribsymbols.h

@@ -29,4 +29,11 @@
   #define EXPTP_PANDAAI IMPORT_TEMPL
   #define EXPTP_PANDAAI IMPORT_TEMPL
 #endif
 #endif
 
 
+#ifdef BUILDING_PANDASPEEDTREE
+  #define EXPCL_PANDASPEEDTREE EXPORT_CLASS
+  #define EXPTP_PANDASPEEDTREE EXPORT_TEMPL
+#else
+  #define EXPCL_PANDASPEEDTREE IMPORT_CLASS
+  #define EXPTP_PANDASPEEDTREE IMPORT_TEMPL
+#endif
 #endif
 #endif

+ 21 - 21
contrib/src/rplight/rpLight.I

@@ -148,7 +148,7 @@ inline void RPLight::assign_slot(int slot) {
  *   changed. This will cause all shadow sources to be updated, emitting a
  *   changed. This will cause all shadow sources to be updated, emitting a
  *   shadow update. Be careful when calling this method if you don't want all
  *   shadow update. Be careful when calling this method if you don't want all
  *   sources to get updated. If you only have to invalidate a single shadow source,
  *   sources to get updated. If you only have to invalidate a single shadow source,
- *   use get_shadow_source(n)->set_needs_update(true).
+ *   use `get_shadow_source(n)->set_needs_update(true)`.
  */
  */
 inline void RPLight::invalidate_shadows() {
 inline void RPLight::invalidate_shadows() {
   for (size_t i = 0; i < _shadow_sources.size(); ++i) {
   for (size_t i = 0; i < _shadow_sources.size(); ++i) {
@@ -296,14 +296,14 @@ inline bool RPLight::get_casts_shadows() const {
 }
 }
 
 
 /**
 /**
- * @brief Sets the lights shadow map resolution
- * @details This sets the lights shadow map resolution. This has no effect
+ * @brief Sets the light's shadow map resolution
+ * @details This sets the light's shadow map resolution. This has no effect
  *   when the light is not told to cast shadows (Use RPLight::set_casts_shadows).
  *   when the light is not told to cast shadows (Use RPLight::set_casts_shadows).
  *
  *
- *   When calling this on a light with multiple shadow sources (e.g. PointLight),
- *   this controls the resolution of each source. If the light has 6 shadow sources,
- *   and you use a resolution of 512x512, the lights shadow map will occur a
- *   space of 6 * 512x512 maps in the shadow atlas.
+ *   When calling this on a light with multiple shadow sources (e.g.
+ *   RPPointLight), this controls the resolution of each source. If the light
+ *   has 6 shadow sources, and you use a resolution of 512x512, the light's
+ *   shadow map will occupy a space of 6 * 512x512 maps in the shadow atlas.
  *
  *
  * @param resolution Resolution of the shadow map in pixels
  * @param resolution Resolution of the shadow map in pixels
  */
  */
@@ -326,14 +326,14 @@ inline size_t RPLight::get_shadow_map_resolution() const {
 }
 }
 
 
 /**
 /**
- * @brief Sets the ies profile
+ * @brief Sets the IES profile
  * @details This sets the ies profile of the light. The parameter should be a
  * @details This sets the ies profile of the light. The parameter should be a
  *   handle previously returned by RenderPipeline.load_ies_profile. Using a
  *   handle previously returned by RenderPipeline.load_ies_profile. Using a
  *   value of -1 indicates no ies profile.
  *   value of -1 indicates no ies profile.
  *
  *
- *   Notice that for ies profiles which cover a whole range, you should use
- *   PointLights, whereas for ies profiles which only cover the lower hemisphere
- *   you should use SpotLights for the best performance.
+ *   Notice that for IES profiles which cover a whole range, you should use an
+ *   RPPointLight, whereas for ies profiles which only cover the lower
+ *   hemisphere you should use an RPSpotLight for the best performance.
  *
  *
  * @param profile IES Profile handle
  * @param profile IES Profile handle
  */
  */
@@ -343,8 +343,8 @@ inline void RPLight::set_ies_profile(int profile) {
 }
 }
 
 
 /**
 /**
- * @brief Returns the lights ies profile
- * @details This returns the ies profile of a light, previously set with
+ * @brief Returns the light's IES profile
+ * @details This returns the IES profile of a light, previously set with
  *   RPLight::set_ies_profile. In case no ies profile was set, returns -1.
  *   RPLight::set_ies_profile. In case no ies profile was set, returns -1.
  *
  *
  * @return IES Profile handle
  * @return IES Profile handle
@@ -354,20 +354,20 @@ inline int RPLight::get_ies_profile() const {
 }
 }
 
 
 /**
 /**
- * @brief Returns whether the light has an ies profile assigned
- * @details This returns whether the light has an ies profile assigned,
+ * @brief Returns whether the light has an IES profile assigned
+ * @details This returns whether the light has an IES profile assigned,
  *   previously done with RPLight::set_ies_profile.
  *   previously done with RPLight::set_ies_profile.
  *
  *
- * @return true if the light has an ies profile assigned, false otherwise
+ * @return true if the light has an IES profile assigned, false otherwise
  */
  */
 inline bool RPLight::has_ies_profile() const {
 inline bool RPLight::has_ies_profile() const {
   return _ies_profile >= 0;
   return _ies_profile >= 0;
 }
 }
 
 
 /**
 /**
- * @brief Clears the ies profile
- * @details This clears the ies profile of the light, telling it to no longer
- *   use an ies profile, and instead use the default attenuation.
+ * @brief Clears the IES profile
+ * @details This clears the IES profile of the light, telling it to no longer
+ *   use an IES profile, and instead use the default attenuation.
  */
  */
 inline void RPLight::clear_ies_profile() {
 inline void RPLight::clear_ies_profile() {
   set_ies_profile(-1);
   set_ies_profile(-1);
@@ -377,7 +377,7 @@ inline void RPLight::clear_ies_profile() {
  * @brief Sets the near plane of the light
  * @brief Sets the near plane of the light
  * @details This sets the near plane of all shadow sources of the light. It has
  * @details This sets the near plane of all shadow sources of the light. It has
  *   no effects if the light does not cast shadows. This prevents artifacts from
  *   no effects if the light does not cast shadows. This prevents artifacts from
- *   objects near to the light. It behaves like Lens::set_near_plane.
+ *   objects near to the light. It behaves like Lens::set_near().
  *
  *
  *   It can also help increasing shadow map precision, low near planes will
  *   It can also help increasing shadow map precision, low near planes will
  *   cause the precision to suffer. Try setting the near plane as big as possible.
  *   cause the precision to suffer. Try setting the near plane as big as possible.
@@ -394,7 +394,7 @@ inline void RPLight::set_near_plane(float near_plane) {
 
 
 /**
 /**
  * @brief Returns the near plane of the light
  * @brief Returns the near plane of the light
- * @details This returns the lights near plane, previously set with
+ * @details This returns the light's near plane, previously set with
  *   RPLight::set_near_plane. If the light does not cast shadows, this value
  *   RPLight::set_near_plane. If the light does not cast shadows, this value
  *   is meaningless.
  *   is meaningless.
  *
  *

+ 0 - 0
panda/src/speedtree/config_speedtree.cxx → contrib/src/speedtree/config_speedtree.cxx


+ 1 - 1
panda/src/speedtree/config_speedtree.h → contrib/src/speedtree/config_speedtree.h

@@ -14,7 +14,7 @@
 #ifndef CONFIG_SPEEDTREE_H
 #ifndef CONFIG_SPEEDTREE_H
 #define CONFIG_SPEEDTREE_H
 #define CONFIG_SPEEDTREE_H
 
 
-#include "pandabase.h"
+#include "contribbase.h"
 #include "notifyCategoryProxy.h"
 #include "notifyCategoryProxy.h"
 #include "configVariableBool.h"
 #include "configVariableBool.h"
 #include "configVariableDouble.h"
 #include "configVariableDouble.h"

+ 0 - 0
panda/src/speedtree/loaderFileTypeSrt.cxx → contrib/src/speedtree/loaderFileTypeSrt.cxx


+ 1 - 1
panda/src/speedtree/loaderFileTypeSrt.h → contrib/src/speedtree/loaderFileTypeSrt.h

@@ -14,7 +14,7 @@
 #ifndef LOADERFILETYPESRT_H
 #ifndef LOADERFILETYPESRT_H
 #define LOADERFILETYPESRT_H
 #define LOADERFILETYPESRT_H
 
 
-#include "pandabase.h"
+#include "contribbase.h"
 
 
 #include "loaderFileType.h"
 #include "loaderFileType.h"
 
 

+ 0 - 0
panda/src/speedtree/loaderFileTypeStf.cxx → contrib/src/speedtree/loaderFileTypeStf.cxx


+ 1 - 1
panda/src/speedtree/loaderFileTypeStf.h → contrib/src/speedtree/loaderFileTypeStf.h

@@ -14,7 +14,7 @@
 #ifndef LOADERFILETYPESTF_H
 #ifndef LOADERFILETYPESTF_H
 #define LOADERFILETYPESTF_H
 #define LOADERFILETYPESTF_H
 
 
-#include "pandabase.h"
+#include "contribbase.h"
 
 
 #include "loaderFileType.h"
 #include "loaderFileType.h"
 
 

+ 0 - 0
panda/src/speedtree/pandaspeedtree_composite1.cxx → contrib/src/speedtree/pandaspeedtree_composite1.cxx


+ 0 - 0
panda/src/speedtree/speedTreeNode.I → contrib/src/speedtree/speedTreeNode.I


+ 1 - 1
panda/src/speedtree/speedTreeNode.cxx → contrib/src/speedtree/speedTreeNode.cxx

@@ -11,7 +11,7 @@
  * @date 2009-03-13
  * @date 2009-03-13
  */
  */
 
 
-#include "pandabase.h"
+#include "contribbase.h"
 #include "speedTreeNode.h"
 #include "speedTreeNode.h"
 #include "stBasicTerrain.h"
 #include "stBasicTerrain.h"
 #include "virtualFileSystem.h"
 #include "virtualFileSystem.h"

+ 1 - 1
panda/src/speedtree/speedTreeNode.h → contrib/src/speedtree/speedTreeNode.h

@@ -14,7 +14,7 @@
 #ifndef SPEEDTREENODE_H
 #ifndef SPEEDTREENODE_H
 #define SPEEDTREENODE_H
 #define SPEEDTREENODE_H
 
 
-#include "pandabase.h"
+#include "contribbase.h"
 #include "pandaNode.h"
 #include "pandaNode.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "stTree.h"
 #include "stTree.h"

+ 0 - 0
panda/src/speedtree/speedtree_api.cxx → contrib/src/speedtree/speedtree_api.cxx


+ 0 - 0
panda/src/speedtree/speedtree_api.h → contrib/src/speedtree/speedtree_api.h


+ 0 - 0
panda/src/speedtree/stBasicTerrain.I → contrib/src/speedtree/stBasicTerrain.I


+ 0 - 0
panda/src/speedtree/stBasicTerrain.cxx → contrib/src/speedtree/stBasicTerrain.cxx


+ 1 - 1
panda/src/speedtree/stBasicTerrain.h → contrib/src/speedtree/stBasicTerrain.h

@@ -14,7 +14,7 @@
 #ifndef STBASICTERRAIN_H
 #ifndef STBASICTERRAIN_H
 #define STBASICTERRAIN_H
 #define STBASICTERRAIN_H
 
 
-#include "pandabase.h"
+#include "contribbase.h"
 #include "stTerrain.h"
 #include "stTerrain.h"
 #include "luse.h"
 #include "luse.h"
 #include "pvector.h"
 #include "pvector.h"

+ 0 - 0
panda/src/speedtree/stTerrain.I → contrib/src/speedtree/stTerrain.I


+ 0 - 0
panda/src/speedtree/stTerrain.cxx → contrib/src/speedtree/stTerrain.cxx


+ 1 - 1
panda/src/speedtree/stTerrain.h → contrib/src/speedtree/stTerrain.h

@@ -14,7 +14,7 @@
 #ifndef STTERRAIN_H
 #ifndef STTERRAIN_H
 #define STTERRAIN_H
 #define STTERRAIN_H
 
 
-#include "pandabase.h"
+#include "contribbase.h"
 #include "typedReferenceCount.h"
 #include "typedReferenceCount.h"
 #include "namable.h"
 #include "namable.h"
 #include "geomVertexData.h"
 #include "geomVertexData.h"

+ 0 - 0
panda/src/speedtree/stTransform.I → contrib/src/speedtree/stTransform.I


+ 0 - 0
panda/src/speedtree/stTransform.cxx → contrib/src/speedtree/stTransform.cxx


+ 1 - 1
panda/src/speedtree/stTransform.h → contrib/src/speedtree/stTransform.h

@@ -14,7 +14,7 @@
 #ifndef STTRANSFORM_H
 #ifndef STTRANSFORM_H
 #define STTRANSFORM_H
 #define STTRANSFORM_H
 
 
-#include "pandabase.h"
+#include "contribbase.h"
 #include "transformState.h"
 #include "transformState.h"
 #include "speedtree_api.h"
 #include "speedtree_api.h"
 #include "deg_2_rad.h"
 #include "deg_2_rad.h"

+ 0 - 0
panda/src/speedtree/stTree.I → contrib/src/speedtree/stTree.I


+ 0 - 0
panda/src/speedtree/stTree.cxx → contrib/src/speedtree/stTree.cxx


+ 1 - 1
panda/src/speedtree/stTree.h → contrib/src/speedtree/stTree.h

@@ -14,7 +14,7 @@
 #ifndef STTREE_H
 #ifndef STTREE_H
 #define STTREE_H
 #define STTREE_H
 
 
-#include "pandabase.h"
+#include "contribbase.h"
 #include "typedReferenceCount.h"
 #include "typedReferenceCount.h"
 #include "namable.h"
 #include "namable.h"
 #include "speedtree_api.h"
 #include "speedtree_api.h"

+ 15 - 1
direct/CMakeLists.txt

@@ -53,7 +53,8 @@ if(HAVE_PYTHON)
   file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pandac/PandaModules.py"
   file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pandac/PandaModules.py"
     "\"This module is deprecated.  Import from panda3d.core and other panda3d.* modules instead.\"
     "\"This module is deprecated.  Import from panda3d.core and other panda3d.* modules instead.\"
 
 
-print(\"Warning: pandac.PandaModules is deprecated, import from panda3d.core instead\")\n")
+if __debug__:
+    print(\"Warning: pandac.PandaModules is deprecated, import from panda3d.core instead\")\n")
 
 
   foreach(module ${ALL_INTERROGATE_MODULES})
   foreach(module ${ALL_INTERROGATE_MODULES})
     string(REGEX REPLACE "^.*\\." "" module_name "${module}")
     string(REGEX REPLACE "^.*\\." "" module_name "${module}")
@@ -66,6 +67,19 @@ except ImportError as err:
 ")
 ")
   endforeach()
   endforeach()
 
 
+  file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/pandac/PandaModules.py"
+    "from direct.showbase import DConfig
+
+def get_config_showbase():
+    return DConfig
+
+def get_config_express():
+    return DConfig
+
+getConfigShowbase = get_config_showbase
+getConfigExpress = get_config_express
+")
+
   # Now install ourselves:
   # Now install ourselves:
   install_python_package(pandac SOURCE "${CMAKE_CURRENT_BINARY_DIR}/pandac" LIB COMPONENT Direct)
   install_python_package(pandac SOURCE "${CMAKE_CURRENT_BINARY_DIR}/pandac" LIB COMPONENT Direct)
 endif()
 endif()

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

@@ -1,4 +1,8 @@
-"""Actor module: contains the Actor class"""
+"""Actor module: contains the Actor class.
+
+See the :ref:`models-and-actors` page in the Programming Guide to learn
+more about loading models and animated actors.
+"""
 
 
 __all__ = ['Actor']
 __all__ = ['Actor']
 
 

+ 3 - 0
direct/src/actor/__init__.py

@@ -4,4 +4,7 @@ distributed variant thereof.  Actor is a high-level interface around
 the lower-level :class:`panda3d.core.Character` implementation.
 the lower-level :class:`panda3d.core.Character` implementation.
 It loads and controls an animated character and manages the animations
 It loads and controls an animated character and manages the animations
 playing on it.
 playing on it.
+
+See the :ref:`models-and-actors` page in the Programming Guide to learn
+more about loading models and animated actors.
 """
 """

+ 3 - 3
direct/src/dcparser/dcClass.cxx

@@ -77,7 +77,9 @@ DCClass(DCFile *dc_file, const string &name, bool is_struct, bool bogus_class) :
   _number = -1;
   _number = -1;
   _constructor = nullptr;
   _constructor = nullptr;
 
 
+#ifdef WITHIN_PANDA
   _python_class_defs = nullptr;
   _python_class_defs = nullptr;
+#endif
 }
 }
 
 
 /**
 /**
@@ -85,9 +87,7 @@ DCClass(DCFile *dc_file, const string &name, bool is_struct, bool bogus_class) :
  */
  */
 DCClass::
 DCClass::
 ~DCClass() {
 ~DCClass() {
-  if (_constructor != nullptr) {
-    delete _constructor;
-  }
+  delete _constructor;
 
 
   Fields::iterator fi;
   Fields::iterator fi;
   for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
   for (fi = _fields.begin(); fi != _fields.end(); ++fi) {

+ 3 - 2
direct/src/dcparser/dcClass.h

@@ -172,6 +172,9 @@ private:
   typedef pmap<int, DCField *> FieldsByIndex;
   typedef pmap<int, DCField *> FieldsByIndex;
   FieldsByIndex _fields_by_index;
   FieldsByIndex _fields_by_index;
 
 
+  friend class DCField;
+
+#ifdef WITHIN_PANDA
   // See pandaNode.h for an explanation of this trick
   // See pandaNode.h for an explanation of this trick
   class PythonClassDefs : public ReferenceCount {
   class PythonClassDefs : public ReferenceCount {
   public:
   public:
@@ -179,8 +182,6 @@ private:
   };
   };
   PT(PythonClassDefs) _python_class_defs;
   PT(PythonClassDefs) _python_class_defs;
 
 
-  friend class DCField;
-#ifdef WITHIN_PANDA
   friend class Extension<DCClass>;
   friend class Extension<DCClass>;
 #endif
 #endif
 };
 };

+ 3 - 0
direct/src/dcparser/dcLexer.cxx.prebuilt

@@ -599,7 +599,10 @@ char *dcyytext;
 #include "dcParser.h"
 #include "dcParser.h"
 #include "dcFile.h"
 #include "dcFile.h"
 #include "dcindent.h"
 #include "dcindent.h"
+
+#ifdef WITHIN_PANDA
 #include "pstrtod.h"
 #include "pstrtod.h"
+#endif
 
 
 
 
 static int yyinput(void);        // declared by flex.
 static int yyinput(void);        // declared by flex.

+ 3 - 1
direct/src/dcparser/dcLexer.lxx

@@ -11,8 +11,10 @@
 #include "dcParser.h"
 #include "dcParser.h"
 #include "dcFile.h"
 #include "dcFile.h"
 #include "dcindent.h"
 #include "dcindent.h"
-#include "pstrtod.h"
 
 
+#ifdef WITHIN_PANDA
+#include "pstrtod.h"
+#endif
 
 
 static int yyinput(void);        // declared by flex.
 static int yyinput(void);        // declared by flex.
 extern "C" int dcyywrap();
 extern "C" int dcyywrap();

+ 5 - 3
direct/src/dcparser/dcPacker.I

@@ -1124,7 +1124,9 @@ operator new(size_t size) {
  */
  */
 INLINE void DCPacker::StackElement::
 INLINE void DCPacker::StackElement::
 operator delete(void *ptr) {
 operator delete(void *ptr) {
-  StackElement *obj = (StackElement *)ptr;
-  obj->_next = _deleted_chain;
-  _deleted_chain = obj;
+  if (ptr != nullptr) {
+    StackElement *obj = (StackElement *)ptr;
+    obj->_next = _deleted_chain;
+    _deleted_chain = obj;
+  }
 }
 }

+ 1 - 1
direct/src/dcparser/dcPacker.cxx

@@ -769,7 +769,7 @@ enquote_string(ostream &out, char quote_mark, const string &str) {
     if ((*pi) == quote_mark || (*pi) == '\\') {
     if ((*pi) == quote_mark || (*pi) == '\\') {
       out << '\\' << (*pi);
       out << '\\' << (*pi);
 
 
-    } else if (!isprint(*pi)) {
+    } else if (!isprint(*pi) || (*pi) == '\t') {
       char buffer[10];
       char buffer[10];
       sprintf(buffer, "%02x", (unsigned char)(*pi));
       sprintf(buffer, "%02x", (unsigned char)(*pi));
       out << "\\x" << buffer;
       out << "\\x" << buffer;

+ 1 - 3
direct/src/dcparser/dcPackerCatalog.cxx

@@ -44,9 +44,7 @@ DCPackerCatalog(const DCPackerCatalog &copy) :
  */
  */
 DCPackerCatalog::
 DCPackerCatalog::
 ~DCPackerCatalog() {
 ~DCPackerCatalog() {
-  if (_live_catalog != nullptr) {
-    delete _live_catalog;
-  }
+  delete _live_catalog;
 
 
   SwitchCatalogs::iterator si;
   SwitchCatalogs::iterator si;
   for (si = _switch_catalogs.begin(); si != _switch_catalogs.end(); ++si) {
   for (si = _switch_catalogs.begin(); si != _switch_catalogs.end(); ++si) {

+ 1 - 3
direct/src/dcparser/dcPackerInterface.cxx

@@ -60,9 +60,7 @@ DCPackerInterface(const DCPackerInterface &copy) :
  */
  */
 DCPackerInterface::
 DCPackerInterface::
 ~DCPackerInterface() {
 ~DCPackerInterface() {
-  if (_catalog != nullptr) {
-    delete _catalog;
-  }
+  delete _catalog;
 }
 }
 
 
 /**
 /**

+ 3 - 9
direct/src/dcparser/dcSwitch.cxx

@@ -42,21 +42,15 @@ DCSwitch::
   nassertv(_key_parameter != nullptr);
   nassertv(_key_parameter != nullptr);
   delete _key_parameter;
   delete _key_parameter;
 
 
-  Cases::iterator ci;
-  for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
-    SwitchCase *dcase = (*ci);
+  for (SwitchCase *dcase : _cases) {
     delete dcase;
     delete dcase;
   }
   }
 
 
-  CaseFields::iterator fi;
-  for (fi = _case_fields.begin(); fi != _case_fields.end(); ++fi) {
-    SwitchFields *fields = (*fi);
+  for (SwitchFields *fields : _case_fields) {
     delete fields;
     delete fields;
   }
   }
 
 
-  Fields::iterator ni;
-  for (ni = _nested_fields.begin(); ni != _nested_fields.end(); ++ni) {
-    DCField *field = (*ni);
+  for (DCField *field : _nested_fields) {
     delete field;
     delete field;
   }
   }
 }
 }

+ 2 - 0
direct/src/dcparser/dcbase.h

@@ -70,6 +70,7 @@
 #define BEGIN_PUBLISH
 #define BEGIN_PUBLISH
 #define END_PUBLISH
 #define END_PUBLISH
 #define BLOCKING
 #define BLOCKING
+#define EXTENSION(x)
 
 
 // These control the declspec(dllexport/dllimport) on Windows.  When compiling
 // These control the declspec(dllexport/dllimport) on Windows.  When compiling
 // outside of Panda, we assume we aren't part of a DLL.
 // outside of Panda, we assume we aren't part of a DLL.
@@ -100,6 +101,7 @@ typedef std::string Filename;
 #define pmap std::map
 #define pmap std::map
 #define pset std::set
 #define pset std::set
 #define vector_uchar std::vector<unsigned char>
 #define vector_uchar std::vector<unsigned char>
+#define patof(x) atof(x)
 
 
 #include <stdint.h>
 #include <stdint.h>
 #include <string.h>
 #include <string.h>

+ 1 - 1
direct/src/directbase/DirectStart.py

@@ -4,7 +4,7 @@ opening a graphical window and setting up the scene graph.
 This example demonstrates its use:
 This example demonstrates its use:
 
 
    import direct.directbase.DirectStart
    import direct.directbase.DirectStart
-   run()
+   base.run()
 
 
 While it may be considered useful for quick prototyping in the interactive
 While it may be considered useful for quick prototyping in the interactive
 Python shell, using it in applications is not considered good style.
 Python shell, using it in applications is not considered good style.

+ 1 - 0
direct/src/directscripts/Doxyfile.cxx

@@ -789,6 +789,7 @@ RECURSIVE              = YES
 EXCLUDE                = dtool/src/parser-inc \
 EXCLUDE                = dtool/src/parser-inc \
                          dtool/src/cppparser \
                          dtool/src/cppparser \
                          dtool/src/interrogate \
                          dtool/src/interrogate \
+                         direct/src/directscripts \
                          direct/src/plugin \
                          direct/src/plugin \
                          direct/src/plugin_standalone \
                          direct/src/plugin_standalone \
                          direct/src/plugin_npapi \
                          direct/src/plugin_npapi \

+ 1 - 1
direct/src/directtools/DirectManipulation.py

@@ -1066,7 +1066,7 @@ class ObjectHandles(NodePath, DirectObject):
         # Load up object handles model and assign it to self
         # Load up object handles model and assign it to self
         self.assign(loader.loadModel('models/misc/objectHandles'))
         self.assign(loader.loadModel('models/misc/objectHandles'))
         self.setName(name)
         self.setName(name)
-        self.scalingNode = NodePath(self)
+        self.scalingNode = self.getChild(0)
         self.scalingNode.setName('ohScalingNode')
         self.scalingNode.setName('ohScalingNode')
         self.ohScalingFactor = 1.0
         self.ohScalingFactor = 1.0
         self.directScalingFactor = 1.0
         self.directScalingFactor = 1.0

+ 0 - 10
direct/src/directutil/DirectMySQLdb.py

@@ -1,10 +0,0 @@
-from MySQLdb import *
-
-### DCR: from MySQLdb __init__.py
-def Connect(*args, **kwargs):
-    """Factory function for connections.Connection."""
-    ### DCR: use DirectMySQLdbConnection to prevent memory leaks
-    from direct.directutil.DirectMySQLdbConnection import DirectMySQLdbConnection
-    return DirectMySQLdbConnection(*args, **kwargs)
-
-connect = Connection = Connect

+ 0 - 117
direct/src/directutil/DirectMySQLdbConnection.py

@@ -1,117 +0,0 @@
-import MySQLdb
-from MySQLdb.connections import *
-
-class DirectMySQLdbConnection(Connection):
-    ### DCR: from MySQLdb connections.py Connection.__init__
-    def __init__(self, *args, **kwargs):
-        ### DCR: fixed up relative imports
-        from MySQLdb.constants import CLIENT, FIELD_TYPE
-        from MySQLdb.converters import conversions
-        from weakref import proxy, WeakValueDictionary
-
-        import types
-
-        kwargs2 = kwargs.copy()
-
-        conv = kwargs.get('conv', conversions)
-
-        kwargs2['conv'] = dict([ (k, v) for k, v in conv.items()
-                                 if type(k) is int ])
-
-        self.cursorclass = kwargs2.pop('cursorclass', self.default_cursor)
-        charset = kwargs2.pop('charset', '')
-
-        if charset:
-            use_unicode = True
-        else:
-            use_unicode = False
-
-        use_unicode = kwargs2.pop('use_unicode', use_unicode)
-        sql_mode = kwargs2.pop('sql_mode', '')
-
-        client_flag = kwargs.get('client_flag', 0)
-        ### DCR: fixed up module reference
-        client_version = tuple([ int(n) for n in MySQLdb.connections._mysql.get_client_info().split('.')[:2] ])
-        if client_version >= (4, 1):
-            client_flag |= CLIENT.MULTI_STATEMENTS
-        if client_version >= (5, 0):
-            client_flag |= CLIENT.MULTI_RESULTS
-
-        kwargs2['client_flag'] = client_flag
-
-        ### DCR: skip over the Connection __init__
-        #super(Connection, self).__init__(*args, **kwargs2)
-        MySQLdb._mysql.connection.__init__(self, *args, **kwargs2)
-
-        self.encoders = dict([ (k, v) for k, v in conv.items()
-                               if type(k) is not int ])
-
-        self._server_version = tuple([ int(n) for n in self.get_server_info().split('.')[:2] ])
-
-        db = proxy(self)
-        ### DCR: these functions create memory leaks with gc.DEBUG_SAVEALL turned on
-        """
-        def _get_string_literal():
-            def string_literal(obj, dummy=None):
-                return db.string_literal(obj)
-            return string_literal
-
-        def _get_unicode_literal():
-            def unicode_literal(u, dummy=None):
-                return db.literal(u.encode(unicode_literal.charset))
-            return unicode_literal
-
-        def _get_string_decoder():
-            def string_decoder(s):
-                return s.decode(string_decoder.charset)
-            return string_decoder
-        """
-
-        ### DCR: use methods rather than inline-defined functions to prevent memory leaks
-        string_literal = self._get_string_literal(db)
-        self.unicode_literal = unicode_literal = self._get_unicode_literal(db)
-        self.string_decoder = string_decoder = self._get_string_decoder()
-        if not charset:
-            charset = self.character_set_name()
-        self.set_character_set(charset)
-
-        if sql_mode:
-            self.set_sql_mode(sql_mode)
-
-        if use_unicode:
-            self.converter[FIELD_TYPE.STRING].insert(-1, (None, string_decoder))
-            self.converter[FIELD_TYPE.VAR_STRING].insert(-1, (None, string_decoder))
-            self.converter[FIELD_TYPE.BLOB].insert(-1, (None, string_decoder))
-
-        self.encoders[types.StringType] = string_literal
-        self.encoders[types.UnicodeType] = unicode_literal
-        self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS
-        if self._transactional:
-            # PEP-249 requires autocommit to be initially off
-            self.autocommit(False)
-        self.messages = []
-
-    ### DCR: make inline-defined functions into member methods to avoid garbage
-    def _string_literal(self, db, obj, dummy=None):
-        return db.string_literal(obj)
-    def _get_string_literal(self, db):
-        return Functor(self._string_literal, db)
-
-    def _unicode_literal(self, db, u, dummy=None):
-        return db.literal(u.encode(unicode_literal.charset))
-    def _get_unicode_literal(self, db):
-        return Functor(self._unicode_literal, db)
-
-    def _string_decoder(self, s):
-        return s.decode(string_decoder.charset)
-    def _get_string_decoder(self):
-        # make it into a Functor since MySQLdb.connections.Connection wants to set
-        # attributes on its string_decoder
-        return Functor(self._string_decoder)
-
-    def close(self):
-        Connection.close(self)
-        # break garbage cycles
-        self.unicode_literal = None
-        self.string_decoder = None
-        self.encoders = None

+ 138 - 16
direct/src/dist/FreezeTool.py

@@ -639,6 +639,51 @@ okMissing = [
     'direct.extensions_native.extensions_darwin',
     'direct.extensions_native.extensions_darwin',
     ]
     ]
 
 
+# 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
+# solution is to embed our own segment into the binary so it can be properly
+# signed.
+mach_header_64_layout = '<IIIIIIII'
+
+# Each load command is guaranteed to start with the command identifier and
+# command size. We'll call this the "lc header".
+lc_header_layout = '<II'
+
+# Each Mach-O segment is made up of sections. We need to change both the segment
+# and section information, so we'll need to know the layout of a section as
+# well.
+section64_header_layout = '<16s16sQQIIIIIIII'
+
+# These are all of the load commands we'll need to modify parts of.
+LC_SEGMENT_64 = 0x19
+LC_DYLD_INFO_ONLY = 0x80000022
+LC_SYMTAB = 0x02
+LC_DYSYMTAB = 0x0B
+LC_FUNCTION_STARTS = 0x26
+LC_DATA_IN_CODE = 0x29
+
+lc_layouts = {
+    LC_SEGMENT_64: '<II16sQQQQIIII',
+    LC_DYLD_INFO_ONLY: '<IIIIIIIIIIII',
+    LC_SYMTAB: '<IIIIII',
+    LC_DYSYMTAB: '<IIIIIIIIIIIIIIIIIIII',
+    LC_FUNCTION_STARTS: '<IIII',
+    LC_DATA_IN_CODE: '<IIII',
+}
+
+# All of our modifications involve sliding some offsets, since we need to insert
+# our data in the middle of the binary (we can't just put the data at the end
+# since __LINKEDIT must be the last segment).
+lc_indices_to_slide = {
+    b'__PANDA': [4, 6],
+    b'__LINKEDIT': [3, 5],
+    LC_DYLD_INFO_ONLY: [2, 4, 8, 10],
+    LC_SYMTAB: [2, 4],
+    LC_DYSYMTAB: [14],
+    LC_FUNCTION_STARTS: [2],
+    LC_DATA_IN_CODE: [2],
+}
+
 class Freezer:
 class Freezer:
     class ModuleDef:
     class ModuleDef:
         def __init__(self, moduleName, filename = None,
         def __init__(self, moduleName, filename = None,
@@ -1288,7 +1333,8 @@ class Freezer:
         for moduleName, module in list(self.mf.modules.items()):
         for moduleName, module in list(self.mf.modules.items()):
             if module.__code__:
             if module.__code__:
                 origPathname = module.__code__.co_filename
                 origPathname = module.__code__.co_filename
-                replace_paths.append((origPathname, moduleName))
+                if origPathname:
+                    replace_paths.append((origPathname, moduleName))
         self.mf.replace_paths = replace_paths
         self.mf.replace_paths = replace_paths
 
 
         # Now that we have built up the replacement mapping, go back
         # Now that we have built up the replacement mapping, go back
@@ -1676,6 +1722,8 @@ class Freezer:
 
 
     def generateRuntimeFromStub(self, target, stub_file, use_console, fields={},
     def generateRuntimeFromStub(self, target, stub_file, use_console, fields={},
                                 log_append=False):
                                 log_append=False):
+        self.__replacePaths()
+
         # We must have a __main__ module to make an exe file.
         # We must have a __main__ module to make an exe file.
         if not self.__writingModule('__main__'):
         if not self.__writingModule('__main__'):
             message = "Can't generate an executable without a __main__ module."
             message = "Can't generate an executable without a __main__ module."
@@ -1799,21 +1847,36 @@ class Freezer:
             # Align to page size, so that it can be mmapped.
             # Align to page size, so that it can be mmapped.
             blob_align = 4096
             blob_align = 4096
 
 
-        # Add padding before the blob if necessary.
-        blob_offset = len(stub_data)
-        if (blob_offset & (blob_align - 1)) != 0:
-            pad = (blob_align - (blob_offset & (blob_align - 1)))
-            stub_data += (b'\0' * pad)
-            blob_offset += pad
-        assert (blob_offset % blob_align) == 0
-        assert blob_offset == len(stub_data)
-
         # Also determine the total blob size now.  Add padding to the end.
         # Also determine the total blob size now.  Add padding to the end.
         blob_size = pool_offset + len(pool)
         blob_size = pool_offset + len(pool)
-        if blob_size & 31 != 0:
-            pad = (32 - (blob_size & 31))
+        if blob_size & (blob_align - 1) != 0:
+            pad = (blob_align - (blob_size & (blob_align - 1)))
             blob_size += pad
             blob_size += pad
 
 
+        # TODO: Support creating custom sections in universal binaries.
+        append_blob = True
+        if self.platform.startswith('macosx') and len(bitnesses) == 1:
+            # If our deploy-stub has a __PANDA segment, we know we're meant to
+            # put our blob there rather than attach it to the end.
+            load_commands = self._parse_macho_load_commands(stub_data)
+            if b'__PANDA' in load_commands.keys():
+                append_blob = False
+
+        if self.platform.startswith("macosx") and not append_blob:
+            # Take this time to shift any Mach-O structures around to fit our
+            # blob. We don't need to worry about aligning the offset since the
+            # compiler already took care of that when creating the segment.
+            blob_offset = self._shift_macho_structures(stub_data, load_commands, blob_size)
+        else:
+            # Add padding before the blob if necessary.
+            blob_offset = len(stub_data)
+            if (blob_offset & (blob_align - 1)) != 0:
+                pad = (blob_align - (blob_offset & (blob_align - 1)))
+                stub_data += (b'\0' * pad)
+                blob_offset += pad
+            assert (blob_offset % blob_align) == 0
+            assert blob_offset == len(stub_data)
+
         # Calculate the offsets for the variables.  These are pointers,
         # Calculate the offsets for the variables.  These are pointers,
         # relative to the beginning of the blob.
         # relative to the beginning of the blob.
         field_offsets = {}
         field_offsets = {}
@@ -1893,9 +1956,13 @@ class Freezer:
             blob += struct.pack('<Q', blob_offset)
             blob += struct.pack('<Q', blob_offset)
 
 
         with open(target, 'wb') as f:
         with open(target, 'wb') as f:
-            f.write(stub_data)
-            assert f.tell() == blob_offset
-            f.write(blob)
+            if append_blob:
+                f.write(stub_data)
+                assert f.tell() == blob_offset
+                f.write(blob)
+            else:
+                stub_data[blob_offset:blob_offset + blob_size] = blob
+                f.write(stub_data)
 
 
         os.chmod(target, 0o755)
         os.chmod(target, 0o755)
         return target
         return target
@@ -2153,7 +2220,9 @@ class Freezer:
                     symoff += nlist_size
                     symoff += nlist_size
                     name = strings[strx : strings.find(b'\0', strx)]
                     name = strings[strx : strings.find(b'\0', strx)]
 
 
-                    if name == b'_' + symbol_name:
+                    # If the entry's type has any bits at 0xe0 set, it's a debug
+                    # symbol, and will point us to the wrong place.
+                    if name == b'_' + symbol_name and type & 0xe0 == 0:
                         # Find out in which segment this is.
                         # Find out in which segment this is.
                         for vmaddr, vmsize, fileoff in segments:
                         for vmaddr, vmsize, fileoff in segments:
                             # Is it defined in this segment?
                             # Is it defined in this segment?
@@ -2163,6 +2232,59 @@ class Freezer:
                                 return fileoff + rel
                                 return fileoff + rel
                         print("Could not find memory address for symbol %s" % (symbol_name))
                         print("Could not find memory address for symbol %s" % (symbol_name))
 
 
+    def _parse_macho_load_commands(self, macho_data):
+        """Returns the list of load commands from macho_data."""
+        mach_header_64 = list(
+            struct.unpack_from(mach_header_64_layout, macho_data, 0))
+
+        num_load_commands = mach_header_64[4]
+
+        load_commands = {}
+
+        curr_lc_offset = struct.calcsize(mach_header_64_layout)
+        for i in range(num_load_commands):
+            lc = struct.unpack_from(lc_header_layout, macho_data, curr_lc_offset)
+            layout = lc_layouts.get(lc[0])
+            if layout:
+                # Make it a list since we want to mutate it.
+                lc = list(struct.unpack_from(layout, macho_data, curr_lc_offset))
+
+                if lc[0] == LC_SEGMENT_64:
+                    stripped_name = lc[2].rstrip(b'\0')
+                    if stripped_name in [b'__PANDA', b'__LINKEDIT']:
+                        load_commands[stripped_name] = (curr_lc_offset, lc)
+                else:
+                    load_commands[lc[0]] = (curr_lc_offset, lc)
+
+            curr_lc_offset += lc[1]
+
+        return load_commands
+
+    def _shift_macho_structures(self, macho_data, load_commands, blob_size):
+        """Given the stub and the size of our blob, make room for it and edit
+        all of the necessary structures to keep the binary valid. Returns the
+        offset where the blob should be placed."""
+
+        for lc_key in load_commands.keys():
+            for index in lc_indices_to_slide[lc_key]:
+                load_commands[lc_key][1][index] += blob_size
+
+            if lc_key == b'__PANDA':
+                section_header_offset = load_commands[lc_key][0] + struct.calcsize(lc_layouts[LC_SEGMENT_64])
+                section_header = list(struct.unpack_from(section64_header_layout, macho_data, section_header_offset))
+                section_header[3] = blob_size
+                struct.pack_into(section64_header_layout, macho_data, section_header_offset, *section_header)
+
+            layout = LC_SEGMENT_64 if lc_key in [b'__PANDA', b'__LINKEDIT'] else lc_key
+            struct.pack_into(lc_layouts[layout], macho_data, load_commands[lc_key][0], *load_commands[lc_key][1])
+
+        blob_offset = load_commands[b'__PANDA'][1][5]
+
+        # Write in some null bytes until we write in the actual blob.
+        macho_data[blob_offset:blob_offset] = b'\0' * blob_size
+
+        return blob_offset
+
     def makeModuleDef(self, mangledName, code):
     def makeModuleDef(self, mangledName, code):
         result = ''
         result = ''
         result += 'static unsigned char %s[] = {' % (mangledName)
         result += 'static unsigned char %s[] = {' % (mangledName)

+ 27 - 13
direct/src/dist/commands.py

@@ -4,8 +4,6 @@ See the :ref:`distribution` section of the programming manual for information
 on how to use these commands.
 on how to use these commands.
 """
 """
 
 
-from __future__ import print_function
-
 import collections
 import collections
 import os
 import os
 import plistlib
 import plistlib
@@ -31,9 +29,6 @@ import panda3d.core as p3d
 
 
 
 
 if sys.version_info < (3, 0):
 if sys.version_info < (3, 0):
-    # Python 3 defines these subtypes of IOError, but Python 2 doesn't.
-    FileNotFoundError = IOError
-
     # Warn the user.  They might be using Python 2 by accident.
     # Warn the user.  They might be using Python 2 by accident.
     print("=================================================================")
     print("=================================================================")
     print("WARNING: You are using Python 2, which has reached the end of its")
     print("WARNING: You are using Python 2, which has reached the end of its")
@@ -218,6 +213,7 @@ class build_apps(setuptools.Command):
             'dciman32.dll', 'comdlg32.dll', 'comctl32.dll', 'ole32.dll',
             'dciman32.dll', 'comdlg32.dll', 'comctl32.dll', 'ole32.dll',
             'oleaut32.dll', 'gdiplus.dll', 'winmm.dll', 'iphlpapi.dll',
             'oleaut32.dll', 'gdiplus.dll', 'winmm.dll', 'iphlpapi.dll',
             'msvcrt.dll', 'kernelbase.dll', 'msimg32.dll', 'msacm32.dll',
             'msvcrt.dll', 'kernelbase.dll', 'msimg32.dll', 'msacm32.dll',
+            'setupapi.dll', 'version.dll',
 
 
             # manylinux1/linux
             # manylinux1/linux
             'libdl.so.*', 'libstdc++.so.*', 'libm.so.*', 'libgcc_s.so.*',
             'libdl.so.*', 'libstdc++.so.*', 'libm.so.*', 'libgcc_s.so.*',
@@ -235,6 +231,12 @@ class build_apps(setuptools.Command):
             '/usr/lib/libedit.*.dylib',
             '/usr/lib/libedit.*.dylib',
             '/System/Library/**',
             '/System/Library/**',
         ]
         ]
+
+        if sys.version_info >= (3, 5):
+            # Python 3.5+ requires at least Windows Vista to run anyway, so we
+            # shouldn't warn about DLLs that are shipped with Vista.
+            self.exclude_dependencies += ['bcrypt.dll']
+
         self.package_data_dirs = {}
         self.package_data_dirs = {}
 
 
         # We keep track of the zip files we've opened.
         # We keep track of the zip files we've opened.
@@ -374,12 +376,13 @@ class build_apps(setuptools.Command):
                     os.remove(os.path.join(whldir, whl))
                     os.remove(os.path.join(whldir, whl))
 
 
         pip_args = [
         pip_args = [
+            '--disable-pip-version-check',
             'download',
             'download',
             '-d', whldir,
             '-d', whldir,
             '-r', self.requirements_path,
             '-r', self.requirements_path,
             '--only-binary', ':all:',
             '--only-binary', ':all:',
             '--platform', platform,
             '--platform', platform,
-            '--abi', abi_tag
+            '--abi', abi_tag,
         ]
         ]
 
 
         if self.use_optimized_wheels:
         if self.use_optimized_wheels:
@@ -623,12 +626,16 @@ class build_apps(setuptools.Command):
                     rootdir = wf.split(os.path.sep, 1)[0]
                     rootdir = wf.split(os.path.sep, 1)[0]
                     search_path.append(os.path.join(whl, rootdir, '.libs'))
                     search_path.append(os.path.join(whl, rootdir, '.libs'))
 
 
+                    # Also look for eg. numpy.libs or Pillow.libs in the root
+                    whl_name = os.path.basename(whl).split('-', 1)[0]
+                    search_path.append(os.path.join(whl, whl_name + '.libs'))
+
                     # Also look for more specific per-package cases, defined in
                     # Also look for more specific per-package cases, defined in
                     # PACKAGE_LIB_DIRS at the top of this file.
                     # PACKAGE_LIB_DIRS at the top of this file.
-                    whl_name = os.path.basename(whl).split('-', 1)[0]
                     extra_dirs = PACKAGE_LIB_DIRS.get(whl_name, [])
                     extra_dirs = PACKAGE_LIB_DIRS.get(whl_name, [])
                     for extra_dir in extra_dirs:
                     for extra_dir in extra_dirs:
                         search_path.append(os.path.join(whl, extra_dir.replace('/', os.path.sep)))
                         search_path.append(os.path.join(whl, extra_dir.replace('/', os.path.sep)))
+
             return search_path
             return search_path
 
 
         def create_runtime(appname, mainscript, use_console):
         def create_runtime(appname, mainscript, use_console):
@@ -1015,7 +1022,10 @@ class build_apps(setuptools.Command):
         source_dir = os.path.dirname(source_path)
         source_dir = os.path.dirname(source_path)
         target_dir = os.path.dirname(target_path)
         target_dir = os.path.dirname(target_path)
         base = os.path.basename(target_path)
         base = os.path.basename(target_path)
-        self.copy_dependencies(target_path, target_dir, search_path + [source_dir], base)
+
+        if source_dir not in search_path:
+            search_path = search_path + [source_dir]
+        self.copy_dependencies(target_path, target_dir, search_path, base)
 
 
     def copy_dependencies(self, target_path, target_dir, search_path, referenced_by):
     def copy_dependencies(self, target_path, target_dir, search_path, referenced_by):
         """ Copies the dependencies of target_path into target_dir. """
         """ Copies the dependencies of target_path into target_dir. """
@@ -1030,8 +1040,7 @@ class build_apps(setuptools.Command):
             pe = pefile.PEFile()
             pe = pefile.PEFile()
             pe.read(fp)
             pe.read(fp)
             for lib in pe.imports:
             for lib in pe.imports:
-                if not lib.lower().startswith('api-ms-win-'):
-                    deps.append(lib)
+                deps.append(lib)
 
 
         elif magic == b'\x7FELF':
         elif magic == b'\x7FELF':
             # Elf magic.  Used on (among others) Linux and FreeBSD.
             # Elf magic.  Used on (among others) Linux and FreeBSD.
@@ -1350,17 +1359,22 @@ class bdist_apps(setuptools.Command):
         nsi.write('Section "" SecCore\n')
         nsi.write('Section "" SecCore\n')
         nsi.write('  SetOutPath "$INSTDIR"\n')
         nsi.write('  SetOutPath "$INSTDIR"\n')
         curdir = ""
         curdir = ""
+        nsi_dir = p3d.Filename.fromOsSpecific(build_cmd.build_base)
+        build_root_dir = p3d.Filename.fromOsSpecific(build_dir)
         for root, dirs, files in os.walk(build_dir):
         for root, dirs, files in os.walk(build_dir):
             for name in files:
             for name in files:
                 basefile = p3d.Filename.fromOsSpecific(os.path.join(root, name))
                 basefile = p3d.Filename.fromOsSpecific(os.path.join(root, name))
                 file = p3d.Filename(basefile)
                 file = p3d.Filename(basefile)
                 file.makeAbsolute()
                 file.makeAbsolute()
-                file.makeRelativeTo(build_dir)
-                outdir = file.getDirname().replace('/', '\\')
+                file.makeRelativeTo(nsi_dir)
+                outdir = p3d.Filename(basefile)
+                outdir.makeAbsolute()
+                outdir.makeRelativeTo(build_root_dir)
+                outdir = outdir.getDirname().replace('/', '\\')
                 if curdir != outdir:
                 if curdir != outdir:
                     nsi.write('  SetOutPath "$INSTDIR\\%s"\n' % outdir)
                     nsi.write('  SetOutPath "$INSTDIR\\%s"\n' % outdir)
                     curdir = outdir
                     curdir = outdir
-                nsi.write('  File "%s"\n' % (basefile.toOsSpecific()))
+                nsi.write('  File "%s"\n' % (file.toOsSpecific()))
         nsi.write('  SetOutPath "$INSTDIR"\n')
         nsi.write('  SetOutPath "$INSTDIR"\n')
         nsi.write('  WriteUninstaller "$INSTDIR\\Uninstall.exe"\n')
         nsi.write('  WriteUninstaller "$INSTDIR\\Uninstall.exe"\n')
         nsi.write('  ; Start menu items\n')
         nsi.write('  ; Start menu items\n')

+ 1 - 0
direct/src/distributed/ConnectionRepository.py

@@ -260,6 +260,7 @@ class ConnectionRepository(
             searchPath = getModelPath().getValue()
             searchPath = getModelPath().getValue()
             for dcFileName in dcFileNames:
             for dcFileName in dcFileNames:
                 pathname = Filename(dcFileName)
                 pathname = Filename(dcFileName)
+                vfs = VirtualFileSystem.getGlobalPtr()
                 vfs.resolveFilename(pathname, searchPath)
                 vfs.resolveFilename(pathname, searchPath)
                 readResult = dcFile.read(pathname)
                 readResult = dcFile.read(pathname)
                 if not readResult:
                 if not readResult:

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

@@ -225,6 +225,7 @@ class ServerRepository:
             searchPath = getModelPath().getValue()
             searchPath = getModelPath().getValue()
             for dcFileName in dcFileNames:
             for dcFileName in dcFileNames:
                 pathname = Filename(dcFileName)
                 pathname = Filename(dcFileName)
+                vfs = VirtualFileSystem.getGlobalPtr()
                 vfs.resolveFilename(pathname, searchPath)
                 vfs.resolveFilename(pathname, searchPath)
                 readResult = dcFile.read(pathname)
                 readResult = dcFile.read(pathname)
                 if not readResult:
                 if not readResult:
@@ -628,7 +629,7 @@ class ServerRepository:
         del self.clientsByConnection[client.connection]
         del self.clientsByConnection[client.connection]
         del self.clientsByDoIdBase[client.doIdBase]
         del self.clientsByDoIdBase[client.doIdBase]
 
 
-        id = client.doIdBase / self.doIdRange
+        id = client.doIdBase // self.doIdRange
         self.idAllocator.free(id)
         self.idAllocator.free(id)
 
 
         self.qcr.removeConnection(client.connection)
         self.qcr.removeConnection(client.connection)
@@ -689,7 +690,7 @@ class ServerRepository:
     def clientHardDisconnectTask(self, task):
     def clientHardDisconnectTask(self, task):
         """ client did not tell us he was leaving but we lost connection to
         """ client did not tell us he was leaving but we lost connection to
         him, so we need to update our data and tell others """
         him, so we need to update our data and tell others """
-        for client in self.clientsByConnection.values():
+        for client in list(self.clientsByConnection.values()):
             if not self.qcr.isConnectionOk(client.connection):
             if not self.qcr.isConnectionOk(client.connection):
                 self.handleClientDisconnect(client)
                 self.handleClientDisconnect(client)
         return Task.cont
         return Task.cont

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

@@ -2,4 +2,7 @@
 This package contains an implementation of the Distributed Networking
 This package contains an implementation of the Distributed Networking
 API, a high-level networking system that automatically propagates
 API, a high-level networking system that automatically propagates
 changes made on distributed objects to interested clients.
 changes made on distributed objects to interested clients.
+
+See the :ref:`distributed-networking` section of the Programming Guide to
+learn more about the distributed networking system.
 """
 """

+ 2 - 5
direct/src/extensions_native/CInterval_extensions.py

@@ -63,12 +63,9 @@ def popupControls(self, tl = None):
         import math
         import math
         # Don't use a regular import, to prevent ModuleFinder from picking
         # Don't use a regular import, to prevent ModuleFinder from picking
         # it up as a dependency when building a .p3d package.
         # it up as a dependency when building a .p3d package.
-        import importlib, sys
+        import importlib
         EntryScale = importlib.import_module('direct.tkwidgets.EntryScale')
         EntryScale = importlib.import_module('direct.tkwidgets.EntryScale')
-        if sys.version_info >= (3, 0):
-            tkinter = importlib.import_module('tkinter')
-        else:
-            tkinter = importlib.import_module('Tkinter')
+        tkinter = importlib.import_module('tkinter')
 
 
         if tl == None:
         if tl == None:
             tl = tkinter.Toplevel()
             tl = tkinter.Toplevel()

+ 119 - 3
direct/src/filter/CommonFilters.py

@@ -1,7 +1,8 @@
 """
 """
 
 
 Class CommonFilters implements certain common image
 Class CommonFilters implements certain common image
-postprocessing filters.
+postprocessing filters.  See the :ref:`common-image-filters` page for
+more information about how to use these filters.
 
 
 It is not ideal that these filters are all included in a single
 It is not ideal that these filters are all included in a single
 monolithic module.  Unfortunately, when you want to apply two filters
 monolithic module.  Unfortunately, when you want to apply two filters
@@ -27,6 +28,7 @@ from panda3d.core import LVecBase4, LPoint2
 from panda3d.core import Filename
 from panda3d.core import Filename
 from panda3d.core import AuxBitplaneAttrib
 from panda3d.core import AuxBitplaneAttrib
 from panda3d.core import Texture, Shader, ATSNone
 from panda3d.core import Texture, Shader, ATSNone
+from panda3d.core import FrameBufferProperties
 import os
 import os
 
 
 CARTOON_BODY="""
 CARTOON_BODY="""
@@ -177,7 +179,15 @@ class CommonFilters:
                 self.textures[tex].setWrapU(Texture.WMClamp)
                 self.textures[tex].setWrapU(Texture.WMClamp)
                 self.textures[tex].setWrapV(Texture.WMClamp)
                 self.textures[tex].setWrapV(Texture.WMClamp)
 
 
-            self.finalQuad = self.manager.renderSceneInto(textures = self.textures, auxbits=auxbits)
+            fbprops = None
+            clamping = None
+            if "HighDynamicRange" in configuration:
+                fbprops = FrameBufferProperties()
+                fbprops.setFloatColor(True)
+                fbprops.setSrgbColor(False)
+                clamping = False
+
+            self.finalQuad = self.manager.renderSceneInto(textures = self.textures, auxbits=auxbits, fbprops=fbprops, clamping=clamping)
             if (self.finalQuad == None):
             if (self.finalQuad == None):
                 self.cleanup()
                 self.cleanup()
                 return False
                 return False
@@ -255,6 +265,17 @@ class CommonFilters:
             texcoordSets = list(enumerate(texcoordPadding.keys()))
             texcoordSets = list(enumerate(texcoordPadding.keys()))
 
 
             text = "//Cg\n"
             text = "//Cg\n"
+            if "HighDynamicRange" in configuration:
+                text += "static const float3x3 aces_input_mat = {\n"
+                text += "  {0.59719, 0.35458, 0.04823},\n"
+                text += "  {0.07600, 0.90834, 0.01566},\n"
+                text += "  {0.02840, 0.13383, 0.83777},\n"
+                text += "};\n"
+                text += "static const float3x3 aces_output_mat = {\n"
+                text += "  { 1.60475, -0.53108, -0.07367},\n"
+                text += "  {-0.10208,  1.10813, -0.00605},\n"
+                text += "  {-0.00327, -0.07276,  1.07602},\n"
+                text += "};\n"
             text += "void vshader(float4 vtx_position : POSITION,\n"
             text += "void vshader(float4 vtx_position : POSITION,\n"
             text += "  out float4 l_position : POSITION,\n"
             text += "  out float4 l_position : POSITION,\n"
 
 
@@ -301,6 +322,10 @@ class CommonFilters:
             if ("VolumetricLighting" in configuration):
             if ("VolumetricLighting" in configuration):
                 text += "  uniform float4 k_casterpos,\n"
                 text += "  uniform float4 k_casterpos,\n"
                 text += "  uniform float4 k_vlparams,\n"
                 text += "  uniform float4 k_vlparams,\n"
+
+            if ("ExposureAdjust" in configuration):
+                text += "  uniform float k_exposure,\n"
+
             text += "  out float4 o_color : COLOR)\n"
             text += "  out float4 o_color : COLOR)\n"
             text += "{\n"
             text += "{\n"
             text += "  o_color = tex2D(k_txcolor, %s);\n" % (texcoords["color"])
             text += "  o_color = tex2D(k_txcolor, %s);\n" % (texcoords["color"])
@@ -332,6 +357,14 @@ class CommonFilters:
                 text += "  }\n"
                 text += "  }\n"
                 text += "  o_color += float4(vlcolor * k_vlparams.z, 1);\n"
                 text += "  o_color += float4(vlcolor * k_vlparams.z, 1);\n"
 
 
+            if ("ExposureAdjust" in configuration):
+                text += "  o_color.rgb *= k_exposure;\n"
+
+            # With thanks to Stephen Hill!
+            if ("HighDynamicRange" in configuration):
+                text += "  float3 aces_color = mul(aces_input_mat, o_color.rgb);\n"
+                text += "  o_color.rgb = saturate(mul(aces_output_mat, (aces_color * (aces_color + 0.0245786f) - 0.000090537f) / (aces_color * (0.983729f * aces_color + 0.4329510f) + 0.238081f)));\n"
+
             if ("GammaAdjust" in configuration):
             if ("GammaAdjust" in configuration):
                 gamma = configuration["GammaAdjust"]
                 gamma = configuration["GammaAdjust"]
                 if gamma == 0.5:
                 if gamma == 0.5:
@@ -341,6 +374,11 @@ class CommonFilters:
                 elif gamma != 1.0:
                 elif gamma != 1.0:
                     text += "  o_color.rgb = pow(o_color.rgb, %ff);\n" % (gamma)
                     text += "  o_color.rgb = pow(o_color.rgb, %ff);\n" % (gamma)
 
 
+            if ("SrgbEncode" in configuration):
+                text += "  o_color.r = (o_color.r < 0.0031308) ? (o_color.r * 12.92) : (1.055 * pow(o_color.r, 0.41666) - 0.055);\n"
+                text += "  o_color.g = (o_color.g < 0.0031308) ? (o_color.g * 12.92) : (1.055 * pow(o_color.g, 0.41666) - 0.055);\n"
+                text += "  o_color.b = (o_color.b < 0.0031308) ? (o_color.b * 12.92) : (1.055 * pow(o_color.b, 0.41666) - 0.055);\n"
+
             if ("Inverted" in configuration):
             if ("Inverted" in configuration):
                 text += "  o_color = float4(1, 1, 1, 1) - o_color;\n"
                 text += "  o_color = float4(1, 1, 1, 1) - o_color;\n"
             text += "}\n"
             text += "}\n"
@@ -386,6 +424,11 @@ class CommonFilters:
                 self.ssao[0].setShaderInput("params1", config.numsamples, -float(config.amount) / config.numsamples, config.radius, 0)
                 self.ssao[0].setShaderInput("params1", config.numsamples, -float(config.amount) / config.numsamples, config.radius, 0)
                 self.ssao[0].setShaderInput("params2", config.strength, config.falloff, 0, 0)
                 self.ssao[0].setShaderInput("params2", config.strength, config.falloff, 0, 0)
 
 
+        if (changed == "ExposureAdjust") or fullrebuild:
+            if ("ExposureAdjust" in configuration):
+                stops = configuration["ExposureAdjust"]
+                self.finalQuad.setShaderInput("exposure", 2 ** stops)
+
         self.update()
         self.update()
         return True
         return True
 
 
@@ -547,6 +590,73 @@ class CommonFilters:
             return self.reconfigure((old_gamma != 1.0), "GammaAdjust")
             return self.reconfigure((old_gamma != 1.0), "GammaAdjust")
         return True
         return True
 
 
+    def setSrgbEncode(self, force=False):
+        """ Applies the inverse sRGB EOTF to the output, unless the window
+        already has an sRGB framebuffer, in which case this filter refuses to
+        apply, to prevent accidental double-application.
+
+        Set the force argument to True to force it to be applied in all cases.
+
+        .. versionadded:: 1.10.7
+        """
+        new_enable = force or not self.manager.win.getFbProperties().getSrgbColor()
+        old_enable = self.configuration.get("SrgbEncode", False)
+        if new_enable and not old_enable:
+            self.configuration["SrgbEncode"] = True
+            return self.reconfigure(True, "SrgbEncode")
+        elif not new_enable and old_enable:
+            del self.configuration["SrgbEncode"]
+        return new_enable
+
+    def delSrgbEncode(self):
+        """ Reverses the effects of setSrgbEncode. """
+        if ("SrgbEncode" in self.configuration):
+            old_enable = self.configuration["SrgbEncode"]
+            del self.configuration["SrgbEncode"]
+            return self.reconfigure(old_enable, "SrgbEncode")
+        return True
+
+    def setHighDynamicRange(self):
+        """ Enables HDR rendering by using a floating-point framebuffer,
+        disabling color clamping on the main scene, and applying a tone map
+        operator (ACES).
+
+        It may also be necessary to use setExposureAdjust to perform exposure
+        compensation on the scene, depending on the lighting intensity.
+
+        .. versionadded:: 1.10.7
+        """
+
+        fullrebuild = (("HighDynamicRange" in self.configuration) is False)
+        self.configuration["HighDynamicRange"] = 1
+        return self.reconfigure(fullrebuild, "HighDynamicRange")
+
+    def delHighDynamicRange(self):
+        if ("HighDynamicRange" in self.configuration):
+            del self.configuration["HighDynamicRange"]
+            return self.reconfigure(True, "HighDynamicRange")
+        return True
+
+    def setExposureAdjust(self, stops):
+        """ Sets a relative exposure adjustment to multiply with the result of
+        rendering the scene, in stops.  A value of 0 means no adjustment, a
+        positive value will result in a brighter image.  Useful in conjunction
+        with HDR, see setHighDynamicRange.
+
+        .. versionadded:: 1.10.7
+        """
+        old_stops = self.configuration.get("ExposureAdjust")
+        if old_stops != stops:
+            self.configuration["ExposureAdjust"] = stops
+            return self.reconfigure(old_stops is None, "ExposureAdjust")
+        return True
+
+    def delExposureAdjust(self):
+        if ("ExposureAdjust" in self.configuration):
+            del self.configuration["ExposureAdjust"]
+            return self.reconfigure(True, "ExposureAdjust")
+        return True
+
     #snake_case alias:
     #snake_case alias:
     del_cartoon_ink = delCartoonInk
     del_cartoon_ink = delCartoonInk
     set_half_pixel_shift = setHalfPixelShift
     set_half_pixel_shift = setHalfPixelShift
@@ -555,7 +665,6 @@ class CommonFilters:
     del_inverted = delInverted
     del_inverted = delInverted
     del_view_glow = delViewGlow
     del_view_glow = delViewGlow
     set_volumetric_lighting = setVolumetricLighting
     set_volumetric_lighting = setVolumetricLighting
-    del_gamma_adjust = delGammaAdjust
     set_bloom = setBloom
     set_bloom = setBloom
     set_view_glow = setViewGlow
     set_view_glow = setViewGlow
     set_ambient_occlusion = setAmbientOcclusion
     set_ambient_occlusion = setAmbientOcclusion
@@ -566,3 +675,10 @@ class CommonFilters:
     del_blur_sharpen = delBlurSharpen
     del_blur_sharpen = delBlurSharpen
     del_volumetric_lighting = delVolumetricLighting
     del_volumetric_lighting = delVolumetricLighting
     set_gamma_adjust = setGammaAdjust
     set_gamma_adjust = setGammaAdjust
+    del_gamma_adjust = delGammaAdjust
+    set_srgb_encode = setSrgbEncode
+    del_srgb_encode = delSrgbEncode
+    set_exposure_adjust = setExposureAdjust
+    del_exposure_adjust = delExposureAdjust
+    set_high_dynamic_range = setHighDynamicRange
+    del_high_dynamic_range = delHighDynamicRange

+ 7 - 1
direct/src/filter/FilterManager.py

@@ -3,6 +3,8 @@
 The FilterManager is a convenience class that helps with the creation
 The FilterManager is a convenience class that helps with the creation
 of render-to-texture buffers for image postprocessing applications.
 of render-to-texture buffers for image postprocessing applications.
 
 
+See :ref:`generalized-image-filters` for information on how to use this class.
+
 Still need to implement:
 Still need to implement:
 
 
 * Make sure sort-order of buffers is correct.
 * Make sure sort-order of buffers is correct.
@@ -22,6 +24,7 @@ from panda3d.core import WindowProperties, FrameBufferProperties
 from panda3d.core import Camera
 from panda3d.core import Camera
 from panda3d.core import OrthographicLens
 from panda3d.core import OrthographicLens
 from panda3d.core import AuxBitplaneAttrib
 from panda3d.core import AuxBitplaneAttrib
+from panda3d.core import LightRampAttrib
 from direct.directnotify.DirectNotifyGlobal import *
 from direct.directnotify.DirectNotifyGlobal import *
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 
 
@@ -124,7 +127,7 @@ class FilterManager(DirectObject):
 
 
         return winx,winy
         return winx,winy
 
 
-    def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None, fbprops=None):
+    def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None, fbprops=None, clamping=None):
 
 
         """ Causes the scene to be rendered into the supplied textures
         """ Causes the scene to be rendered into the supplied textures
         instead of into the original window.  Puts a fullscreen quad
         instead of into the original window.  Puts a fullscreen quad
@@ -207,6 +210,9 @@ class FilterManager(DirectObject):
         #cs.setShaderAuto()
         #cs.setShaderAuto()
         if (auxbits):
         if (auxbits):
             cs.setAttrib(AuxBitplaneAttrib.make(auxbits))
             cs.setAttrib(AuxBitplaneAttrib.make(auxbits))
+        if clamping is False:
+            # Disables clamping in the shader generator.
+            cs.setAttrib(LightRampAttrib.make_identity())
         self.camera.node().setInitialState(cs.getState())
         self.camera.node().setInitialState(cs.getState())
 
 
         quadcamnode = Camera("filter-quad-cam")
         quadcamnode = Camera("filter-quad-cam")

+ 3 - 0
direct/src/filter/__init__.py

@@ -8,4 +8,7 @@ texture values as desired.
 The :class:`.CommonFilters` class contains various filters that are
 The :class:`.CommonFilters` class contains various filters that are
 provided out of the box, whereas the :class:`.FilterManager` class
 provided out of the box, whereas the :class:`.FilterManager` class
 is a lower-level class that allows you to set up your own filters.
 is a lower-level class that allows you to set up your own filters.
+
+See the :ref:`render-to-texture-and-image-postprocessing` section of the
+Programming Guide to learn more about image postprocessing in Panda3D.
 """
 """

+ 2 - 19
direct/src/fsm/State.py

@@ -33,15 +33,13 @@ class State(DirectObject):
                     if enterFunc.__func__ == oldFunction:
                     if enterFunc.__func__ == oldFunction:
                         # print 'found: ', enterFunc, oldFunction
                         # print 'found: ', enterFunc, oldFunction
                         state.setEnterFunc(types.MethodType(newFunction,
                         state.setEnterFunc(types.MethodType(newFunction,
-                                                            enterFunc.__self__,
-                                                            enterFunc.__self__.__class__))
+                                                            enterFunc.__self__))
                         count += 1
                         count += 1
                 if type(exitFunc) == types.MethodType:
                 if type(exitFunc) == types.MethodType:
                     if exitFunc.__func__ == oldFunction:
                     if exitFunc.__func__ == oldFunction:
                         # print 'found: ', exitFunc, oldFunction
                         # print 'found: ', exitFunc, oldFunction
                         state.setExitFunc(types.MethodType(newFunction,
                         state.setExitFunc(types.MethodType(newFunction,
-                                                           exitFunc.__self__,
-                                                           exitFunc.__self__.__class__))
+                                                           exitFunc.__self__))
                         count += 1
                         count += 1
             return count
             return count
 
 
@@ -215,18 +213,3 @@ class State(DirectObject):
     def __str__(self):
     def __str__(self):
         return "State: name = %s, enter = %s, exit = %s, trans = %s, children = %s" %\
         return "State: name = %s, enter = %s, exit = %s, trans = %s, children = %s" %\
                (self.__name, self.__enterFunc, self.__exitFunc, self.__transitions, self.__FSMList)
                (self.__name, self.__enterFunc, self.__exitFunc, self.__transitions, self.__FSMList)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

+ 16 - 0
direct/src/gui/DirectGuiGlobals.py

@@ -128,6 +128,8 @@ def getDefaultFont():
     return defaultFont
     return defaultFont
 
 
 def setDefaultFont(newFont):
 def setDefaultFont(newFont):
+    """Changes the default font for DirectGUI items.  To change the default
+    font across the board, see :meth:`.TextNode.setDefaultFont`. """
     global defaultFont
     global defaultFont
     defaultFont = newFont
     defaultFont = newFont
 
 
@@ -161,3 +163,17 @@ def getDefaultPanel():
 def setDefaultPanel(newPanel):
 def setDefaultPanel(newPanel):
     global panel
     global panel
     panel = newPanel
     panel = newPanel
+
+get_default_rollover_sound = getDefaultRolloverSound
+set_default_rollover_sound = setDefaultRolloverSound
+get_default_click_sound = getDefaultClickSound
+set_default_click_sound = setDefaultClickSound
+get_default_font = getDefaultFont
+set_default_font = setDefaultFont
+get_default_dialog_geom = getDefaultDialogGeom
+get_default_dialog_relief = getDefaultDialogRelief
+set_default_dialog_geom = setDefaultDialogGeom
+get_default_draw_order = getDefaultDrawOrder
+set_default_draw_order = setDefaultDrawOrder
+get_default_panel = getDefaultPanel
+set_default_panel = setDefaultPanel

+ 1 - 2
direct/src/interval/FunctionInterval.py

@@ -37,8 +37,7 @@ class FunctionInterval(Interval.Interval):
                     if ival.function.__func__ == oldFunction:
                     if ival.function.__func__ == oldFunction:
                         # print 'found: ', ival.function, oldFunction
                         # print 'found: ', ival.function, oldFunction
                         ival.function = types.MethodType(newFunction,
                         ival.function = types.MethodType(newFunction,
-                                                         ival.function.__self__,
-                                                         ival.function.__self__.__class__)
+                                                         ival.function.__self__)
                         count += 1
                         count += 1
             return count
             return count
 
 

+ 5 - 5
direct/src/showbase/DirectObject.py

@@ -94,12 +94,12 @@ class DirectObject:
         if hasattr(self, '_taskList'):
         if hasattr(self, '_taskList'):
             tasks = [task.name for task in self._taskList.values()]
             tasks = [task.name for task in self._taskList.values()]
         if len(events) or len(tasks):
         if len(events) or len(tasks):
-            estr = choice(len(events), 'listening to events: %s' % events, '')
-            andStr = choice(len(events) and len(tasks), ' and ', '')
-            tstr = choice(len(tasks), '%srunning tasks: %s' % (andStr, tasks), '')
+            estr = ('listening to events: %s' % events if len(events) else '')
+            andStr = (' and ' if len(events) and len(tasks) else '')
+            tstr = ('%srunning tasks: %s' % (andStr, tasks) if len(tasks) else '')
             notify = directNotify.newCategory('LeakDetect')
             notify = directNotify.newCategory('LeakDetect')
-            func = choice(getRepository()._crashOnProactiveLeakDetect,
-                          self.notify.error, self.notify.warning)
+            crash = getattr(getRepository(), '_crashOnProactiveLeakDetect', False)
+            func = (self.notify.error if crash else self.notify.warning)
             func('destroyed %s instance is still %s%s' % (self.__class__.__name__, estr, tstr))
             func('destroyed %s instance is still %s%s' % (self.__class__.__name__, estr, tstr))
 
 
     #snake_case alias:
     #snake_case alias:

+ 9 - 9
direct/src/showbase/Loader.py

@@ -24,14 +24,14 @@ class Loader(DirectObject):
 
 
     _loadedPythonFileTypes = False
     _loadedPythonFileTypes = False
 
 
-    class Callback:
+    class _Callback:
         """Returned by loadModel when used asynchronously.  This class is
         """Returned by loadModel when used asynchronously.  This class is
         modelled after Future, and can be awaited."""
         modelled after Future, and can be awaited."""
 
 
         # This indicates that this class behaves like a Future.
         # This indicates that this class behaves like a Future.
         _asyncio_future_blocking = False
         _asyncio_future_blocking = False
 
 
-        class ResultAwaiter(object):
+        class _ResultAwaiter(object):
             """Reinvents generators because of PEP 479, sigh.  See #513."""
             """Reinvents generators because of PEP 479, sigh.  See #513."""
 
 
             __slots__ = 'requestList', 'index'
             __slots__ = 'requestList', 'index'
@@ -126,9 +126,9 @@ class Loader(DirectObject):
                 self._asyncio_future_blocking = True
                 self._asyncio_future_blocking = True
 
 
             if self.gotList:
             if self.gotList:
-                return self.ResultAwaiter([self])
+                return self._ResultAwaiter([self])
             else:
             else:
-                return self.ResultAwaiter(self.requestList)
+                return self._ResultAwaiter(self.requestList)
 
 
         def __aiter__(self):
         def __aiter__(self):
             """ This allows using `async for` to iterate asynchronously over
             """ This allows using `async for` to iterate asynchronously over
@@ -138,7 +138,7 @@ class Loader(DirectObject):
             requestList = self.requestList
             requestList = self.requestList
             assert requestList is not None, "Request was cancelled."
             assert requestList is not None, "Request was cancelled."
 
 
-            return self.ResultAwaiter(requestList)
+            return self._ResultAwaiter(requestList)
 
 
     # special methods
     # special methods
     def __init__(self, base):
     def __init__(self, base):
@@ -308,7 +308,7 @@ class Loader(DirectObject):
             # requested models have been loaded, we'll invoke the
             # requested models have been loaded, we'll invoke the
             # callback (passing it the models on the parameter list).
             # callback (passing it the models on the parameter list).
 
 
-            cb = Loader.Callback(self, len(modelList), gotList, callback, extraArgs)
+            cb = Loader._Callback(self, len(modelList), gotList, callback, extraArgs)
             i = 0
             i = 0
             for modelPath in modelList:
             for modelPath in modelList:
                 request = self.loader.makeAsyncRequest(Filename(modelPath), loaderOptions)
                 request = self.loader.makeAsyncRequest(Filename(modelPath), loaderOptions)
@@ -476,7 +476,7 @@ class Loader(DirectObject):
             # requested models have been saved, we'll invoke the
             # requested models have been saved, we'll invoke the
             # callback (passing it the models on the parameter list).
             # callback (passing it the models on the parameter list).
 
 
-            cb = Loader.Callback(self, len(modelList), gotList, callback, extraArgs)
+            cb = Loader._Callback(self, len(modelList), gotList, callback, extraArgs)
             i = 0
             i = 0
             for modelPath, node in modelList:
             for modelPath, node in modelList:
                 request = self.loader.makeAsyncSaveRequest(Filename(modelPath), loaderOptions, node)
                 request = self.loader.makeAsyncSaveRequest(Filename(modelPath), loaderOptions, node)
@@ -1013,7 +1013,7 @@ class Loader(DirectObject):
             # requested sounds have been loaded, we'll invoke the
             # requested sounds have been loaded, we'll invoke the
             # callback (passing it the sounds on the parameter list).
             # callback (passing it the sounds on the parameter list).
 
 
-            cb = Loader.Callback(self, len(soundList), gotList, callback, extraArgs)
+            cb = Loader._Callback(self, len(soundList), gotList, callback, extraArgs)
             for i, soundPath in enumerate(soundList):
             for i, soundPath in enumerate(soundList):
                 request = AudioLoadRequest(manager, soundPath, positional)
                 request = AudioLoadRequest(manager, soundPath, positional)
                 request.setDoneEvent(self.hook)
                 request.setDoneEvent(self.hook)
@@ -1078,7 +1078,7 @@ class Loader(DirectObject):
             callback = self.__asyncFlattenDone
             callback = self.__asyncFlattenDone
             gotList = True
             gotList = True
 
 
-        cb = Loader.Callback(self, len(modelList), gotList, callback, extraArgs)
+        cb = Loader._Callback(self, len(modelList), gotList, callback, extraArgs)
         i = 0
         i = 0
         for model in modelList:
         for model in modelList:
             request = ModelFlattenRequest(model.node())
             request = ModelFlattenRequest(model.node())

+ 2 - 3
direct/src/showbase/Messenger.py

@@ -1,5 +1,5 @@
 """This defines the Messenger class, which is responsible for most of the
 """This defines the Messenger class, which is responsible for most of the
-event handling that happens on the Python side.
+:ref:`event handling <event-handlers>` that happens on the Python side.
 """
 """
 
 
 __all__ = ['Messenger']
 __all__ = ['Messenger']
@@ -464,8 +464,7 @@ class Messenger:
                 #       'oldMethod: ' + repr(oldMethod) + '\n' +
                 #       'oldMethod: ' + repr(oldMethod) + '\n' +
                 #       'newFunction: ' + repr(newFunction) + '\n')
                 #       'newFunction: ' + repr(newFunction) + '\n')
                 if (function == oldMethod):
                 if (function == oldMethod):
-                    newMethod = types.MethodType(
-                        newFunction, method.__self__, method.__self__.__class__)
+                    newMethod = types.MethodType(newFunction, method.__self__)
                     params[0] = newMethod
                     params[0] = newMethod
                     # Found it retrun true
                     # Found it retrun true
                     retFlag += 1
                     retFlag += 1

+ 3 - 3
direct/src/showbase/OnScreenDebug.py

@@ -38,9 +38,9 @@ class OnScreenDebug:
             print("failed to load OnScreenDebug font %s" % fontPath)
             print("failed to load OnScreenDebug font %s" % fontPath)
             font = TextNode.getDefaultFont()
             font = TextNode.getDefaultFont()
         self.onScreenText = OnscreenText.OnscreenText(
         self.onScreenText = OnscreenText.OnscreenText(
-                pos = (-1.0, 0.9), fg=fgColor, bg=bgColor,
-                scale = (fontScale, fontScale, 0.0), align = TextNode.ALeft,
-                mayChange = 1, font = font)
+                parent = base.a2dTopLeft, pos = (0.0, -0.1),
+                fg=fgColor, bg=bgColor, scale = (fontScale, fontScale, 0.0),
+                align = TextNode.ALeft, mayChange = 1, font = font)
         # Make sure readout is never lit or drawn in wireframe
         # Make sure readout is never lit or drawn in wireframe
         DirectUtil.useDirectRenderStyle(self.onScreenText)
         DirectUtil.useDirectRenderStyle(self.onScreenText)
 
 

+ 0 - 1
direct/src/showbase/ProfileSession.py

@@ -1,4 +1,3 @@
-from __future__ import print_function
 from panda3d.core import TrueClock
 from panda3d.core import TrueClock
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.showbase.PythonUtil import (
 from direct.showbase.PythonUtil import (

+ 4 - 3
direct/src/showbase/PythonUtil.py

@@ -39,6 +39,7 @@ import random
 import time
 import time
 import builtins
 import builtins
 import importlib
 import importlib
+import functools
 
 
 __report_indent = 3
 __report_indent = 3
 
 
@@ -1560,7 +1561,7 @@ def appendStr(obj, st):
             return s
             return s
         oldStr = Functor(stringer, str(obj))
         oldStr = Functor(stringer, str(obj))
         stringer = None
         stringer = None
-    obj.__str__ = types.MethodType(Functor(appendedStr, oldStr, st), obj, obj.__class__)
+    obj.__str__ = types.MethodType(Functor(appendedStr, oldStr, st), obj)
     appendedStr = None
     appendedStr = None
     return obj
     return obj
 
 
@@ -2062,7 +2063,7 @@ def report(types = [], prefix = '', xform = None, notifyFunc = None, dConfigPara
             if not rArgs:
             if not rArgs:
                 rArgs = '()'
                 rArgs = '()'
             else:
             else:
-                rArgs = '(' + reduce(str.__add__,rArgs)[:-2] + ')'
+                rArgs = '(' + functools.reduce(str.__add__,rArgs)[:-2] + ')'
 
 
 
 
             outStr = '%s%s' % (f.__name__, rArgs)
             outStr = '%s%s' % (f.__name__, rArgs)
@@ -2345,7 +2346,7 @@ class MiniLog:
         if not rArgs:
         if not rArgs:
             rArgs = '()'
             rArgs = '()'
         else:
         else:
-            rArgs = '(' + reduce(str.__add__,rArgs)[:-2] + ')'
+            rArgs = '(' + functools.reduce(str.__add__,rArgs)[:-2] + ')'
 
 
         line = '%s%s' % (funcName, rArgs)
         line = '%s%s' % (funcName, rArgs)
         self.appendFunctionCall(line)
         self.appendFunctionCall(line)

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 277 - 141
direct/src/showbase/ShowBase.py


+ 10 - 5
direct/src/showbase/ShowBaseGlobal.py

@@ -2,9 +2,14 @@
 :class:`~.ShowBase.ShowBase` instance, as an alternative to using the builtin
 :class:`~.ShowBase.ShowBase` instance, as an alternative to using the builtin
 scope.
 scope.
 
 
-Note that you cannot directly import `base` from this module since ShowBase
-may not have been created yet; instead, ShowBase dynamically adds itself to
-this module's scope when instantiated."""
+Many of the variables contained in this module are also automatically written
+to the :mod:`builtins` module when ShowBase is instantiated, making them
+available to any Python code.  Importing them from this module instead can make
+it easier to see where these variables are coming from.
+
+Note that you cannot directly import :data:`~builtins.base` from this module
+since ShowBase may not have been created yet; instead, ShowBase dynamically
+adds itself to this module's scope when instantiated."""
 
 
 __all__ = []
 __all__ = []
 
 
@@ -17,8 +22,8 @@ from . import DConfig as config
 
 
 __dev__ = config.GetBool('want-dev', __debug__)
 __dev__ = config.GetBool('want-dev', __debug__)
 
 
-#: The global instance of the :class:`~panda3d.core.VirtualFileSystem`, as
-#: obtained using :meth:`panda3d.core.VirtualFileSystem.getGlobalPtr()`.
+#: The global instance of the :ref:`virtual-file-system`, as obtained using
+#: :meth:`panda3d.core.VirtualFileSystem.getGlobalPtr()`.
 vfs = VirtualFileSystem.getGlobalPtr()
 vfs = VirtualFileSystem.getGlobalPtr()
 
 
 #: The default Panda3D output stream for notifications and logging, as
 #: The default Panda3D output stream for notifications and logging, as

+ 3 - 0
direct/src/showbase/__init__.py

@@ -0,0 +1,3 @@
+""" This package contains `.ShowBase`, an application framework responsible
+for opening a graphical display, setting up input devices and creating
+the scene graph. """

+ 6 - 3
direct/src/showutil/TexMemWatcher.py

@@ -327,7 +327,10 @@ class TexMemWatcher(DirectObject):
 
 
         if self.dynamicLimit:
         if self.dynamicLimit:
             # Choose a suitable limit by rounding to the next power of two.
             # Choose a suitable limit by rounding to the next power of two.
-            self.limit = Texture.upToPower2(self.totalSize)
+            limit = 1
+            while limit < self.totalSize:
+                limit *= 2
+            self.limit = limit
 
 
         # Set our GSG to limit itself to no more textures than we
         # Set our GSG to limit itself to no more textures than we
         # expect to display onscreen, so we don't go crazy with
         # expect to display onscreen, so we don't go crazy with
@@ -883,7 +886,7 @@ class TexMemWatcher(DirectObject):
             matches.append((match, tp))
             matches.append((match, tp))
 
 
         if matches:
         if matches:
-            return max(matches)[1]
+            return max(matches, key=lambda match: match[0])[1]
         return None
         return None
 
 
     def findHolePieces(self, area):
     def findHolePieces(self, area):
@@ -937,7 +940,7 @@ class TexMemWatcher(DirectObject):
     def findLargestHole(self):
     def findLargestHole(self):
         holes = self.findAvailableHoles(0)
         holes = self.findAvailableHoles(0)
         if holes:
         if holes:
-            return max(holes)[1]
+            return max(holes, key=lambda hole: hole[0])[1]
         return None
         return None
 
 
     def findAvailableHoles(self, area, w = None, h = None):
     def findAvailableHoles(self, area, w = None, h = None):

+ 2 - 1
direct/src/stdpy/__init__.py

@@ -1,5 +1,6 @@
 """
 """
 This package contains various modules that provide a drop-in substitute
 This package contains various modules that provide a drop-in substitute
 for some of the built-in Python modules.  These substitutes make better
 for some of the built-in Python modules.  These substitutes make better
-use of Panda3D's virtual file system and threading system.
+use of Panda3D's :ref:`Virtual File System <virtual-file-system>` and
+:ref:`threading` system.
 """
 """

+ 1 - 3
direct/src/task/Task.py

@@ -593,9 +593,7 @@ class TaskManager:
         else:
         else:
             function = method
             function = method
         if (function == oldMethod):
         if (function == oldMethod):
-            newMethod = types.MethodType(newFunction,
-                                         method.__self__,
-                                         method.__self__.__class__)
+            newMethod = types.MethodType(newFunction, method.__self__)
             task.setFunction(newMethod)
             task.setFunction(newMethod)
             # Found a match
             # Found a match
             return 1
             return 1

+ 14 - 8
direct/src/tkpanels/Inspector.py

@@ -1,8 +1,15 @@
 """Inspectors allow you to visually browse through the members of
 """Inspectors allow you to visually browse through the members of
-various python objects.  To open an inspector, import this module, and
-execute inspector.inspect(anObject) I start IDLE with this command
-line: idle.py -c "from inspector import inspect"
-so that I can just type: inspect(anObject) any time."""
+various Python objects.  To open an inspector, import this module, and
+execute ``inspector.inspect(anObject)``.
+
+I start IDLE with this command line::
+
+   idle.py -c "from inspector import inspect"
+
+so that I can just type: ``inspect(anObject)`` any time.
+
+See :ref:`inspection-utilities` for more information.
+"""
 
 
 
 
 __all__ = ['inspect', 'inspectorFor', 'Inspector', 'ModuleInspector', 'ClassInspector', 'InstanceInspector', 'FunctionInspector', 'InstanceMethodInspector', 'CodeInspector', 'ComplexInspector', 'DictionaryInspector', 'SequenceInspector', 'SliceInspector', 'InspectorWindow']
 __all__ = ['inspect', 'inspectorFor', 'Inspector', 'ModuleInspector', 'ClassInspector', 'InstanceInspector', 'FunctionInspector', 'InstanceMethodInspector', 'CodeInspector', 'ComplexInspector', 'DictionaryInspector', 'SequenceInspector', 'SliceInspector', 'InspectorWindow']
@@ -13,6 +20,9 @@ import Pmw
 ### public API
 ### public API
 
 
 def inspect(anObject):
 def inspect(anObject):
+    """Opens up a window for visually inspecting the details of a given Python
+    object.  See :ref:`inspection-utilities`.
+    """
     inspector = inspectorFor(anObject)
     inspector = inspectorFor(anObject)
     inspectorWindow = InspectorWindow(inspector)
     inspectorWindow = InspectorWindow(inspector)
     inspectorWindow.open()
     inspectorWindow.open()
@@ -437,7 +447,3 @@ class InspectorWindow:
                 label = item,
                 label = item,
                 command = lambda p = part, f = func: f(p))
                 command = lambda p = part, f = func: f(p))
         return popupMenu
         return popupMenu
-
-
-
-

+ 71 - 0
doc/ReleaseNotes

@@ -1,3 +1,74 @@
+------------------------  RELEASE 1.10.7  -----------------------
+
+This is primarily a bugfix release, but includes a few new features as well.
+
+Rendering
+* Add High Dynamic Range filter with ACES tone mapping to CommonFilters
+* Add sRGB filter to CommonFilters (to be used as fallback to framebuffer-srgb)
+* Fix (shadow) buffer no longer working after host buffer is destroyed (#890)
+* Fix rare bug with shader parameters not being set right across render passes
+* Fog density passed to shader now defaults to 0 when no fog is applied
+* Don't check sampler/light type mismatch for non-shadow-casting lights (#942)
+* Shader generator now makes use of Material alpha values if present (#912)
+* Support sRGB textures and framebuffers in OpenGL ES 2 renderer
+
+Asset Loading
+* Egg files can now be loaded with sRGB texture formats automatically
+* Fix maya2egg regression not creating animations properly (#1004)
+* Fix FMOD issue reading sounds from read-write-opened multifiles (#1002)
+
+Stability
+* Fix faulty collision detection when sphere is under polygon (#907)
+* Fix PStats misreporting an exploding number of RenderState/TransformState
+* Fix memory leak when removing a task that is awaiting a non-Panda future
+* Optimize RenderState cache for case where texture is replaced repeatedly
+* PNMImage add_sub_image() / mult_sub_image() now properly adds offset (#903)
+* Fix some ServerRepository issues in Python 3
+* Fix has_tags() still returning true after clearing all Python tags (#936)
+* Fix crash in BitArray.has_any_of()
+* Fix errors in PythonUtil.detectLeaks() and PythonUtil.report()
+* Fix runtime error during ControlManager deletion (#884)
+* Some error messages in nativenet are changed to debug messages
+* Fix TexMemWatcher crash when graphics memory reaches 1 GB (#975)
+* Fix a Triangulator crash dealing with certain invalid polygons (#985)
+* Fix in MultiplexStreamBuf::Output::write_string() (#902)
+* Fix a buffer overrun on FreeBSD when extracting very long command-line args
+
+Input and Windowing
+* M_confined mouse mode on Windows now confines mouse to client rectangle
+* Fix incorrect handling of shift modifier on macOS (#959)
+* Fix erroneous dpad_*-up events when emulating a dpad on Linux (#973)
+* Fix tab handling in DirectEntry with certain versions of Windows CRT (#994)
+* Fix parented window receiving WS_POPUP style on Windows (#915)
+
+Deployment
+* macOS app bundle now performs chdir into Resources folder upon launch
+* No longer defaults to FMOD audio on macOS unless FMOD is explicitly bundled
+* Improvements to Config.prc handling (strip comments, sort files, etc.)
+* Line buffering is now used on Windows when writing to log files (#947)
+* stdout/stderr output streams are now flushed on exit (#946)
+* Build paths are now properly stripped from compiled Python code (#991)
+* Update to support a change in location of numpy/Pillow libraries (#914)
+* Fix libffi-7.dll not being included in official wheels
+* PYTHONINSPECT mechanism is no longer enabled when building with optimizations
+* A few unnecessary warning messages are squelched
+* Windows builds now include previously missing CRT dlls
+
+API
+* Add pickle support to Datagram class
+* Unexpose a crashing CollisionPolygon constructor and method (#908)
+* FilterManager has new parameter to control framebuffer clamping
+* Add snake_case aliases for functions in DirectGuiGlobals
+* Global delete operator is now safe to call with a null pointer
+* Improvements to API reference documentation
+
+Build
+* Fix issues building with development versions Python 3.9 and 3.10
+* Fix an ABI incompatibility issue with MouseWatcher in NDEBUG builds
+* Fix incorrect NaN/inf detection in double-precision release builds (#987)
+* interrogate C++ parser supports arbitrary constant expressions in bitfields
+* interrogate C++ parser supports sizeof with constant expression
+
 ------------------------  RELEASE 1.10.6  -----------------------
 ------------------------  RELEASE 1.10.6  -----------------------
 
 
 This is a recommended bugfix release that adds additional stability fixes.
 This is a recommended bugfix release that adds additional stability fixes.

+ 57 - 63
dtool/Config.cmake

@@ -33,8 +33,6 @@ if(IS_MULTICONFIG)
   set(CMAKE_CONFIGURATION_TYPES ${_configs})
   set(CMAKE_CONFIGURATION_TYPES ${_configs})
 endif()
 endif()
 
 
-set(PER_CONFIG_OPTIONS)
-
 # Are we building with static or dynamic linking?
 # Are we building with static or dynamic linking?
 option(BUILD_SHARED_LIBS
 option(BUILD_SHARED_LIBS
   "Causes subpackages to be built separately -- setup for dynamic linking.
   "Causes subpackages to be built separately -- setup for dynamic linking.
@@ -145,7 +143,7 @@ identified by PRC_ENCRYPTED_PATTERNS.")
 # that case, config will execute the file if it appears to be
 # that case, config will execute the file if it appears to be
 # executable; otherwise, it will simply read it.
 # executable; otherwise, it will simply read it.
 
 
-set(PRC_EXECUTABLE_PATTERNS "" CACHE STRING 
+set(PRC_EXECUTABLE_PATTERNS "" CACHE STRING
   "The filename(s) to search for, and execute, in the above paths.
   "The filename(s) to search for, and execute, in the above paths.
 Normally this is empty.")
 Normally this is empty.")
 
 
@@ -204,10 +202,9 @@ set(PRC_INC_TRUST_LEVEL "0" CACHE STRING
 # Similarly, the descriptions are normally saved only in a
 # Similarly, the descriptions are normally saved only in a
 # development build, not in a release build.  Set this value true to
 # development build, not in a release build.  Set this value true to
 # explicitly save them anyway.
 # explicitly save them anyway.
-#XXX only for release-release builds
-option(PRC_SAVE_DESCRIPTIONS
+per_config_option(PRC_SAVE_DESCRIPTIONS
   "Define if you want to save the descriptions for ConfigVariables."
   "Define if you want to save the descriptions for ConfigVariables."
-  ON)
+  Debug Standard)
 
 
 mark_as_advanced(DEFAULT_PRC_DIR PRC_DIR_ENVVARS PRC_PATH_ENVVARS
 mark_as_advanced(DEFAULT_PRC_DIR PRC_DIR_ENVVARS PRC_PATH_ENVVARS
   PRC_PATTERNS PRC_ENCRYPTED_PATTERNS PRC_ENCRYPTION_KEY
   PRC_PATTERNS PRC_ENCRYPTED_PATTERNS PRC_ENCRYPTION_KEY
@@ -254,49 +251,46 @@ debugging information." OFF)
 mark_as_advanced(INTERROGATE_OPTIONS)
 mark_as_advanced(INTERROGATE_OPTIONS)
 
 
 #
 #
-# The following options have to do with the memory allocation system
-# that will be used by Panda3D.
+# The following options have to do with optional debugging features.
 #
 #
 
 
-option(DO_MEMORY_USAGE
+per_config_option(DO_MEMORY_USAGE
   "Do you want to compile in support for tracking memory usage?  This
   "Do you want to compile in support for tracking memory usage?  This
 enables you to define the variable 'track-memory-usage' at runtime
 enables you to define the variable 'track-memory-usage' at runtime
 to help track memory leaks, and also report total memory usage on
 to help track memory leaks, and also report total memory usage on
 PStats.  There is some small overhead for having this ability
 PStats.  There is some small overhead for having this ability
-available, even if it is unused." OFF)
-list(APPEND PER_CONFIG_OPTIONS DO_MEMORY_USAGE)
-set(DO_MEMORY_USAGE_Debug ON CACHE BOOL "")
+available, even if it is unused." Debug Standard)
+
+per_config_option(DO_COLLISION_RECORDING
+  "Do you want to enable debugging features for the collision system?"
+  Debug Standard)
+
+per_config_option(DO_PSTATS
+  "Enable support for performance profiling using PStats?"
+  Debug Standard)
 
 
-option(SIMULATE_NETWORK_DELAY
+per_config_option(DO_DCAST
+  "Add safe typecast checking?  This adds significant overhead."
+  Debug Standard)
+
+per_config_option(SIMULATE_NETWORK_DELAY
   "This option compiles in support for simulating network delay via
   "This option compiles in support for simulating network delay via
 the min-lag and max-lag prc variables.  It adds a tiny bit of
 the min-lag and max-lag prc variables.  It adds a tiny bit of
 overhead even when it is not activated, so it is typically enabled
 overhead even when it is not activated, so it is typically enabled
-only in a development build." OFF)
-list(APPEND PER_CONFIG_OPTIONS SIMULATE_NETWORK_DELAY)
-set(SIMULATE_NETWORK_DELAY_Debug ON CACHE BOOL "")
+only in a development build."
+  Debug)
 
 
-option(SUPPORT_IMMEDIATE_MODE
-  "This option compiles in support for immediate-mode OpenGL
-rendering.  Since this is normally useful only for researching
-buggy drivers, and since there is a tiny bit of per-primitive
-overhead to have this option available even if it is unused, it is
-by default enabled only in a development build.  This has no effect
-on DirectX rendering." OFF)
-list(APPEND PER_CONFIG_OPTIONS SUPPORT_IMMEDIATE_MODE)
-set(SUPPORT_IMMEDIATE_MODE_Debug ON CACHE BOOL "")
-
-option(NOTIFY_DEBUG
+per_config_option(NOTIFY_DEBUG
   "Do you want to include the 'debug' and 'spam' Notify messages?
   "Do you want to include the 'debug' and 'spam' Notify messages?
 Normally, these are stripped out when we build for release, but sometimes it's
 Normally, these are stripped out when we build for release, but sometimes it's
-useful to keep them around. Turn this setting on to achieve that." OFF)
-list(APPEND PER_CONFIG_OPTIONS NOTIFY_DEBUG)
-set(NOTIFY_DEBUG_Debug ON CACHE BOOL "")
-set(NOTIFY_DEBUG_Standard ON CACHE BOOL "")
+useful to keep them around. Turn this setting on to achieve that."
+  Debug Standard)
 
 
-option(SUPPORT_FIXED_FUNCTION
-  "This option compiles in support for the fixed-function OpenGL
-pipeline.  It is only really useful to turn this off if you are targeting
-an OpenGL ES 2 system." ON)
+mark_as_advanced(SIMULATE_NETWORK_DELAY DO_MEMORY_USAGE DO_DCAST)
+
+#
+# The following options have to do with the memory allocation system.
+#
 
 
 option(USE_MEMORY_DLMALLOC
 option(USE_MEMORY_DLMALLOC
   "This is an optional alternative memory-allocation scheme
   "This is an optional alternative memory-allocation scheme
@@ -324,8 +318,7 @@ calls to malloc() and free() for frequently-created and -deleted
 objects.  There's usually no reason to set this false, unless you
 objects.  There's usually no reason to set this false, unless you
 suspect a bug in Panda's memory management code." ON)
 suspect a bug in Panda's memory management code." ON)
 
 
-mark_as_advanced(DO_MEMORY_USAGE SIMULATE_NETWORK_DELAY
-  SUPPORT_IMMEDIATE_MODE USE_MEMORY_DLMALLOC USE_MEMORY_PTMALLOC2
+mark_as_advanced(USE_MEMORY_DLMALLOC USE_MEMORY_PTMALLOC2
   MEMORY_HOOK_DO_ALIGN USE_DELETED_CHAIN)
   MEMORY_HOOK_DO_ALIGN USE_DELETED_CHAIN)
 
 
 
 
@@ -379,11 +372,11 @@ mark_as_advanced(ANDROID_NDK_HOME ANDROID_ABI ANDROID_STL
 
 
 # By default, we'll assume the user only wants to run with Debug
 # By default, we'll assume the user only wants to run with Debug
 # python if he has to--that is, on Windows when building a debug build.
 # python if he has to--that is, on Windows when building a debug build.
-set(USE_DEBUG_PYTHON OFF)
 if(WIN32)
 if(WIN32)
-  set(USE_DEBUG_PYTHON_Debug ON)
+  per_config_option(USE_DEBUG_PYTHON "" Debug)
+else()
+  option(USE_DEBUG_PYTHON "" OFF)
 endif()
 endif()
-list(APPEND PER_CONFIG_OPTIONS USE_DEBUG_PYTHON)
 
 
 cmake_dependent_option(HAVE_VIDEO4LINUX
 cmake_dependent_option(HAVE_VIDEO4LINUX
   "Set this to enable webcam support on Linux." ON
   "Set this to enable webcam support on Linux." ON
@@ -405,15 +398,27 @@ version and below, which may reduce runtime portability to other
 systems, but it will avoid issues with getting extension function
 systems, but it will avoid issues with getting extension function
 pointers.")
 pointers.")
 
 
+option(SUPPORT_FIXED_FUNCTION
+  "This option compiles in support for the fixed-function OpenGL pipeline.
+It is only really useful to turn this off to save space if you are building
+an application that only needs to use an OpenGL 3.2+ context and only uses
+custom GLSL shaders." ON)
+
+option(SUPPORT_IMMEDIATE_MODE
+  "This option compiles in support for immediate-mode OpenGL
+rendering.  Since this is normally useful only for researching
+buggy drivers, and since there is a tiny bit of per-primitive
+overhead to have this option available even if it is unused, it is
+by default enabled only in a development build.  This has no effect
+on DirectX rendering." OFF)
+
+mark_as_advanced(SUPPORT_FIXED_FUNCTION)
 
 
 # Should build tinydisplay?
 # Should build tinydisplay?
 #option(HAVE_TINYDISPLAY
 #option(HAVE_TINYDISPLAY
 #  "Builds TinyDisplay, a light software renderer based on TinyGL,
 #  "Builds TinyDisplay, a light software renderer based on TinyGL,
 #that is built into Panda. TinyDisplay is not as full-featured as Mesa
 #that is built into Panda. TinyDisplay is not as full-featured as Mesa
 #but is many times faster." ON)
 #but is many times faster." ON)
-#option(HAVE_TINYDISPLAY_MinSizeRel "" OFF)
-#list(APPEND PER_CONFIG_OPTIONS HAVE_TINYDISPLAY)
-
 
 
 # Is SDL installed, and where?
 # Is SDL installed, and where?
 set(Threads_FIND_QUIETLY TRUE) # Fix for builtin FindSDL
 set(Threads_FIND_QUIETLY TRUE) # Fix for builtin FindSDL
@@ -477,9 +482,6 @@ build (such as, for instance, for the iPhone)." ON)
 option(HAVE_AUDIO
 option(HAVE_AUDIO
   "Do you want to build the audio interface?" ON)
   "Do you want to build the audio interface?" ON)
 
 
-option(DO_PSTATS
-  "Enable the pstats client?" ON)
-
 option(USE_PANDAFILESTREAM
 option(USE_PANDAFILESTREAM
   "Enable the PandaFileStream implementation of pfstream etc.?" ON)
   "Enable the PandaFileStream implementation of pfstream etc.?" ON)
 
 
@@ -492,16 +494,12 @@ option(HAVE_IMG "Enable support for loading IMG images." ON)
 option(HAVE_SOFTIMAGE_PIC "Enable support for loading SOFTIMAGE PIC images." ON)
 option(HAVE_SOFTIMAGE_PIC "Enable support for loading SOFTIMAGE PIC images." ON)
 option(HAVE_BMP "Enable support for loading BMP images." ON)
 option(HAVE_BMP "Enable support for loading BMP images." ON)
 option(HAVE_PNM "Enable support for loading PNM images." ON)
 option(HAVE_PNM "Enable support for loading PNM images." ON)
-
-foreach(adv_image_format
-  HAVE_SGI_RGB HAVE_TGA HAVE_IMG HAVE_SOFTIMAGE_PIC HAVE_BMP HAVE_PNM)
-
-  option(${adv_image_format}_MinSizeRel "" OFF)
-  list(APPEND PER_CONFIG_OPTIONS ${adv_image_format})
-
-  mark_as_advanced(${adv_image_format} ${adv_image_format}_MinSizeRel)
-
-endforeach(adv_image_format)
+option(HAVE_SGI_RGB "" ON)
+option(HAVE_TGA "" ON)
+option(HAVE_IMG "" ON)
+option(HAVE_SOFTIMAGE_PIC "" ON)
+option(HAVE_BMP "" ON)
+option(HAVE_PNM "" ON)
 
 
 # How to invoke bison and flex.  Panda takes advantage of some
 # How to invoke bison and flex.  Panda takes advantage of some
 # bison/flex features, and therefore specifically requires bison and
 # bison/flex features, and therefore specifically requires bison and
@@ -539,9 +537,9 @@ slightly slow down Panda for the single CPU case."
   IMPORTED_AS Threads::Threads)
   IMPORTED_AS Threads::Threads)
 
 
 # Configure debug threads
 # Configure debug threads
-option(DEBUG_THREADS "If on, enables debugging of thread and sync operations (i.e. mutexes, deadlocks)" OFF)
-list(APPEND PER_CONFIG_OPTIONS DEBUG_THREADS)
-set(DEBUG_THREADS_Debug ON CACHE BOOL "")
+option(DEBUG_THREADS
+  "If on, enables debugging of thread and sync operations (i.e. mutexes,
+deadlocks).  Very slow, disabled by default." OFF)
 
 
 option(SIMPLE_THREADS
 option(SIMPLE_THREADS
   "If on, compile with simulated threads.  Threads, by default, use
   "If on, compile with simulated threads.  Threads, by default, use
@@ -551,7 +549,6 @@ On the other hand, compiling in this full OS-provided support can
 impose some substantial runtime overhead, making the application
 impose some substantial runtime overhead, making the application
 run slower on a single-CPU machine. This settings avoid the overhead,
 run slower on a single-CPU machine. This settings avoid the overhead,
 but still gain some of the basic functionality of threads." OFF)
 but still gain some of the basic functionality of threads." OFF)
-list(APPEND PER_CONFIG_OPTIONS SIMPLE_THREADS)
 
 
 option(OS_SIMPLE_THREADS
 option(OS_SIMPLE_THREADS
   "If on, OS threading constructs will be used to perform context switches.
   "If on, OS threading constructs will be used to perform context switches.
@@ -560,7 +557,6 @@ normal SIMPLE_THREADS optimizations still apply, and the normal
 SIMPLE_THREADS scheduler is used to switch between threads (instead
 SIMPLE_THREADS scheduler is used to switch between threads (instead
 of the OS scheduler).  This may be more portable and more reliable,
 of the OS scheduler).  This may be more portable and more reliable,
 but it is a hybrid between user-space threads and os-provided threads." ON)
 but it is a hybrid between user-space threads and os-provided threads." ON)
-list(APPEND PER_CONFIG_OPTIONS OS_SIMPLE_THREADS)
 
 
 ### Configure pipelining ###
 ### Configure pipelining ###
 option(DO_PIPELINING "If on, compile with pipelined rendering." ON)
 option(DO_PIPELINING "If on, compile with pipelined rendering." ON)
@@ -570,8 +566,6 @@ option(COMPILE_IN_DEFAULT_FONT
   "If on, compiles in a default font, so that every TextNode will always
   "If on, compiles in a default font, so that every TextNode will always
 have a font available without requiring the user to specify one.
 have a font available without requiring the user to specify one.
 When turned off, the generated library will save a few kilobytes." ON)
 When turned off, the generated library will save a few kilobytes." ON)
-list(APPEND PER_CONFIG_OPTIONS COMPILE_IN_DEFAULT_FONT)
-set(COMPILE_IN_DEFAULT_FONT_MinSizeRel OFF CACHE BOOL "")
 
 
 option(STDFLOAT_DOUBLE
 option(STDFLOAT_DOUBLE
   "Define this true to compile a special version of Panda to use a
   "Define this true to compile a special version of Panda to use a

+ 7 - 4
dtool/LocalSetup.cmake

@@ -186,11 +186,14 @@ message("")
 # Generate dtool_config.h
 # Generate dtool_config.h
 if(IS_MULTICONFIG)
 if(IS_MULTICONFIG)
   foreach(config ${CMAKE_CONFIGURATION_TYPES})
   foreach(config ${CMAKE_CONFIGURATION_TYPES})
-    foreach(option ${PER_CONFIG_OPTIONS})
+    string(TOUPPER "${config}" config_upper)
+    foreach(option ${_PER_CONFIG_OPTIONS})
       # Check for the presence of a config-specific option, and override what's
       # Check for the presence of a config-specific option, and override what's
       # in the cache if there is.
       # in the cache if there is.
-      if(DEFINED ${option}_${config})
-        set(${option} ${${option}_${config}})
+      if(DEFINED "${option}_${config_upper}")
+        set(${option} ${${option}_${config_upper}})
+      else()
+        message(FATAL_ERROR "${option}_${config_upper} is not defined")
       endif()
       endif()
     endforeach(option)
     endforeach(option)
 
 
@@ -199,7 +202,7 @@ if(IS_MULTICONFIG)
 
 
     # unset() does not unset CACHE variables by default, just normal variables.
     # unset() does not unset CACHE variables by default, just normal variables.
     # By doing this we're reverting back to what was in the cache.
     # By doing this we're reverting back to what was in the cache.
-    foreach(option ${PER_CONFIG_OPTIONS})
+    foreach(option ${_PER_CONFIG_OPTIONS})
       unset(${option})
       unset(${option})
     endforeach(option)
     endforeach(option)
   endforeach(config)
   endforeach(config)

+ 2 - 2
dtool/Package.cmake

@@ -369,7 +369,7 @@ package_option(TIFF "Enable support for loading .tif images.")
 package_status(TIFF "libtiff")
 package_status(TIFF "libtiff")
 
 
 # OpenEXR
 # OpenEXR
-find_package(OpenEXR QUIET)
+find_package(OpenEXR QUIET MODULE)
 
 
 package_option(OpenEXR "Enable support for loading .exr images.")
 package_option(OpenEXR "Enable support for loading .exr images.")
 
 
@@ -390,7 +390,7 @@ package_status(SQUISH "libsquish")
 #
 #
 
 
 # Assimp
 # Assimp
-find_package(Assimp QUIET)
+find_package(Assimp QUIET MODULE)
 
 
 package_option(Assimp
 package_option(Assimp
   "Build pandatool with support for loading 3D assets supported by Assimp.")
   "Build pandatool with support for loading 3D assets supported by Assimp.")

+ 1 - 50
dtool/PandaVersion.cmake

@@ -24,37 +24,7 @@ particular license. Some packages don't have a listed license because
 they are almost always required/used, or because they are only used in
 they are almost always required/used, or because they are only used in
 plugins that can be easily removed (eg. directx, ffmpeg, fmod, ...).")
 plugins that can be easily removed (eg. directx, ffmpeg, fmod, ...).")
 
 
-set(PANDA_PACKAGE_VERSION CACHE STRING
-  "This string is used to describe the Panda3D \"package\" associated
-with this current build of Panda. It should increment with major
-and minor version changes, but not sequence (or \"bugfix\") changes.
-It should be unique for each unique distributor. The default is
-the empty string, which means this build does not precisely match
-any distributable Panda3D packages. If you are making a Panda3D
-build which you will be using to produce a distributable Panda3D
-package, you should set this string appropriately.")
-
-set(P3D_PLUGIN_VERSION "1.0.4" CACHE STRING
-  "We also define a version for the Panda3D plugin/runtime,
-i.e. nppanda3d.dll, p3dactivex.ocx, and panda3d.exe. This is an
-independent version number from PANDA_VERSION or
-PANDA_PACKAGE_VERSION, because it is anticipated that this plugin
-code, once settled, will need to be updated much less frequently
-than Panda itself.")
-
-set(P3D_COREAPI_VERSION "${P3D_PLUGIN_VERSION}.1" CACHE STRING
-  "Finally, there's a separate version number for the Core API. At
-first, we didn't believe we needed a Core API version number, but
-in this belief we were naive.  This version number is a little less
-strict in its format requirements than P3D_PLUGIN_VERSION, above,
-and it doesn't necessarily consist of a specific number of
-integers, but by convention it will consist of four integers, with
-the first three matching the plugin version, and the fourth integer
-being incremented with each new Core API revision.")
-
-mark_as_advanced(PANDA_VERSION PANDA_OFFICIAL_VERSION
-  PANDA_PACKAGE_VERSION P3D_PLUGIN_VERSION P3D_COREAPI_VERSION
-  PANDA_DIST_USE_LICENSES)
+mark_as_advanced(PANDA_VERSION PANDA_OFFICIAL_VERSION PANDA_DIST_USE_LICENSES)
 
 
 # The version gets a "c" at the end if it's not an official one.
 # The version gets a "c" at the end if it's not an official one.
 if(PANDA_OFFICIAL_VERSION)
 if(PANDA_OFFICIAL_VERSION)
@@ -82,22 +52,3 @@ if(GIT_EXECUTABLE)
     OUTPUT_VARIABLE PANDA_GIT_COMMIT_STR
     OUTPUT_VARIABLE PANDA_GIT_COMMIT_STR
     ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
     ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
 endif()
 endif()
-
-# Separate the plugin version into its three components.
-string(REPLACE "." ";" P3D_PLUGIN_VERSION_LIST "${P3D_PLUGIN_VERSION}")
-list(GET P3D_PLUGIN_VERSION_LIST 0 P3D_PLUGIN_MAJOR_VERSION)
-list(GET P3D_PLUGIN_VERSION_LIST 1 P3D_PLUGIN_MINOR_VERSION)
-list(GET P3D_PLUGIN_VERSION_LIST 2 P3D_PLUGIN_SEQUENCE_VERSION)
-
-set(P3D_PLUGIN_VERSION_STR "${P3D_PLUGIN_VERSION}${VERSION_SUFFIX}")
-
-# The plugin version as dot-delimited integer quad, according to MS
-# conventions for DLL version numbers.
-if(PANDA_OFFICIAL_VERSION)
-  set(P3D_PLUGIN_DLL_DOT_VERSION "${P3D_PLUGIN_VERSION}.1000")
-else()
-  set(P3D_PLUGIN_DLL_DOT_VERSION "${P3D_PLUGIN_VERSION}.0")
-endif()
-
-# The same thing as a comma-delimited quad.
-string(REPLACE "." "," P3D_PLUGIN_DLL_COMMA_VERSION "${P3D_PLUGIN_DLL_DOT_VERSION}")

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 432 - 353
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 6 - 2
dtool/src/cppparser/cppBison.h.prebuilt

@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.5.  */
+/* A Bison parser, made by GNU Bison 3.5.3.  */
 
 
 /* Bison interface for Yacc-like parsers in C
 /* Bison interface for Yacc-like parsers in C
 
 
-   Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+   Inc.
 
 
    This program is free software: you can redistribute it and/or modify
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
    This special exception was added by the Free Software Foundation in
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
    version 2.2 of Bison.  */
 
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 #ifndef YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
 #ifndef YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
 # define YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
 # define YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
 /* Debug traces.  */
 /* Debug traces.  */

+ 13 - 37
dtool/src/cppparser/cppBison.yxx

@@ -1891,7 +1891,7 @@ instance_identifier_and_maybe_trailing_return_type:
   }
   }
   $$ = $1;
   $$ = $1;
 }
 }
-        | instance_identifier ':' INTEGER
+        | instance_identifier ':' const_expr
 {
 {
   // Bitfield definition.
   // Bitfield definition.
   $1->_bit_width = $3;
   $1->_bit_width = $3;
@@ -3278,17 +3278,9 @@ no_angle_bracket_const_expr:
 {
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
 }
 }
-        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+        | KW_SIZEOF no_angle_bracket_const_expr %prec UNARY
 {
 {
-  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
-  if (arg == nullptr) {
-    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
-  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
-    CPPInstance *inst = arg->as_instance();
-    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
-  } else {
-    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
-  }
+  $$ = new CPPExpression(CPPExpression::sizeof_func($2));
 }
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
 {
@@ -3402,9 +3394,9 @@ no_angle_bracket_const_expr:
 {
 {
   $$ = new CPPExpression('f', $1);
   $$ = new CPPExpression('f', $1);
 }
 }
-        | no_angle_bracket_const_expr '.' no_angle_bracket_const_expr
+        | no_angle_bracket_const_expr '.' name
 {
 {
-  $$ = new CPPExpression('.', $1, $3);
+  $$ = new CPPExpression('.', $1, new CPPExpression($3, current_scope, global_scope, current_lexer));
 }
 }
         | no_angle_bracket_const_expr POINTSAT no_angle_bracket_const_expr
         | no_angle_bracket_const_expr POINTSAT no_angle_bracket_const_expr
 {
 {
@@ -3542,17 +3534,9 @@ const_expr:
 {
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
 }
 }
-        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+        | KW_SIZEOF const_expr %prec UNARY
 {
 {
-  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
-  if (arg == nullptr) {
-    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
-  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
-    CPPInstance *inst = arg->as_instance();
-    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
-  } else {
-    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
-  }
+  $$ = new CPPExpression(CPPExpression::sizeof_func($2));
 }
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
 {
@@ -3704,9 +3688,9 @@ const_expr:
 {
 {
   $$ = new CPPExpression('f', $1);
   $$ = new CPPExpression('f', $1);
 }
 }
-        | const_expr '.' const_expr
+        | const_expr '.' name
 {
 {
-  $$ = new CPPExpression('.', $1, $3);
+  $$ = new CPPExpression('.', $1, new CPPExpression($3, current_scope, global_scope, current_lexer));
 }
 }
         | const_expr POINTSAT const_expr
         | const_expr POINTSAT const_expr
 {
 {
@@ -3886,17 +3870,9 @@ formal_const_expr:
 {
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
 }
 }
-        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+        | KW_SIZEOF formal_const_expr %prec UNARY
 {
 {
-  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
-  if (arg == nullptr) {
-    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
-  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
-    CPPInstance *inst = arg->as_instance();
-    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
-  } else {
-    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
-  }
+  $$ = new CPPExpression(CPPExpression::sizeof_func($2));
 }
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
 {
@@ -4044,9 +4020,9 @@ formal_const_expr:
 {
 {
   $$ = new CPPExpression('f', $1);
   $$ = new CPPExpression('f', $1);
 }
 }
-        | formal_const_expr '.' const_expr
+        | formal_const_expr '.' name
 {
 {
-  $$ = new CPPExpression('.', $1, $3);
+  $$ = new CPPExpression('.', $1, new CPPExpression($3, current_scope, global_scope, current_lexer));
 }
 }
         | formal_const_expr POINTSAT const_expr
         | formal_const_expr POINTSAT const_expr
 {
 {

+ 47 - 9
dtool/src/cppparser/cppExpression.cxx

@@ -429,12 +429,24 @@ type_trait(int trait, CPPType *type, CPPType *arg) {
 CPPExpression CPPExpression::
 CPPExpression CPPExpression::
 sizeof_func(CPPType *type) {
 sizeof_func(CPPType *type) {
   CPPExpression expr(0);
   CPPExpression expr(0);
-  expr._type = T_sizeof;
+  expr._type = T_sizeof_type;
   expr._u._typecast._to = type;
   expr._u._typecast._to = type;
   expr._u._typecast._op1 = nullptr;
   expr._u._typecast._op1 = nullptr;
   return expr;
   return expr;
 }
 }
 
 
+/**
+ *
+ */
+CPPExpression CPPExpression::
+sizeof_func(CPPExpression *op1) {
+  CPPExpression expr(0);
+  expr._type = T_sizeof_expr;
+  expr._u._typecast._to = nullptr;
+  expr._u._typecast._op1 = op1;
+  return expr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -629,7 +641,8 @@ evaluate() const {
   case T_empty_aggregate_init:
   case T_empty_aggregate_init:
   case T_new:
   case T_new:
   case T_default_new:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
+  case T_sizeof_expr:
   case T_sizeof_ellipsis:
   case T_sizeof_ellipsis:
     return Result();
     return Result();
 
 
@@ -1058,7 +1071,8 @@ determine_type() const {
   case T_default_new:
   case T_default_new:
     return CPPType::new_type(new CPPPointerType(_u._typecast._to));
     return CPPType::new_type(new CPPPointerType(_u._typecast._to));
 
 
-  case T_sizeof:
+  case T_sizeof_type:
+  case T_sizeof_expr:
   case T_sizeof_ellipsis:
   case T_sizeof_ellipsis:
   case T_alignof:
   case T_alignof:
     // Note: this should actually be size_t, but that is defined as a typedef
     // Note: this should actually be size_t, but that is defined as a typedef
@@ -1334,10 +1348,13 @@ is_fully_specified() const {
   case T_default_construct:
   case T_default_construct:
   case T_empty_aggregate_init:
   case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
   case T_alignof:
   case T_alignof:
     return _u._typecast._to->is_fully_specified();
     return _u._typecast._to->is_fully_specified();
 
 
+  case T_sizeof_expr:
+    return _u._typecast._op1->is_fully_specified();
+
   case T_sizeof_ellipsis:
   case T_sizeof_ellipsis:
     return _u._ident->is_fully_specified();
     return _u._ident->is_fully_specified();
 
 
@@ -1469,7 +1486,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
   case T_default_construct:
   case T_default_construct:
   case T_empty_aggregate_init:
   case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
   case T_alignof:
   case T_alignof:
     rep->_u._typecast._to =
     rep->_u._typecast._to =
       _u._typecast._to->substitute_decl(subst, current_scope, global_scope)
       _u._typecast._to->substitute_decl(subst, current_scope, global_scope)
@@ -1477,6 +1494,13 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
     any_changed = any_changed || (rep->_u._typecast._to != _u._typecast._to);
     any_changed = any_changed || (rep->_u._typecast._to != _u._typecast._to);
     break;
     break;
 
 
+  case T_sizeof_expr:
+    rep->_u._typecast._op1 =
+      _u._typecast._op1->substitute_decl(subst, current_scope, global_scope)
+      ->as_expression();
+    any_changed = any_changed || (rep->_u._typecast._op1 != _u._typecast._op1);
+    break;
+
   case T_trinary_operation:
   case T_trinary_operation:
     rep->_u._op._op3 =
     rep->_u._op._op3 =
       _u._op._op3->substitute_decl(subst, current_scope, global_scope)
       _u._op._op3->substitute_decl(subst, current_scope, global_scope)
@@ -1567,10 +1591,13 @@ is_tbd() const {
   case T_new:
   case T_new:
   case T_default_construct:
   case T_default_construct:
   case T_default_new:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
   case T_alignof:
   case T_alignof:
     return _u._typecast._to->is_tbd();
     return _u._typecast._to->is_tbd();
 
 
+  case T_sizeof_expr:
+    return _u._typecast._op1->is_tbd();
+
   case T_trinary_operation:
   case T_trinary_operation:
     if (_u._op._op3->is_tbd()) {
     if (_u._op._op3->is_tbd()) {
       return true;
       return true;
@@ -1807,12 +1834,17 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << "())";
     out << "())";
     break;
     break;
 
 
-  case T_sizeof:
+  case T_sizeof_type:
     out << "sizeof(";
     out << "sizeof(";
     _u._typecast._to->output(out, indent_level, scope, false);
     _u._typecast._to->output(out, indent_level, scope, false);
     out << ")";
     out << ")";
     break;
     break;
 
 
+  case T_sizeof_expr:
+    out << "sizeof ";
+    _u._typecast._op1->output(out, indent_level, scope, false);
+    break;
+
   case T_sizeof_ellipsis:
   case T_sizeof_ellipsis:
     out << "sizeof...(";
     out << "sizeof...(";
     _u._ident->output(out, scope);
     _u._ident->output(out, scope);
@@ -2222,10 +2254,13 @@ is_equal(const CPPDeclaration *other) const {
   case T_default_construct:
   case T_default_construct:
   case T_empty_aggregate_init:
   case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
   case T_alignof:
   case T_alignof:
     return _u._typecast._to == ot->_u._typecast._to;
     return _u._typecast._to == ot->_u._typecast._to;
 
 
+  case T_sizeof_expr:
+    return _u._typecast._op1 == ot->_u._typecast._op1;
+
   case T_unary_operation:
   case T_unary_operation:
     return *_u._op._op1 == *ot->_u._op._op1;
     return *_u._op._op1 == *ot->_u._op._op1;
 
 
@@ -2324,10 +2359,13 @@ is_less(const CPPDeclaration *other) const {
   case T_default_construct:
   case T_default_construct:
   case T_empty_aggregate_init:
   case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
   case T_alignof:
   case T_alignof:
     return _u._typecast._to < ot->_u._typecast._to;
     return _u._typecast._to < ot->_u._typecast._to;
 
 
+  case T_sizeof_expr:
+    return _u._typecast._op1 < ot->_u._typecast._op1;
+
   case T_trinary_operation:
   case T_trinary_operation:
     if (*_u._op._op3 != *ot->_u._op._op3) {
     if (*_u._op._op3 != *ot->_u._op._op3) {
       return *_u._op._op3 < *ot->_u._op._op3;
       return *_u._op._op3 < *ot->_u._op._op3;

+ 3 - 1
dtool/src/cppparser/cppExpression.h

@@ -52,7 +52,8 @@ public:
     T_empty_aggregate_init,
     T_empty_aggregate_init,
     T_new,
     T_new,
     T_default_new,
     T_default_new,
-    T_sizeof,
+    T_sizeof_type,
+    T_sizeof_expr,
     T_sizeof_ellipsis,
     T_sizeof_ellipsis,
     T_alignof,
     T_alignof,
     T_unary_operation,
     T_unary_operation,
@@ -89,6 +90,7 @@ public:
   static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info);
   static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info);
   static CPPExpression type_trait(int trait, CPPType *type, CPPType *arg = nullptr);
   static CPPExpression type_trait(int trait, CPPType *type, CPPType *arg = nullptr);
   static CPPExpression sizeof_func(CPPType *type);
   static CPPExpression sizeof_func(CPPType *type);
+  static CPPExpression sizeof_func(CPPExpression *op1);
   static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
   static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
   static CPPExpression alignof_func(CPPType *type);
   static CPPExpression alignof_func(CPPType *type);
   static CPPExpression lambda(CPPClosureType *type);
   static CPPExpression lambda(CPPClosureType *type);

+ 11 - 1
dtool/src/cppparser/cppInstance.cxx

@@ -74,7 +74,17 @@ CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
   ii->_ident = nullptr;
   ii->_ident = nullptr;
   _storage_class = storage_class;
   _storage_class = storage_class;
   _initializer = nullptr;
   _initializer = nullptr;
-  _bit_width = ii->_bit_width;
+
+  if (ii->_bit_width != nullptr) {
+    CPPExpression::Result result = ii->_bit_width->evaluate();
+    if (result._type != CPPExpression::RT_error) {
+      _bit_width = ii->_bit_width->evaluate().as_integer();
+    } else {
+      _bit_width = -1;
+    }
+  } else {
+    _bit_width = -1;
+  }
 
 
   CPPParameterList *params = ii->get_initializer();
   CPPParameterList *params = ii->get_initializer();
   if (params != nullptr) {
   if (params != nullptr) {

+ 1 - 1
dtool/src/cppparser/cppInstanceIdentifier.cxx

@@ -82,7 +82,7 @@ initializer_type(CPPParameterList *params) {
 CPPInstanceIdentifier::
 CPPInstanceIdentifier::
 CPPInstanceIdentifier(CPPIdentifier *ident) :
 CPPInstanceIdentifier(CPPIdentifier *ident) :
   _ident(ident),
   _ident(ident),
-  _bit_width(-1),
+  _bit_width(nullptr),
   _packed(false) {
   _packed(false) {
 }
 }
 
 

+ 2 - 2
dtool/src/cppparser/cppInstanceIdentifier.h

@@ -86,8 +86,8 @@ public:
   typedef std::vector<Modifier> Modifiers;
   typedef std::vector<Modifier> Modifiers;
   Modifiers _modifiers;
   Modifiers _modifiers;
 
 
-  // If not -1, indicates a bitfield
-  int _bit_width;
+  // If not null, indicates a bitfield
+  CPPExpression *_bit_width;
 
 
   // Indicates a parameter pack
   // Indicates a parameter pack
   bool _packed;
   bool _packed;

+ 1 - 3
dtool/src/cppparser/cppManifest.cxx

@@ -127,9 +127,7 @@ CPPManifest(const string &macro, const string &definition) :
  */
  */
 CPPManifest::
 CPPManifest::
 ~CPPManifest() {
 ~CPPManifest() {
-  if (_expr != nullptr) {
-    delete _expr;
-  }
+  delete _expr;
 }
 }
 
 
 /**
 /**

+ 2 - 2
dtool/src/dtoolbase/cmath.I

@@ -351,7 +351,7 @@ cnan(double v) {
 #if __FINITE_MATH_ONLY__
 #if __FINITE_MATH_ONLY__
   // GCC's isnan breaks when using -ffast-math.
   // GCC's isnan breaks when using -ffast-math.
   union { double d; uint64_t x; } u = { v };
   union { double d; uint64_t x; } u = { v };
-  return ((u.x << 1) > 0xff70000000000000ull);
+  return ((u.x << 1) > 0xffe0000000000000ull);
 #elif !defined(_WIN32)
 #elif !defined(_WIN32)
   return std::isnan(v);
   return std::isnan(v);
 #else
 #else
@@ -383,7 +383,7 @@ cinf(double v) {
 #if __FINITE_MATH_ONLY__
 #if __FINITE_MATH_ONLY__
   // GCC's isinf breaks when using -ffast-math.
   // GCC's isinf breaks when using -ffast-math.
   union { double d; uint64_t x; } u = { v };
   union { double d; uint64_t x; } u = { v };
-  return ((u.x << 1) == 0xff70000000000000ull);
+  return ((u.x << 1) == 0xffe0000000000000ull);
 #elif !defined(_WIN32)
 #elif !defined(_WIN32)
   return std::isinf(v);
   return std::isinf(v);
 #else
 #else

+ 6 - 2
dtool/src/dtoolbase/deletedChain.h

@@ -85,7 +85,9 @@ public:
     return ptr;                                              \
     return ptr;                                              \
   }                                                          \
   }                                                          \
   inline void operator delete(void *ptr) {                   \
   inline void operator delete(void *ptr) {                   \
-    StaticDeletedChain< Type >::deallocate((Type *)ptr, get_type_handle(Type)); \
+    if (ptr != nullptr) {                                    \
+      StaticDeletedChain< Type >::deallocate((Type *)ptr, get_type_handle(Type)); \
+    }                                                        \
   }                                                          \
   }                                                          \
   inline void operator delete(void *, void *) {              \
   inline void operator delete(void *, void *) {              \
   }                                                          \
   }                                                          \
@@ -104,7 +106,9 @@ public:
     return ptr;                                              \
     return ptr;                                              \
   }                                                          \
   }                                                          \
   inline void operator delete(void *ptr) {                   \
   inline void operator delete(void *ptr) {                   \
-    _deleted_chain.deallocate((Type *)ptr, get_type_handle(Type)); \
+    if (ptr != nullptr) {                                    \
+      _deleted_chain.deallocate((Type *)ptr, get_type_handle(Type)); \
+    }                                                        \
   }                                                          \
   }                                                          \
   inline void operator delete(void *, void *) {              \
   inline void operator delete(void *, void *) {              \
   }                                                          \
   }                                                          \

+ 6 - 2
dtool/src/dtoolbase/memoryBase.h

@@ -32,7 +32,9 @@
     return ptr;                                              \
     return ptr;                                              \
   }                                                          \
   }                                                          \
   inline void operator delete(void *ptr) {                   \
   inline void operator delete(void *ptr) {                   \
-    PANDA_FREE_SINGLE(ptr);                                  \
+    if (ptr != nullptr) {                                    \
+      PANDA_FREE_SINGLE(ptr);                                \
+    }                                                        \
   }                                                          \
   }                                                          \
   inline void operator delete(void *, void *) {              \
   inline void operator delete(void *, void *) {              \
   }                                                          \
   }                                                          \
@@ -44,7 +46,9 @@
     return ptr;                                              \
     return ptr;                                              \
   }                                                          \
   }                                                          \
   inline void operator delete[](void *ptr) {                 \
   inline void operator delete[](void *ptr) {                 \
-    PANDA_FREE_ARRAY(ptr);                                   \
+    if (ptr != nullptr) {                                    \
+      PANDA_FREE_ARRAY(ptr);                                 \
+    }                                                        \
   }                                                          \
   }                                                          \
   inline void operator delete[](void *, void *) {            \
   inline void operator delete[](void *, void *) {            \
   }
   }

+ 0 - 10
dtool/src/dtoolbase/pandaVersion.h.in

@@ -61,13 +61,3 @@
 
 
 /* This is a string indicating who has provided this distribution. */
 /* This is a string indicating who has provided this distribution. */
 #define PANDA_DISTRIBUTOR "@PANDA_DISTRIBUTOR@"
 #define PANDA_DISTRIBUTOR "@PANDA_DISTRIBUTOR@"
-
-/* The string indicating the version number of the associated Panda3D
-   distributable package, or empty string if there is no associated
-   package. */
-#define PANDA_PACKAGE_VERSION_STR "@PANDA_PACKAGE_VERSION@"
-
-/* The string indicating the URL from which the associated Panda3D
-   distributable package may be downloaded, or empty string if there
-   is no associated package. */
-#define PANDA_PACKAGE_HOST_URL "@PANDA_PACKAGE_HOST_URL@"

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است