diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 91417cb9ff..762c684450 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -2,6 +2,7 @@ name: Bug report about: Report a defect title: +type: bug labels: assignees: --- diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..98ee85f95f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,12 @@ +contact_links: + - name: Community forums + url: https://discourse.panda3d.org/ + about: Please visit the community forums for technical support and other questions. + + - name: Documentation bugs + url: https://github.com/panda3d/panda3d-docs/issues + about: Problems with the online documentation should be reported on the panda3d-docs issue tracker, not here. + + - name: Discord server + url: https://discord.gg/UyepRMm + about: Get real-time help with questions about Panda3D or discuss ideas with the developers on our Discord server. diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index 954153caf3..190f226dbb 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -2,6 +2,7 @@ name: Enhancement request about: Request new functionality or improvement to existing functionality title: +type: feature labels: enhancement assignees: --- diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..4fc308718e --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4d0ca918a..18ce4881f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,15 +11,15 @@ jobs: matrix: profile: - - ubuntu-bionic-standard-unity-makefile + - ubuntu-bionic-double-standard-unity-makefile - ubuntu-bionic-coverage-ninja - - macos-eigen-coverage-unity-xcode + #- macos-coverage-unity-xcode - macos-nometa-standard-makefile - windows-standard-unity-msvc - windows-nopython-nometa-standard-msvc include: - - profile: ubuntu-bionic-standard-unity-makefile + - profile: ubuntu-bionic-double-standard-unity-makefile os: ubuntu-20.04 config: Standard unity: YES @@ -28,6 +28,7 @@ jobs: metalibs: YES python: YES eigen: NO + double: YES - profile: ubuntu-bionic-coverage-ninja os: ubuntu-20.04 @@ -38,19 +39,21 @@ jobs: metalibs: YES python: YES eigen: NO + double: NO - - profile: macos-eigen-coverage-unity-xcode - os: macOS-12 - config: Coverage - unity: YES - generator: Xcode - compiler: Default - metalibs: YES - python: YES - eigen: YES + #- profile: macos-coverage-unity-xcode + # os: macOS-13 + # config: Coverage + # unity: YES + # generator: Xcode + # compiler: Default + # metalibs: YES + # python: YES + # eigen: NO + # double: NO - profile: macos-nometa-standard-makefile - os: macOS-12 + os: macOS-13 config: Standard unity: NO generator: Unix Makefiles @@ -58,6 +61,7 @@ jobs: metalibs: NO python: YES eigen: NO + double: NO - profile: windows-standard-unity-msvc os: windows-2022 @@ -68,6 +72,7 @@ jobs: metalibs: YES python: YES eigen: NO + double: NO - profile: windows-nopython-nometa-standard-msvc os: windows-2022 @@ -78,11 +83,12 @@ jobs: metalibs: NO python: NO eigen: NO + double: NO runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: fetch-depth: 10 @@ -92,16 +98,20 @@ jobs: - name: Install dependencies (macOS) if: runner.os == 'macOS' run: | - curl -O https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-mac.tar.gz - tar -xf panda3d-1.10.14-tools-mac.tar.gz - mv panda3d-1.10.14/thirdparty thirdparty - rmdir panda3d-1.10.14 + curl -O https://www.panda3d.org/download/panda3d-1.10.15/panda3d-1.10.15-tools-mac.tar.gz + tar -xf panda3d-1.10.15-tools-mac.tar.gz + mv panda3d-1.10.15/thirdparty thirdparty + rmdir panda3d-1.10.15 # Temporary hack so that pzip can run, since we are about to remove Cg anyway. install_name_tool -id "$(pwd)/thirdparty/darwin-libs-a/nvidiacg/lib/libCg.dylib" thirdparty/darwin-libs-a/nvidiacg/lib/libCg.dylib brew install ccache + - name: Set up XCode (macOS) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_14.3.1.app/Contents/Developer + - name: Install dependencies (Ubuntu) if: startsWith(matrix.os, 'ubuntu') run: > @@ -117,24 +127,24 @@ jobs: - name: Cache dependencies (Windows) if: runner.os == 'Windows' - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: thirdparty - key: ci-cmake-${{ runner.OS }}-thirdparty-v1.10.14-r1 + key: ci-cmake-${{ runner.OS }}-thirdparty-v1.10.15-r1 - name: Install dependencies (Windows) if: runner.os == 'Windows' shell: powershell run: | if (!(Test-Path thirdparty/win-libs-vc14-x64)) { $wc = New-Object System.Net.WebClient - $wc.DownloadFile("https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-win64.zip", "thirdparty-tools.zip") + $wc.DownloadFile("https://www.panda3d.org/download/panda3d-1.10.15/panda3d-1.10.15-tools-win64.zip", "thirdparty-tools.zip") Expand-Archive -Path thirdparty-tools.zip - Move-Item -Path thirdparty-tools/panda3d-1.10.14/thirdparty -Destination . + Move-Item -Path thirdparty-tools/panda3d-1.10.15/thirdparty -Destination . } - name: ccache (non-Windows) if: runner.os != 'Windows' - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ccache key: ci-cmake-ccache-${{ matrix.profile }} @@ -171,6 +181,7 @@ jobs: -D BUILD_METALIBS=${{ matrix.metalibs }} -D HAVE_PYTHON=${{ runner.os != 'Windows' && matrix.python || 'NO' }} -D HAVE_EIGEN=${{ matrix.eigen }} + -D STDFLOAT_DOUBLE=${{ matrix.double }} .. - name: Build (no Python) @@ -182,7 +193,7 @@ jobs: - name: Setup Python (Python 3.8) if: contains(matrix.python, 'YES') - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.8' - name: Configure (Python 3.8) @@ -214,7 +225,7 @@ jobs: - name: Setup Python (Python 3.9) if: contains(matrix.python, 'YES') - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.9' - name: Configure (Python 3.9) @@ -246,7 +257,7 @@ jobs: - name: Setup Python (Python 3.10) if: contains(matrix.python, 'YES') - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' - name: Configure (Python 3.10) @@ -278,7 +289,7 @@ jobs: - name: Setup Python (Python 3.11) if: contains(matrix.python, 'YES') - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Configure (Python 3.11) @@ -310,7 +321,7 @@ jobs: - name: Setup Python (Python 3.12) if: contains(matrix.python, 'YES') - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.12' - name: Configure (Python 3.12) @@ -361,10 +372,10 @@ jobs: if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')" strategy: matrix: - os: [ubuntu-20.04, windows-2019, macOS-12] + os: [ubuntu-20.04, windows-2019, macOS-13] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Install dependencies (Ubuntu) if: matrix.os == 'ubuntu-20.04' run: | @@ -375,40 +386,62 @@ jobs: shell: powershell run: | $wc = New-Object System.Net.WebClient - $wc.DownloadFile("https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-win64.zip", "thirdparty-tools.zip") + $wc.DownloadFile("https://www.panda3d.org/download/panda3d-1.10.15/panda3d-1.10.15-tools-win64.zip", "thirdparty-tools.zip") Expand-Archive -Path thirdparty-tools.zip - Move-Item -Path thirdparty-tools/panda3d-1.10.14/thirdparty -Destination . + Move-Item -Path thirdparty-tools/panda3d-1.10.15/thirdparty -Destination . - name: Get thirdparty packages (macOS) if: runner.os == 'macOS' run: | - curl -O https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-mac.tar.gz - tar -xf panda3d-1.10.14-tools-mac.tar.gz - mv panda3d-1.10.14/thirdparty thirdparty - rmdir panda3d-1.10.14 + curl -O https://www.panda3d.org/download/panda3d-1.10.15/panda3d-1.10.15-tools-mac.tar.gz + tar -xf panda3d-1.10.15-tools-mac.tar.gz + mv panda3d-1.10.15/thirdparty thirdparty + rmdir panda3d-1.10.15 (cd thirdparty/darwin-libs-a && rm -rf rocket) - - name: Set up Python 3.12 - uses: actions/setup-python@v4 + - name: Set up XCode (macOS) + if: runner.os == 'macOS' + run: sudo xcode-select -s /Applications/Xcode_14.3.1.app/Contents/Developer + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 with: - python-version: '3.12' - - name: Build Python 3.12 + python-version: '3.13' + - name: Build Python 3.13 shell: bash run: | - python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 - - name: Test Python 3.12 + python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 --msvc-version=14.2 + - name: Test Python 3.13 shell: bash run: | python -m pip install -r requirements-test.txt PYTHONPATH=built LD_LIBRARY_PATH=built/lib:$pythonLocation/lib DYLD_LIBRARY_PATH=built/lib python -m pytest + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Build Python 3.12 (double) + shell: bash + run: | + python makepanda/makepanda.py --override STDFLOAT_DOUBLE=1 --git-commit=${{github.sha}} --outputdir=built_dbl --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 --msvc-version=14.2 + - name: Test Python 3.12 (double) + shell: bash + run: | + python -m pip install -r requirements-test.txt + PYTHONPATH=built_dbl LD_LIBRARY_PATH=built_dbl/lib:$pythonLocation/lib DYLD_LIBRARY_PATH=built_dbl/lib python -m pytest + + - name: Make installer + run: | + python makepanda/makepackage.py --verbose --lzma --outputdir=built_dbl + - name: Set up Python 3.11 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Build Python 3.11 shell: bash run: | - python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 + python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 --msvc-version=14.2 - name: Test Python 3.11 shell: bash run: | @@ -416,13 +449,13 @@ jobs: PYTHONPATH=built LD_LIBRARY_PATH=built/lib:$pythonLocation/lib DYLD_LIBRARY_PATH=built/lib python -m pytest - name: Set up Python 3.10 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' - name: Build Python 3.10 shell: bash run: | - python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 + python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 --msvc-version=14.2 - name: Test Python 3.10 shell: bash run: | @@ -430,13 +463,13 @@ jobs: PYTHONPATH=built LD_LIBRARY_PATH=built/lib:$pythonLocation/lib DYLD_LIBRARY_PATH=built/lib python -m pytest - name: Set up Python 3.9 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.9' - name: Build Python 3.9 shell: bash run: | - python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 + python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 --msvc-version=14.2 - name: Test Python 3.9 shell: bash run: | @@ -444,13 +477,13 @@ jobs: PYTHONPATH=built LD_LIBRARY_PATH=built/lib:$pythonLocation/lib DYLD_LIBRARY_PATH=built/lib python -m pytest - name: Set up Python 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.8' - name: Build Python 3.8 shell: bash run: | - python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 + python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 --msvc-version=14.2 - name: Test Python 3.8 shell: bash run: | @@ -463,22 +496,59 @@ jobs: emscripten: if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')" - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Install dependencies run: | sudo apt-get update - sudo apt-get install build-essential ninja-build bison flex + sudo apt-get install build-essential ninja-build bison flex nodejs python3-pip - name: Setup emsdk uses: mymindstorm/setup-emsdk@v14 with: - version: 3.1.51 + version: 3.1.70 actions-cache-folder: 'emsdk-cache' + - name: Restore Python build cache + id: cache-emscripten-python-restore + uses: actions/cache/restore@v4 + with: + path: ~/python + key: cache-emscripten-python-3.12.7 + + - name: Build Python 3.12 + if: steps.cache-emscripten-python-restore.outputs.cache-hit != 'true' + run: | + wget https://www.python.org/ftp/python/3.12.7/Python-3.12.7.tar.xz + tar -xJf Python-3.12.7.tar.xz + (cd Python-3.12.7 && EM_CONFIG=$EMSDK/.emscripten python3 Tools/wasm/wasm_build.py emscripten-browser) + (cd Python-3.12.7/builddir/emscripten-browser && make install DESTDIR=~/python) + cp Python-3.12.7/builddir/emscripten-browser/Modules/_hacl/libHacl_Hash_SHA2.a ~/python/usr/local/lib + cp Python-3.12.7/builddir/emscripten-browser/Modules/_decimal/libmpdec/libmpdec.a ~/python/usr/local/lib + cp Python-3.12.7/builddir/emscripten-browser/Modules/expat/libexpat.a ~/python/usr/local/lib + rm -rf Python-3.12.7 + + - name: Save Python build cache + id: cache-emscripten-python-save + if: steps.cache-emscripten-python-restore.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + path: ~/python + key: ${{ steps.cache-emscripten-python-restore.outputs.cache-primary-key }} + - name: Build for Emscripten shell: bash run: | - python3 makepanda/makepanda.py --git-commit=${{github.sha}} --target emscripten --outputdir=built --everything --no-python --verbose --threads=4 + python3 makepanda/makepanda.py --git-commit=${{github.sha}} --target emscripten --python-incdir=~/python/usr/local/include --python-libdir=~/python/usr/local/lib --static --everything --no-pandatool --no-deploytools --verbose --threads=4 + + - name: Install test dependencies + shell: bash + run: | + python3 -m pip install -t ~/python/usr/local/lib/python3.12/site-packages -r requirements-test.txt + + - name: Test in node.js + shell: bash + run: | + PYTHONHOME=~/python/usr/local PYTHONPATH=built node built/bin/run_tests.js tests diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 1266bfddfb..6e70577204 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -10,9 +10,9 @@ jobs: python-version: ['3.8', '3.11'] fail-fast: false steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/BACKERS.md b/BACKERS.md index a3eb53177b..2b48940fc3 100644 --- a/BACKERS.md +++ b/BACKERS.md @@ -33,6 +33,7 @@ This is a list of all the people who are contributing financially to Panda3D. I * GameDev JONI * Max Rodriguez * Jethro Schoppenhorst +* dabe ## Backers diff --git a/README.md b/README.md index c4a18ce8a3..6e4e78784b 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Installing Panda3D ================== The latest Panda3D SDK can be downloaded from -[this page](https://www.panda3d.org/download/sdk-1-10-14/). +[this page](https://www.panda3d.org/download/sdk-1-10-15/). If you are familiar with installing Python packages, you can use the following command: @@ -52,7 +52,7 @@ Building Panda3D Windows ------- -You can build Panda3D with the Microsoft Visual C++ 2015, 2017, 2019 or 2022 +You can build Panda3D with the Microsoft Visual C++ 2017, 2019 or 2022 compiler, which can be downloaded for free from the [Visual Studio site](https://visualstudio.microsoft.com/downloads/). You will also need to install the [Windows SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-sdk), and if you intend to target Windows Vista, you will also need the @@ -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 building them from source. -- https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-win64.zip -- https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-win32.zip +- https://www.panda3d.org/download/panda3d-1.10.15/panda3d-1.10.15-tools-win64.zip +- https://www.panda3d.org/download/panda3d-1.10.15/panda3d-1.10.15-tools-win32.zip After acquiring these dependencies, you can build Panda3D from the command prompt using the following command. Change the `--msvc-version` option based @@ -136,7 +136,7 @@ macOS ----- On macOS, you will need to download a set of precompiled thirdparty packages in order to -compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-mac.tar.gz). +compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.15/panda3d-1.10.15-tools-mac.tar.gz). After placing the thirdparty directory inside the panda3d source directory, you may build Panda3D using a command like the following: diff --git a/cmake/macros/Python.cmake b/cmake/macros/Python.cmake index 32258d4a6d..ce605e00b9 100644 --- a/cmake/macros/Python.cmake +++ b/cmake/macros/Python.cmake @@ -49,6 +49,7 @@ function(add_python_target target) add_library(${target} ${MODULE_TYPE} ${sources}) target_link_libraries(${target} PKG::PYTHON) + target_include_directories(${target} PRIVATE "${PROJECT_SOURCE_DIR}/dtool/src/interrogatedb") if(BUILD_SHARED_LIBS) set(_outdir "${PANDA_OUTPUT_DIR}/${slash_namespace}") diff --git a/direct/src/dcparser/dcClass_ext.cxx b/direct/src/dcparser/dcClass_ext.cxx index 44ab8f27bb..c7135cfabb 100644 --- a/direct/src/dcparser/dcClass_ext.cxx +++ b/direct/src/dcparser/dcClass_ext.cxx @@ -547,31 +547,35 @@ client_format_generate_CMU(PyObject *distobj, DOID_TYPE do_id, } // Also specify the optional fields. - int num_optional_fields = 0; if (PyObject_IsTrue(optional_fields)) { - num_optional_fields = PySequence_Size(optional_fields); - } - packer.raw_pack_uint16(num_optional_fields); + optional_fields = PySequence_Tuple(optional_fields); + Py_ssize_t num_optional_fields = PyTuple_GET_SIZE(optional_fields); + packer.raw_pack_uint16(num_optional_fields); - for (int i = 0; i < num_optional_fields; i++) { - PyObject *py_field_name = PySequence_GetItem(optional_fields, i); - std::string field_name = PyUnicode_AsUTF8(py_field_name); - Py_XDECREF(py_field_name); + for (Py_ssize_t i = 0; i < num_optional_fields; i++) { + PyObject *py_field_name = PyTuple_GET_ITEM(optional_fields, i); + std::string field_name = PyUnicode_AsUTF8(py_field_name); - DCField *field = _this->get_field_by_name(field_name); - if (field == nullptr) { - std::ostringstream strm; - strm << "No field named " << field_name << " in class " << _this->get_name() - << "\n"; - nassert_raise(strm.str()); - return Datagram(); + DCField *field = _this->get_field_by_name(field_name); + if (field == nullptr) { + std::ostringstream strm; + strm << "No field named " << field_name << " in class " << _this->get_name() + << "\n"; + nassert_raise(strm.str()); + Py_DECREF(optional_fields); + return Datagram(); + } + packer.raw_pack_uint16(field->get_number()); + packer.begin_pack(field); + if (!pack_required_field(packer, distobj, field)) { + Py_DECREF(optional_fields); + return Datagram(); + } + packer.end_pack(); } - packer.raw_pack_uint16(field->get_number()); - packer.begin_pack(field); - if (!pack_required_field(packer, distobj, field)) { - return Datagram(); - } - packer.end_pack(); + Py_DECREF(optional_fields); + } else { + packer.raw_pack_uint16(0); } return Datagram(packer.get_data(), packer.get_length()); @@ -646,13 +650,13 @@ ai_format_generate(PyObject *distobj, DOID_TYPE do_id, // Also specify the optional fields. if (has_optional_fields) { - int num_optional_fields = PySequence_Size(optional_fields); + optional_fields = PySequence_Tuple(optional_fields); + Py_ssize_t num_optional_fields = PyTuple_GET_SIZE(optional_fields); packer.raw_pack_uint16(num_optional_fields); - for (int i = 0; i < num_optional_fields; ++i) { - PyObject *py_field_name = PySequence_GetItem(optional_fields, i); + for (Py_ssize_t i = 0; i < num_optional_fields; ++i) { + PyObject *py_field_name = PyTuple_GET_ITEM(optional_fields, i); std::string field_name = PyUnicode_AsUTF8(py_field_name); - Py_XDECREF(py_field_name); DCField *field = _this->get_field_by_name(field_name); if (field == nullptr) { @@ -660,6 +664,7 @@ ai_format_generate(PyObject *distobj, DOID_TYPE do_id, strm << "No field named " << field_name << " in class " << _this->get_name() << "\n"; nassert_raise(strm.str()); + Py_DECREF(optional_fields); return Datagram(); } @@ -667,10 +672,13 @@ ai_format_generate(PyObject *distobj, DOID_TYPE do_id, packer.begin_pack(field); if (!pack_required_field(packer, distobj, field)) { + Py_DECREF(optional_fields); return Datagram(); } packer.end_pack(); } + + Py_DECREF(optional_fields); } return Datagram(packer.get_data(), packer.get_length()); diff --git a/direct/src/dcparser/dcField_ext.cxx b/direct/src/dcparser/dcField_ext.cxx index 6a92b9d255..6df84efc45 100644 --- a/direct/src/dcparser/dcField_ext.cxx +++ b/direct/src/dcparser/dcField_ext.cxx @@ -286,8 +286,9 @@ get_pystr(PyObject *value) { return result; } - if (value->ob_type != nullptr) { - PyObject *typestr = PyObject_Str((PyObject *)(value->ob_type)); + PyTypeObject *type = Py_TYPE(value); + if (type != nullptr) { + PyObject *typestr = PyObject_Str((PyObject *)type); if (typestr != nullptr) { std::string result = PyUnicode_AsUTF8(typestr); Py_DECREF(typestr); diff --git a/direct/src/dcparser/dcPacker_ext.cxx b/direct/src/dcparser/dcPacker_ext.cxx index 276a2dd7f9..9ffca60ba9 100644 --- a/direct/src/dcparser/dcPacker_ext.cxx +++ b/direct/src/dcparser/dcPacker_ext.cxx @@ -136,6 +136,7 @@ pack_object(PyObject *object) { // The supplied object is not an instance of the expected class object, // but it is a sequence. This is case (2). _this->push(); + Py_BEGIN_CRITICAL_SECTION(object); int size = PySequence_Size(object); for (int i = 0; i < size; ++i) { PyObject *element = PySequence_GetItem(object, i); @@ -146,6 +147,7 @@ pack_object(PyObject *object) { std::cerr << "Unable to extract item " << i << " from sequence.\n"; } } + Py_END_CRITICAL_SECTION(); _this->pop(); } else { // The supplied object is not a sequence, and we weren't expecting a diff --git a/direct/src/directbase/TestStart.py b/direct/src/directbase/TestStart.py index bdbab206e5..16ada8e9e7 100755 --- a/direct/src/directbase/TestStart.py +++ b/direct/src/directbase/TestStart.py @@ -8,6 +8,9 @@ base = ShowBase.ShowBase() # Put an axis in the world: base.loader.loadModel("models/misc/xyzAxis").reparentTo(base.render) +assert base.camera is not None +assert base.camLens is not None + base.camera.setPosHpr(0, -10.0, 0, 0, 0, 0) base.camLens.setFov(52.0) base.camLens.setNearFar(1.0, 10000.0) diff --git a/direct/src/directbase/ThreeUpStart.py b/direct/src/directbase/ThreeUpStart.py index 3ca50b34fe..26f9bf7401 100644 --- a/direct/src/directbase/ThreeUpStart.py +++ b/direct/src/directbase/ThreeUpStart.py @@ -10,6 +10,9 @@ base = ThreeUpShow.ThreeUpShow() # Put an axis in the world: base.loader.loadModel("models/misc/xyzAxis").reparentTo(base.render) +assert base.camera is not None +assert base.camLens is not None + base.camera.setPosHpr(0, -10.0, 0, 0, 0, 0) base.camLens.setFov(52.0) base.camLens.setNearFar(1.0, 10000.0) diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 505e57697b..5f12b7fe4b 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -75,6 +75,7 @@ def _model_to_bam(_build_cmd, srcpath, dstpath): src_fn = p3d.Filename.from_os_specific(srcpath) dst_fn = p3d.Filename.from_os_specific(dstpath) + dst_fn.set_binary() _register_python_loaders() @@ -85,8 +86,30 @@ def _model_to_bam(_build_cmd, srcpath, dstpath): if not node: raise IOError('Failed to load model: %s' % (srcpath)) - if not p3d.NodePath(node).write_bam_file(dst_fn): - raise IOError('Failed to write .bam file: %s' % (dstpath)) + stream = p3d.OFileStream() + if not dst_fn.open_write(stream): + raise IOError('Failed to open .bam file for writing: %s' % (dstpath)) + + # We pass it the source filename here so that texture files are made + # relative to the original pathname and don't point from the destination + # back into the source directory. + dout = p3d.DatagramOutputFile() + if not dout.open(stream, src_fn) or not dout.write_header("pbj\0\n\r"): + raise IOError('Failed to write to .bam file: %s' % (dstpath)) + + writer = p3d.BamWriter(dout) + writer.root_node = node + writer.init() + if _build_cmd.bam_embed_textures: + writer.set_file_texture_mode(p3d.BamEnums.BTM_rawdata) + else: + writer.set_file_texture_mode(p3d.BamEnums.BTM_relative) + writer.write_object(node) + writer.flush() + writer = None + dout.close() + dout = None + stream.close() macosx_binary_magics = ( @@ -289,6 +312,11 @@ class build_apps(setuptools.Command): 'macosx_10_9_x86_64', 'win_amd64', ] + + if sys.version_info >= (3, 13): + # This version of Python is only available for 10.13+. + self.platforms[1] = 'macosx_10_13_x86_64' + self.plugins = [] self.embed_prc_data = True self.extra_prc_files = [] @@ -307,6 +335,7 @@ class build_apps(setuptools.Command): ] self.file_handlers = {} self.bam_model_extensions = ['.egg', '.gltf', '.glb'] + self.bam_embed_textures = False self.exclude_dependencies = [ # Windows 'kernel32.dll', 'user32.dll', 'wsock32.dll', 'ws2_32.dll', @@ -321,7 +350,8 @@ class build_apps(setuptools.Command): # manylinux1/linux 'libdl.so.*', 'libstdc++.so.*', 'libm.so.*', 'libgcc_s.so.*', - 'libpthread.so.*', 'libc.so.*', 'ld-linux-x86-64.so.*', + 'libpthread.so.*', 'libc.so.*', + 'ld-linux-x86-64.so.*', 'ld-linux-aarch64.so.*', 'libgl.so.*', 'libx11.so.*', 'libncursesw.so.*', 'libz.so.*', 'librt.so.*', 'libutil.so.*', 'libnsl.so.1', 'libXext.so.6', 'libXrender.so.1', 'libICE.so.6', 'libSM.so.6', 'libEGL.so.1', @@ -646,14 +676,20 @@ class build_apps(setuptools.Command): subprocess.check_call([sys.executable, '-m', 'pip'] + pip_args) except: # Display a more helpful message for these common issues. - if platform.startswith('manylinux2010_') and sys.version_info >= (3, 11): + if platform.startswith('macosx_10_9_') and sys.version_info >= (3, 13): + new_platform = platform.replace('macosx_10_9_', 'macosx_10_13_') + self.announce('This error likely occurs because {} is not a supported target as of Python 3.13.\nChange the target platform to {} instead.'.format(platform, new_platform), distutils.log.ERROR) + elif platform.startswith('manylinux2010_') and sys.version_info >= (3, 11): new_platform = platform.replace('manylinux2010_', 'manylinux2014_') self.announce('This error likely occurs because {} is not a supported target as of Python 3.11.\nChange the target platform to {} instead.'.format(platform, new_platform), distutils.log.ERROR) elif platform.startswith('manylinux1_') and sys.version_info >= (3, 10): new_platform = platform.replace('manylinux1_', 'manylinux2014_') self.announce('This error likely occurs because {} is not a supported target as of Python 3.10.\nChange the target platform to {} instead.'.format(platform, new_platform), distutils.log.ERROR) elif platform.startswith('macosx_10_6_') and sys.version_info >= (3, 8): - new_platform = platform.replace('macosx_10_6_', 'macosx_10_9_') + if sys.version_info >= (3, 13): + new_platform = platform.replace('macosx_10_6_', 'macosx_10_13_') + else: + new_platform = platform.replace('macosx_10_6_', 'macosx_10_9_') self.announce('This error likely occurs because {} is not a supported target as of Python 3.8.\nChange the target platform to {} instead.'.format(platform, new_platform), distutils.log.ERROR) raise diff --git a/direct/src/distributed/ConnectionRepository.py b/direct/src/distributed/ConnectionRepository.py index 62c2d5da46..a29c61cafa 100644 --- a/direct/src/distributed/ConnectionRepository.py +++ b/direct/src/distributed/ConnectionRepository.py @@ -174,35 +174,6 @@ class ConnectionRepository( return retVal def generateGlobalObject(self, doId, dcname, values=None): - def applyFieldValues(distObj, dclass, values): - for i in range(dclass.getNumInheritedFields()): - field = dclass.getInheritedField(i) - if field.asMolecularField() is None: - value = values.get(field.getName(), None) - if value is None and field.isRequired(): - # Gee, this could be better. What would really be - # nicer is to get value from field.getDefaultValue - # or similar, but that returns a binary string, not - # a python tuple, like the following does. If you - # want to change something better, please go ahead. - packer = DCPacker() - packer.beginPack(field) - packer.packDefaultValue() - packer.endPack() - - unpacker = DCPacker() - unpacker.setUnpackData(packer.getString()) - unpacker.beginUnpack(field) - value = unpacker.unpackObject() - unpacker.endUnpack() - if value is not None: - function = getattr(distObj, field.getName()) - if function is not None: - function(*value) - else: - self.notify.error("\n\n\nNot able to find %s.%s"%( - distObj.__class__.__name__, field.getName())) - # Look up the dclass dclass = self.dclassesByName.get(dcname+self.dcSuffix) if dclass is None: @@ -229,7 +200,37 @@ class ConnectionRepository( distObj.generateInit() # Only called when constructed distObj.generate() if values is not None: - applyFieldValues(distObj, dclass, values) + for i in range(dclass.getNumInheritedFields()): + field = dclass.getInheritedField(i) + if field.asMolecularField() is None: + value = values.get(field.getName(), None) + if value is None and field.isRequired(): + # Gee, this could be better. What would really be + # nicer is to get value from field.getDefaultValue + # or similar, but that returns a binary string, not + # a python tuple, like the following does. If you + # want to change something better, please go ahead. + packer = DCPacker() + packer.beginPack(field) + packer.packDefaultValue() + packer.endPack() + + unpacker = DCPacker() + unpacker.setUnpackData(packer.getString()) + unpacker.beginUnpack(field) + value = unpacker.unpackObject() + unpacker.endUnpack() + if value is not None: + function = getattr(distObj, field.getName()) + if function is not None: + function(*value) + else: + self.notify.error( + "\n\n\nNot able to find %s.%s" % ( + distObj.__class__.__name__, + field.getName() + ) + ) distObj.announceGenerate() distObj.parentId = 0 distObj.zoneId = 0 diff --git a/direct/src/distributed/cConnectionRepository.cxx b/direct/src/distributed/cConnectionRepository.cxx index d7db58cde3..9f505a947e 100644 --- a/direct/src/distributed/cConnectionRepository.cxx +++ b/direct/src/distributed/cConnectionRepository.cxx @@ -713,11 +713,12 @@ handle_update_field() { nassertr(doId2do != nullptr, false); PyObject *doId = PyLong_FromUnsignedLong(do_id); - PyObject *distobj = PyDict_GetItem(doId2do, doId); + PyObject *distobj; + int result = PyDict_GetItemRef(doId2do, doId, &distobj); Py_DECREF(doId); Py_DECREF(doId2do); - if (distobj != nullptr) { + if (result > 0) { PyObject *dclass_obj = PyObject_GetAttrString(distobj, "dclass"); nassertr(dclass_obj != nullptr, false); @@ -736,9 +737,11 @@ handle_update_field() { nassertr(neverDisable != nullptr, false); unsigned int cNeverDisable = PyLong_AsLong(neverDisable); + Py_DECREF(neverDisable); if (!cNeverDisable) { // in quiet zone and distobj is disable-able drop update on the // floor + Py_DECREF(distobj); #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) PyGILState_Release(gstate); #endif @@ -746,13 +749,8 @@ handle_update_field() { } } - // It's a good idea to ensure the reference count to distobj is raised - // while we call the update method--otherwise, the update method might - // get into trouble if it tried to delete the object from the doId2do - // map. - PyObject *distobj_ref = Py_NewRef(distobj); - invoke_extension(dclass).receive_update(distobj_ref, _di); - Py_DECREF(distobj_ref); + invoke_extension(dclass).receive_update(distobj, _di); + Py_DECREF(distobj); if (PyErr_Occurred()) { #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) @@ -802,10 +800,11 @@ handle_update_field_owner() { PyObject *doId = PyLong_FromUnsignedLong(do_id); // pass the update to the owner view first - PyObject *distobjOV = PyDict_GetItem(doId2ownerView, doId); + PyObject *distobjOV; + int result = PyDict_GetItemRef(doId2ownerView, doId, &distobjOV); Py_DECREF(doId2ownerView); - if (distobjOV != nullptr) { + if (result > 0) { PyObject *dclass_obj = PyObject_GetAttrString(distobjOV, "dclass"); nassertr(dclass_obj != nullptr, false); @@ -823,32 +822,29 @@ handle_update_field_owner() { int field_id = packer.raw_unpack_uint16(); DCField *field = dclass->get_field_by_index(field_id); if (field->is_ownrecv()) { - // It's a good idea to ensure the reference count to distobjOV is - // raised while we call the update method--otherwise, the update - // method might get into trouble if it tried to delete the object from - // the doId2do map. - PyObject *distobjOV_ref = Py_NewRef(distobjOV); // make a copy of the datagram iterator so that we can use the main // iterator for the non-owner update DatagramIterator _odi(_di); - invoke_extension(dclass).receive_update(distobjOV_ref, _odi); - Py_DECREF(distobjOV_ref); + invoke_extension(dclass).receive_update(distobjOV, _odi); if (PyErr_Occurred()) { + Py_DECREF(distobjOV); #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) PyGILState_Release(gstate); #endif return false; } } + Py_DECREF(distobjOV); } // now pass the update to the visible view - PyObject *distobj = PyDict_GetItem(doId2do, doId); + PyObject *distobj; + result = PyDict_GetItemRef(doId2do, doId, &distobj); Py_DECREF(doId); Py_DECREF(doId2do); - if (distobj != nullptr) { + if (result > 0) { PyObject *dclass_obj = PyObject_GetAttrString(distobj, "dclass"); nassertr(dclass_obj != nullptr, false); @@ -867,21 +863,17 @@ handle_update_field_owner() { //int field_id = packer.raw_unpack_uint16(); //DCField *field = dclass->get_field_by_index(field_id); if (true) {//field->is_broadcast()) { - // It's a good idea to ensure the reference count to distobj is raised - // while we call the update method--otherwise, the update method might - // get into trouble if it tried to delete the object from the doId2do - // map. - PyObject *distobj_ref = Py_NewRef(distobj); - invoke_extension(dclass).receive_update(distobj_ref, _di); - Py_DECREF(distobj_ref); + invoke_extension(dclass).receive_update(distobj, _di); if (PyErr_Occurred()) { + Py_DECREF(distobj); #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) PyGILState_Release(gstate); #endif return false; } } + Py_DECREF(distobj); } } @@ -995,12 +987,14 @@ describe_message(std::ostream &out, const string &prefix, nassertv(doId2do != nullptr); PyObject *doId = PyLong_FromUnsignedLong(do_id); - PyObject *distobj = PyDict_GetItem(doId2do, doId); + PyObject *distobj; + int result = PyDict_GetItemRef(doId2do, doId, &distobj); Py_DECREF(doId); Py_DECREF(doId2do); - if (distobj != nullptr) { + if (result > 0) { PyObject *dclass_obj = PyObject_GetAttrString(distobj, "dclass"); + Py_DECREF(distobj); nassertv(dclass_obj != nullptr); PyObject *dclass_this = PyObject_GetAttrString(dclass_obj, "this"); diff --git a/direct/src/filter/CommonFilters.py b/direct/src/filter/CommonFilters.py index 85d0a18f16..942b2748f6 100644 --- a/direct/src/filter/CommonFilters.py +++ b/direct/src/filter/CommonFilters.py @@ -100,6 +100,11 @@ void fshader(out float4 o_color : COLOR, """ +class ToneMap: + ACES = object() + PBR_NEUTRAL = object() + + class FilterConfig: pass @@ -279,16 +284,19 @@ class CommonFilters: 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" + tonemap = configuration["HighDynamicRange"] + if tonemap is ToneMap.ACES: + 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 += " out float4 l_position : POSITION,\n" @@ -381,10 +389,30 @@ class CommonFilters: 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" + tonemap = configuration["HighDynamicRange"] + if tonemap is ToneMap.ACES: + # With thanks to Stephen Hill! + 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" + elif tonemap is ToneMap.PBR_NEUTRAL: + text += " const float start_compression = 0.8 - 0.04;\n" + text += " const float desaturation = 0.15;\n" + + text += " float x = min(o_color.r, min(o_color.g, o_color.b));\n" + text += " float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n" + text += " o_color.rgb -= offset;\n" + + text += " float peak = max(o_color.r, max(o_color.g, o_color.b));\n" + + text += " if (peak >= start_compression) {\n" + text += " const float d = 1.0 - start_compression;\n" + text += " float new_peak = 1.0 - d * d / (peak + d - start_compression);\n" + text += " o_color.rgb *= new_peak / peak;\n" + text += " float g = 1.0 - 1.0 / (desaturation * (peak - new_peak) + 1.0);\n" + + text += " o_color.rgb = lerp(o_color.rgb, new_peak * float3(1, 1, 1), g);\n" + text += "}\n" if "GammaAdjust" in configuration: gamma = configuration["GammaAdjust"] @@ -668,10 +696,10 @@ class CommonFilters: return self.reconfigure(old_enable, "SrgbEncode") return True - def setHighDynamicRange(self): + def setHighDynamicRange(self, tonemap=ToneMap.ACES): """ Enables HDR rendering by using a floating-point framebuffer, disabling color clamping on the main scene, and applying a tone map - operator (ACES). + operator (ACES or Khronos PBR Neutral). It may also be necessary to use setExposureAdjust to perform exposure compensation on the scene, depending on the lighting intensity. @@ -679,8 +707,11 @@ class CommonFilters: .. versionadded:: 1.10.7 """ - fullrebuild = (("HighDynamicRange" in self.configuration) is False) - self.configuration["HighDynamicRange"] = 1 + fullrebuild = "HighDynamicRange" not in self.configuration or \ + self.configuration["HighDynamicRange"] is not tonemap + if tonemap is not ToneMap.ACES and tonemap is not ToneMap.PBR_NEUTRAL: + raise ValueError("Invalid value for tonemap") + self.configuration["HighDynamicRange"] = tonemap return self.reconfigure(fullrebuild, "HighDynamicRange") def delHighDynamicRange(self): diff --git a/direct/src/fsm/FSM.py b/direct/src/fsm/FSM.py index 06efc4b1a5..e7a4498691 100644 --- a/direct/src/fsm/FSM.py +++ b/direct/src/fsm/FSM.py @@ -485,9 +485,8 @@ class FSM(DirectObject): new_index = (cur_index + 1) % len(self.stateArray) return self.request(self.stateArray[new_index], args) else: - assert self.notifier.debug( + assert self.notify.debug( "stateArray empty. Can't switch to next.") - finally: self.fsmLock.release() @@ -503,7 +502,7 @@ class FSM(DirectObject): new_index = (cur_index - 1) % len(self.stateArray) return self.request(self.stateArray[new_index], args) else: - assert self.notifier.debug( + assert self.notify.debug( "stateArray empty. Can't switch to next.") finally: self.fsmLock.release() diff --git a/direct/src/interval/cMetaInterval.cxx b/direct/src/interval/cMetaInterval.cxx index 3627a99bc0..a203167557 100644 --- a/direct/src/interval/cMetaInterval.cxx +++ b/direct/src/interval/cMetaInterval.cxx @@ -679,7 +679,7 @@ write(std::ostream &out, int indent_level) const { int total_digits = num_decimals + 4; static const int max_digits = 32; // totally arbitrary nassertv(total_digits <= max_digits); - char format_str[16]; + char format_str[26]; sprintf(format_str, "%%%d.%df", total_digits, num_decimals); indent(out, indent_level) << get_name() << ":\n"; @@ -708,7 +708,7 @@ timeline(std::ostream &out) const { int total_digits = num_decimals + 4; static const int max_digits = 32; // totally arbitrary nassertv(total_digits <= max_digits); - char format_str[16]; + char format_str[26]; sprintf(format_str, "%%%d.%df", total_digits, num_decimals); int extra_indent_level = 0; diff --git a/direct/src/showbase/DistancePhasedNode.py b/direct/src/showbase/DistancePhasedNode.py index fc4c5a471b..5fc12769e0 100755 --- a/direct/src/showbase/DistancePhasedNode.py +++ b/direct/src/showbase/DistancePhasedNode.py @@ -87,7 +87,8 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath): """ Reuse abandoned ids. """ - DistancePhasedNode.__InstanceDeque.append(id) + if DistancePhasedNode is not None: + DistancePhasedNode.__InstanceDeque.append(id) def __init__(self, name, phaseParamMap = {}, autoCleanup = True, diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 75436a4d64..71ed125746 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -32,6 +32,8 @@ built-in scope. """ +from __future__ import annotations + __all__ = ['ShowBase', 'WindowControls'] # This module redefines the builtin import function with one @@ -71,9 +73,11 @@ from panda3d.core import ( GraphicsPipe, GraphicsPipeSelection, GraphicsWindow, + InputDevice, InputDeviceManager, InputDeviceNode, KeyboardButton, + Lens, LensNode, Mat4, ModelNode, @@ -118,9 +122,11 @@ from . import DConfig from direct.extensions_native import NodePath_extensions # pylint: disable=unused-import # This needs to be available early for DirectGUI imports +from typing import Any +builtins: Any # Tell mypy not to worry about us setting attributes on builtins import sys import builtins -builtins.config = DConfig # type: ignore[attr-defined] +builtins.config = DConfig from direct.directnotify.DirectNotifyGlobal import directNotify, giveNotify from direct.directnotify.Notifier import Notifier @@ -141,7 +147,7 @@ import importlib from direct.showbase import ExceptionVarDump from . import DirectObject from . import SfxPlayer -from typing import ClassVar, Optional +from typing import Callable, ClassVar, Literal, NoReturn if __debug__: from direct.showbase import GarbageReport from direct.directutil import DeltaProfiler @@ -150,9 +156,10 @@ if __debug__: @atexit.register -def exitfunc(): - if getattr(builtins, 'base', None) is not None: - builtins.base.destroy() +def exitfunc() -> None: + base = getattr(builtins, 'base', None) + if base is not None: + base.destroy() # Now ShowBase is a DirectObject. We need this so ShowBase can hang # hooks on messages, particularly on window-event. This doesn't @@ -170,7 +177,7 @@ class ShowBase(DirectObject.DirectObject): aspect2d: NodePath pixel2d: NodePath - def __init__(self, fStartDirect=True, windowType=None): + def __init__(self, fStartDirect: bool = True, windowType: str | None = None) -> None: """Opens a window, sets up a 3-D and several 2-D scene graphs, and everything else needed to render the scene graph to the window. @@ -233,10 +240,10 @@ class ShowBase(DirectObject.DirectObject): self.wantRender2dp = ConfigVariableBool('want-render2dp', True).value self.screenshotExtension = ConfigVariableString('screenshot-extension', 'jpg').value - self.musicManager = None - self.musicManagerIsValid = None - self.sfxManagerList = [] - self.sfxManagerIsValidList = [] + self.musicManager: AudioManager | None = None + self.musicManagerIsValid: bool | None = None + self.sfxManagerList: list[AudioManager] = [] + self.sfxManagerIsValidList: list[bool] = [] self.wantStats = ConfigVariableBool('want-pstats', False).value self.wantTk = False @@ -245,12 +252,12 @@ class ShowBase(DirectObject.DirectObject): #: Fill this in with a function to invoke when the user "exits" #: the program by closing the main window. - self.exitFunc = None + self.exitFunc: Callable[[], object] | None = None #: Add final-exit callbacks to this list. These will be called #: when sys.exit() is called, after Panda has unloaded, and #: just before Python is about to shut down. - self.finalExitCallbacks = [] + self.finalExitCallbacks: list[Callable[[], object]] = [] # Set up the TaskManager to reset the PStats clock back # whenever we resume from a pause. This callback function is @@ -268,7 +275,7 @@ class ShowBase(DirectObject.DirectObject): self.__configAspectRatio = ConfigVariableDouble('aspect-ratio', 0).value # This variable is used to see if the aspect ratio has changed when # we get a window-event. - self.__oldAspectRatio = None + self.__oldAspectRatio: float | None = None #: This is set to the value of the window-type config variable, but may #: optionally be overridden in the Showbase constructor. Should either @@ -279,68 +286,68 @@ class ShowBase(DirectObject.DirectObject): self.requireWindow = ConfigVariableBool('require-window', True).value #: This is the main, or only window; see `winList` for a list of *all* windows. - self.win = None - self.frameRateMeter = None - self.sceneGraphAnalyzerMeter = None + self.win: GraphicsOutput | None = None + self.frameRateMeter: FrameRateMeter | None = None + self.sceneGraphAnalyzerMeter: SceneGraphAnalyzerMeter | None = None #: A list of all windows opened via `openWindow()`. - self.winList = [] - self.winControls = [] - self.mainWinMinimized = 0 - self.mainWinForeground = 0 + self.winList: list[GraphicsEngine] = [] + self.winControls: list[WindowControls] = [] + self.mainWinMinimized = False + self.mainWinForeground = False #: Contains the :class:`~panda3d.core.GraphicsPipe` object created by #: `makeDefaultPipe()`. - self.pipe = None + self.pipe: GraphicsPipe | None = None #: The full list of :class:`~panda3d.core.GraphicsPipe` objects, #: including any auxiliary pipes. Filled by `makeAllPipes()`. - self.pipeList = [] - self.mouse2cam = None - self.buttonThrowers = None - self.mouseWatcher = None + self.pipeList: list[GraphicsPipe] = [] + self.mouse2cam: NodePath | None = None + self.buttonThrowers: list[ButtonThrower] | None = None + self.mouseWatcher: NodePath | None = None #: The :class:`~panda3d.core.MouseWatcher` object, created by #: `setupMouse()`. - self.mouseWatcherNode = None - self.pointerWatcherNodes = None - self.mouseInterface = None - self.drive = None - self.trackball = None - self.texmem = None - self.showVertices = None - self.deviceButtonThrowers = [] + self.mouseWatcherNode: MouseWatcher | None = None + self.pointerWatcherNodes: list[MouseWatcher] | None = None + self.mouseInterface: NodePath | None = None + self.drive: NodePath | None = None + self.trackball: NodePath | None = None + self.texmem: Any | None = None + self.showVertices: NodePath | None = None + self.deviceButtonThrowers: list[NodePath] = [] #: This is a :class:`~panda3d.core.NodePath` pointing to the #: :class:`~panda3d.core.Camera` object set up for the 3D scene. #: Usually a child of `camera`. - self.cam = None + self.cam: NodePath | None = None #: Same as `cam`, but for the 2D scene graph. - self.cam2d = None + self.cam2d: NodePath | None = None #: Same as `cam2d`, but for the 2D overlay scene graph. - self.cam2dp = None + self.cam2dp: NodePath | None = None #: This is the :class:`~panda3d.core.NodePath` that should be used to #: manipulate the camera. It points at the node to which the default #: camera (`cam`, `camNode`) is attached. - self.camera = None + self.camera: NodePath | None = None #: Same as `camera`, but for the 2D scene graph. Parent of `cam2d`. - self.camera2d = None + self.camera2d: NodePath | None = None #: Same as `camera2d`, but for the 2D overlay scene graph. Parent of #: `cam2dp`. - self.camera2dp = None + self.camera2dp: NodePath | None = None #: A list of all cameras created with `makeCamera()`, including `cam`. - self.camList = [] + self.camList: list[NodePath] = [] #: Convenience accessor for base.cam.node(), containing a #: :class:`~panda3d.core.Camera` object. - self.camNode = None + self.camNode: Camera | None = None #: Convenience accessor for base.camNode.get_lens(), containing a #: :class:`~panda3d.core.Lens` object. - self.camLens = None - self.camFrustumVis = None + self.camLens: Lens | None = None + self.camFrustumVis: NodePath | None = None self.direct = None #: This is used to store the wx.Application object used when want-wx is #: set or `startWx()` is called. - self.wxApp = None + self.wxApp: Any | None = None self.wxAppCreated = False - self.tkRoot = None + self.tkRoot: Any | None = None self.tkRootCreated = False # This is used for syncing multiple PCs in a distributed cluster @@ -371,11 +378,11 @@ class ShowBase(DirectObject.DirectObject): #: traverse it automatically in the collisionLoop task, so you won't #: need to call :meth:`~panda3d.core.CollisionTraverser.traverse()` #: yourself every frame. - self.cTrav = 0 - self.shadowTrav = 0 + self.cTrav: CollisionTraverser | Literal[0] = 0 + self.shadowTrav: CollisionTraverser | Literal[0] = 0 self.cTravStack = Stack() # Ditto for an AppTraverser. - self.appTrav = 0 + self.appTrav: Any | Literal[0] = 0 # This is the DataGraph traverser, which we might as well # create now. @@ -383,7 +390,7 @@ class ShowBase(DirectObject.DirectObject): # Maybe create a RecorderController to record and/or play back # the user session. - self.recorder = None + self.recorder: RecorderController | None = None playbackSession = ConfigVariableFilename('playback-session', '') recordSession = ConfigVariableFilename('record-session', '') if not playbackSession.empty(): @@ -448,22 +455,22 @@ class ShowBase(DirectObject.DirectObject): #: If `enableParticles()` has been called, this is the particle manager #: as imported from :mod:`direct.particles.ParticleManagerGlobal`. self.particleMgr = None - self.particleMgrEnabled = 0 + self.particleMgrEnabled = False #: If `enableParticles()` has been called, this is the physics manager #: as imported from :mod:`direct.showbase.PhysicsManagerGlobal`. self.physicsMgr = None - self.physicsMgrEnabled = 0 - self.physicsMgrAngular = 0 + self.physicsMgrEnabled = False + self.physicsMgrAngular = False #: This is the global :class:`~panda3d.core.InputDeviceManager`, which #: keeps track of connected input devices. self.devices = InputDeviceManager.getGlobalPtr() - self.__inputDeviceNodes = {} + self.__inputDeviceNodes: dict[InputDevice, NodePath] = {} self.createStats() - self.AppHasAudioFocus = 1 + self.AppHasAudioFocus = True # Get a pointer to Panda's global ClockObject, used for # synchronizing events between Python and C. @@ -502,7 +509,7 @@ class ShowBase(DirectObject.DirectObject): affinity = ConfigVariableInt('client-cpu-affinity', -1).value if (affinity in (None, -1)) and autoAffinity: affinity = 0 - if affinity not in (None, -1): + if affinity is not None and affinity != -1: # Windows XP supports a 32-bit affinity mask TrueClock.getGlobalPtr().setCpuAffinity(1 << (affinity % 32)) @@ -575,7 +582,7 @@ class ShowBase(DirectObject.DirectObject): # Now hang a hook on the window-event from Panda. This allows # us to detect when the user resizes, minimizes, or closes the # main window. - self.__prevWindowProperties = None + self.__prevWindowProperties: WindowProperties | None = None self.__directObject.accept('window-event', self.windowEvent) # Transition effects (fade, iris, etc) @@ -658,7 +665,7 @@ class ShowBase(DirectObject.DirectObject): #print getDnaPath() print("}") - def destroy(self): + def destroy(self) -> None: """ Call this function to destroy the ShowBase and stop all its tasks, freeing all of the Panda resources. Normally, you should not need to call it explicitly, as it is bound to the @@ -704,6 +711,7 @@ class ShowBase(DirectObject.DirectObject): self.shutdown() if getattr(self, 'musicManager', None): + assert self.musicManager is not None self.musicManager.shutdown() self.musicManager = None for sfxManager in self.sfxManagerList: @@ -711,12 +719,12 @@ class ShowBase(DirectObject.DirectObject): self.sfxManagerList = [] if getattr(self, 'loader', None): self.loader.destroy() - self.loader = None + del self.loader if getattr(self, 'graphicsEngine', None): self.graphicsEngine.removeAllWindows() try: - self.direct.panel.destroy() + self.direct.panel.destroy() # type: ignore[attr-defined] except Exception: pass @@ -1185,7 +1193,7 @@ class ShowBase(DirectObject.DirectObject): self.setSceneGraphAnalyzerMeter(flag.value) return success - def setSleep(self, amount): + def setSleep(self, amount: float) -> None: """ Sets up a task that calls python 'sleep' every frame. This is a simple way to reduce the CPU usage (and frame rate) of a panda program. @@ -1205,7 +1213,7 @@ class ShowBase(DirectObject.DirectObject): #time.sleep(self.clientSleep) return Task.cont - def setFrameRateMeter(self, flag): + def setFrameRateMeter(self, flag: bool) -> None: """ Turns on or off (according to flag) a standard frame rate meter in the upper-right corner of the main window. @@ -1219,7 +1227,7 @@ class ShowBase(DirectObject.DirectObject): self.frameRateMeter.clearWindow() self.frameRateMeter = None - def setSceneGraphAnalyzerMeter(self, flag): + def setSceneGraphAnalyzerMeter(self, flag: bool) -> None: """ Turns on or off (according to flag) a standard frame rate meter in the upper-right corner of the main window. @@ -1242,7 +1250,7 @@ class ShowBase(DirectObject.DirectObject): mouseKeyboard = self.dataRoot.find("**/*")) self.winControls.append(winCtrl) - def setupRender(self): + def setupRender(self) -> None: """ Creates the render scene graph, the primary scene graph for rendering 3-d geometry. @@ -1252,11 +1260,11 @@ class ShowBase(DirectObject.DirectObject): self.render.setAttrib(RescaleNormalAttrib.makeDefault()) self.render.setTwoSided(0) - self.backfaceCullingEnabled = 1 - self.textureEnabled = 1 - self.wireframeEnabled = 0 + self.backfaceCullingEnabled = True + self.textureEnabled = True + self.wireframeEnabled = False - def setupRender2d(self): + def setupRender2d(self) -> None: """ Creates the render2d scene graph, the primary scene graph for 2-d objects and gui elements that are superimposed over the @@ -1355,7 +1363,7 @@ class ShowBase(DirectObject.DirectObject): if xsize > 0 and ysize > 0: self.pixel2d.setScale(2.0 / xsize, 1.0, 2.0 / ysize) - def setupRender2dp(self): + def setupRender2dp(self) -> None: """ Creates a render2d scene graph, the secondary scene graph for 2-d objects and gui elements that are superimposed over the @@ -1677,7 +1685,7 @@ class ShowBase(DirectObject.DirectObject): return camera2dp - def setupDataGraph(self): + def setupDataGraph(self) -> None: """ Creates the data graph and populates it with the basic input devices. @@ -2006,7 +2014,7 @@ class ShowBase(DirectObject.DirectObject): self.physicsMgr.doPhysics(dt) return Task.cont - def createStats(self, hostname=None, port=None): + def createStats(self, hostname: str | None = None, port: int | None = None) -> bool: """ If want-pstats is set in Config.prc, or the `wantStats` member is otherwise set to True, connects to the PStats server. @@ -2323,7 +2331,7 @@ class ShowBase(DirectObject.DirectObject): throw_new_frame() return Task.cont - def restart(self, clusterSync=False, cluster=None): + def restart(self, clusterSync: bool = False, cluster=None) -> None: self.shutdown() # __resetPrevTransform goes at the very beginning of the frame. self.taskMgr.add( @@ -2354,7 +2362,7 @@ class ShowBase(DirectObject.DirectObject): self.taskMgr.add(self.__audioLoop, 'audioLoop', sort = 60) self.eventMgr.restart() - def shutdown(self): + def shutdown(self) -> None: self.taskMgr.remove('audioLoop') self.taskMgr.remove('igLoop') self.taskMgr.remove('shadowCollisionLoop') @@ -3195,14 +3203,14 @@ class ShowBase(DirectObject.DirectObject): # If anybody needs to update their GUI, put a callback on this event messenger.send("aspectRatioChanged") - def userExit(self): + def userExit(self) -> NoReturn: # The user has requested we exit the program. Deal with this. if self.exitFunc: self.exitFunc() self.notify.info("Exiting ShowBase.") self.finalizeExit() - def finalizeExit(self): + def finalizeExit(self) -> NoReturn: """ Called by `userExit()` to quit the application. The default implementation just calls `sys.exit()`. diff --git a/direct/src/showbase/Transitions.py b/direct/src/showbase/Transitions.py index 159e62f3b2..1db17d97a4 100644 --- a/direct/src/showbase/Transitions.py +++ b/direct/src/showbase/Transitions.py @@ -327,8 +327,6 @@ class Transitions: else: self.transitionIval = self.getIrisInIval(t, finishIval, blendType) self.__transitionFuture = AsyncFuture() - if finishIval: - self.transitionIval.append(finishIval) self.transitionIval.start() return self.__transitionFuture @@ -349,8 +347,6 @@ class Transitions: else: self.transitionIval = self.getIrisOutIval(t, finishIval, blendType) self.__transitionFuture = AsyncFuture() - if finishIval: - self.transitionIval.append(finishIval) self.transitionIval.start() return self.__transitionFuture diff --git a/direct/src/stdpy/glob.py b/direct/src/stdpy/glob.py index 3b4f0fefb5..8944548a6c 100755 --- a/direct/src/stdpy/glob.py +++ b/direct/src/stdpy/glob.py @@ -52,7 +52,7 @@ def glob1(dirname, pattern): if not dirname: dirname = os.curdir try: - names = os.listdir(dirname) + names = file.listdir(dirname) except os.error: return [] if pattern[0] != '.': diff --git a/doc/CODING_STYLE.md b/doc/CODING_STYLE.md index 614057737d..05814b74e1 100644 --- a/doc/CODING_STYLE.md +++ b/doc/CODING_STYLE.md @@ -184,7 +184,7 @@ Try to group logically-similar lines, separating them with a single blank line. Modern language features ------------------------ -Panda3D is a C++11 project. The use of the following modern language features +Panda3D is a C++14 project. The use of the following modern language features is greatly encouraged: 1. `nullptr` over `NULL` @@ -197,4 +197,4 @@ creating a typedef for the container type instead. Avoid using `std::function` in cases where a lambda can be accepted directly (using a template function), since it has extra overhead over lambdas. -C++14 and C++17 features should be avoided for now. +C++17 features should be avoided for now. diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index 97a15ddbe8..e5651145b7 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -1,3 +1,64 @@ +----------------------- RELEASE 1.10.15 ----------------------- + +This release adds support for Python 3.13, and fixes some significant bugs. +Upgrading is highly recommended. + +Windowing +* Fix regression related to fullscreen switching on Windows (#1594) +* Fix issues related to fullscreen switching corner cases on macOS +* Fix keyUp event being eaten when switching fullscreen modes on macOS +* Support UTF-8 window titles on X11 +* Fix wrong error message on X11 if xf86dga extension is not found + +Rendering +* Add "Khronos PBR Neutral" tone mapping operator to HDR filter (#1659) +* OpenGL: Fix offscreen buffer clearing if back buffers are requested +* DirectX 9: Fix crash on window event after window close +* DirectX 9: Fix support for r32f and rgba32f textures +* DirectX 9: Fix crash when copying inverted framebuffer to texture RAM +* DirectX 9: Fix buffer crash if main window has no depth buffer + +Text +* Fix handling of surrogate pairs in text on Windows (#1629) +* Fix disabling text-native-antialias setting not working properly +* Fix small-caps not working with text-use-harfbuzz enabled (#1666) +* Show error instead of crash if glyph does not fit in page (#1626) +* Update docstring for set_text_color() (#1621) + +GUI +* Fix crash when PGEntry removes itself with background focus (#1650) +* Fix `PGEntry::get_cursor_Y()`, which always returned 0.0 (#1633) +* Now makes copies of mutable default values in DirectGUI constructor (#1587) + +Deployment +* Fix wrong relative paths with bam_model_extensions (#1642) +* Add bam_embed_textures option to embed textures in .bam files +* Don't warn about missing ld-linux library on aarch64 Linux +* build_apps dist hooks no longer import Panda3D (#1624) + +Miscellaneous +* Fix major memory leak on M1/M2/M3 Macs +* Fix seeking in OpenAL sounds not working on macOS in some cases (#1607) +* Fix direct.stdpy.glob not finding files in VFS (#1675) +* Improve printing of floating-point linmath objects (#1671) +* Fix VFS mount points not being listed as directories (#1244) +* Fix splits occurring in RopeNode geometry (#1325) +* Fix DistancePhasedNode exception at module clean-up time +* Fix magfilter on KW_mipmap in egg-palettize (#1631) +* Fix creating LerpFunctionInterval from functools.partial (#1623) +* Fix "no attribute notifier" in FSM.requestNext/Prev (#1644) +* Fix file_texture_mode property on BamWriter being read-only +* TransformState getters no longer return references to temporary (#1625) + +Build +* Assorted build fixes for Python 3.13 and 3.13t +* Fix assorted compiler warnings +* Build fix for newer FFmpeg versions +* Add --ignore option to test_wheel.py to allow ignoring tests +* Update Eigen to 3.2.10 (fixes binder2nd error when building with C++17) +* Fix non-determinism in Python bindings (#1651) +* Fix preprocessor issues in interrogate (#1635) + ----------------------- RELEASE 1.10.14 ----------------------- This release adds support for Python 3.12 and furthermore contains significant diff --git a/dtool/CompilerFlags.cmake b/dtool/CompilerFlags.cmake index 48f931387f..31d96279e3 100644 --- a/dtool/CompilerFlags.cmake +++ b/dtool/CompilerFlags.cmake @@ -51,8 +51,8 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GCC") endif() -# Panda3D is now a C++11 project. -set(CMAKE_CXX_STANDARD 11) +# Panda3D is now a C++14 project. +set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Set certain CMake flags we expect @@ -190,8 +190,8 @@ else() check_cxx_compiler_flag("-fno-rtti" COMPILER_SUPPORTS_FRTTI) if(COMPILER_SUPPORTS_FRTTI) - set(cxx_rtti_on "-frtti") - set(cxx_rtti_off "-fno-rtti") + set(cxx_rtti_on "$<$,$>:-frtti>") + set(cxx_rtti_off "$<$,$>:-fno-rtti>") else() set(cxx_rtti_on) diff --git a/dtool/Config.cmake b/dtool/Config.cmake index 771e105be5..f3063d86ad 100644 --- a/dtool/Config.cmake +++ b/dtool/Config.cmake @@ -265,7 +265,7 @@ if(BUILD_INTERROGATE) panda3d-interrogate GIT_REPOSITORY https://github.com/panda3d/interrogate.git - GIT_TAG e297384b30f1eae8ab839ec096fc3bb6bdb3edeb + GIT_TAG 03418d6d7ddda7fb99abf27230aa42d1d8bd607e PREFIX ${_interrogate_dir} CMAKE_ARGS diff --git a/dtool/Package.cmake b/dtool/Package.cmake index 42758c2702..dfa6c5772a 100644 --- a/dtool/Package.cmake +++ b/dtool/Package.cmake @@ -1,9 +1,54 @@ -set(_thirdparty_dir_default "${PROJECT_SOURCE_DIR}/thirdparty") -if(NOT IS_DIRECTORY "${_thirdparty_dir_default}") - set(_thirdparty_dir_default "") +set(_thirdparty_platform) + +if(APPLE) + set(_thirdparty_platform "darwin-libs-a") + +elseif(WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_thirdparty_platform "win-libs-vc14-x64") + else() + set(_thirdparty_platform "win-libs-vc14") + endif() + +elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(_thirdparty_platform "linux-libs-arm64") + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_thirdparty_platform "linux-libs-x64") + else() + set(_thirdparty_platform "linux-libs-a") + endif() + +elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(_thirdparty_platform "freebsd-libs-arm64") + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_thirdparty_platform "freebsd-libs-x64") + else() + set(_thirdparty_platform "freebsd-libs-a") + endif() + +elseif(CMAKE_SYSTEM_NAME STREQUAL "Android") + set(_thirdparty_platform "android-libs-${CMAKE_ANDROID_ARCH}") + +elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + set(_thirdparty_platform "emscripten-libs") + +elseif(CMAKE_SYSTEM_NAME STREQUAL "WASI") + set(_thirdparty_platform "wasi-libs-${CMAKE_SYSTEM_PROCESSOR}") + endif() -if(CMAKE_SYSTEM_NAME STREQUAL "WASI") - set(_thirdparty_dir_default "") + +set(_thirdparty_dir_default "") +if(_thirdparty_platform) + if(IS_DIRECTORY "${PROJECT_SOURCE_DIR}/thirdparty/${_thirdparty_platform}") + set(_thirdparty_dir_default "${PROJECT_SOURCE_DIR}/thirdparty") + + else() + message(WARNING + "Ignoring thirdparty directory without ${_thirdparty_platform} subdirectory.") + + endif() endif() set(THIRDPARTY_DIRECTORY "${_thirdparty_dir_default}" CACHE PATH @@ -14,6 +59,11 @@ set(THIRDPARTY_DIRECTORY "${_thirdparty_dir_default}" CACHE PATH set(THIRDPARTY_DLLS) if(THIRDPARTY_DIRECTORY) + if(NOT _thirdparty_platform) + message(FATAL_ERROR + "You can't use THIRDPARTY_DIRECTORY on this platform. Unset it to continue.") + endif() + # This policy is necessary for PackageName_ROOT variables to be respected if(POLICY CMP0074) cmake_policy(GET CMP0074 _policy_cmp0074) @@ -24,63 +74,14 @@ if(THIRDPARTY_DIRECTORY) "Your version of CMake is too old; please upgrade or unset THIRDPARTY_DIRECTORY to continue.") endif() - # Dig up the actual "libs" directory if(APPLE) - set(_package_dir "${THIRDPARTY_DIRECTORY}/darwin-libs-a") - # Make sure thirdparty has the first shot, not system frameworks set(CMAKE_FIND_FRAMEWORK LAST) elseif(WIN32) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(_package_dir "${THIRDPARTY_DIRECTORY}/win-libs-vc14-x64") - - file(GLOB _python_dirs "${THIRDPARTY_DIRECTORY}/win-python*-x64") - else() - set(_package_dir "${THIRDPARTY_DIRECTORY}/win-libs-vc14") - - file(GLOB _python_dirs "${THIRDPARTY_DIRECTORY}/win-python*") - endif() - - list(REVERSE _python_dirs) # Descending order of version - if(NOT DEFINED Python_ROOT) - set(Python_ROOT "${_python_dirs}") - endif() - set(BISON_ROOT "${THIRDPARTY_DIRECTORY}/win-util") set(FLEX_ROOT "${THIRDPARTY_DIRECTORY}/win-util") - elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") - set(_package_dir ${THIRDPARTY_DIRECTORY}/linux-libs-arm64) - elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(_package_dir ${THIRDPARTY_DIRECTORY}/linux-libs-x64) - else() - set(_package_dir ${THIRDPARTY_DIRECTORY}/linux-libs-a) - endif() - - elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") - set(_package_dir ${THIRDPARTY_DIRECTORY}/freebsd-libs-arm64) - elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(_package_dir ${THIRDPARTY_DIRECTORY}/freebsd-libs-x64) - else() - set(_package_dir ${THIRDPARTY_DIRECTORY}/freebsd-libs-a) - endif() - - elseif(CMAKE_SYSTEM_NAME STREQUAL "Android") - set(_package_dir ${THIRDPARTY_DIRECTORY}/android-libs-${CMAKE_ANDROID_ARCH}) - - else() - message(FATAL_ERROR - "You can't use THIRDPARTY_DIRECTORY on this platform. Unset it to continue.") - - endif() - - if(NOT EXISTS "${_package_dir}") - message(FATAL_ERROR - "Either your THIRDPARTY_DIRECTORY path does not exist, or it is for the wrong platform.") - endif() foreach(_Package @@ -133,7 +134,7 @@ if(THIRDPARTY_DIRECTORY) endif() # Set search path - set(${_Package}_ROOT "${_package_dir}/${_package}") + set(${_Package}_ROOT "${THIRDPARTY_DIRECTORY}/${_thirdparty_platform}/${_package}") # Set up copying DLLs, if necessary file(GLOB _dlls "${${_Package}_ROOT}/bin/*.dll") @@ -200,6 +201,27 @@ if(DEFINED _PREV_WANT_PYTHON_VERSION endif() +# Look for Python in the thirdparty directory on Windows. +if(WIN32 AND THIRDPARTY_DIRECTORY) + set(_python_dir_suffix "") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_python_dir_suffix "-x64") + endif() + + if(WANT_PYTHON_VERSION) + set(Python_ROOT_DIR "${THIRDPARTY_DIRECTORY}/win-python${WANT_PYTHON_VERSION}${_python_dir_suffix}") + else() + # CMake doesn't support NATURAL sorting until 3.18, so we sort the 3.1x + # versions separately from the prior versions. + file(GLOB _python_dirs "${THIRDPARTY_DIRECTORY}/win-python3.[0-9][0-9]${_python_dir_suffix}") + file(GLOB _python_dirs2 "${THIRDPARTY_DIRECTORY}/win-python3.[0-9]${_python_dir_suffix}") + list(SORT _python_dirs COMPARE FILE_BASENAME CASE INSENSITIVE ORDER DESCENDING) + list(SORT _python_dirs2 COMPARE FILE_BASENAME CASE INSENSITIVE ORDER DESCENDING) + list(APPEND _python_dirs ${_python_dirs2}) + set(Python_ROOT_DIR "${_python_dirs}") + endif() +endif() + if(WANT_PYTHON_VERSION) # A specific version is requested; ensure we get that specific version list(APPEND WANT_PYTHON_VERSION "EXACT") @@ -319,6 +341,104 @@ if(HAVE_PYTHON) set(PYTHON_EXTENSION_SUFFIX "${_EXT_SUFFIX}" CACHE STRING "Suffix for Python binary extension modules.") + # Determine the platform to use for .whl files. + if(WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_platform "win-amd64") + else() + set(_platform "win32") + endif() + + elseif(APPLE) + if(NOT CMAKE_OSX_ARCHITECTURES) + set(_arch_tag ${CMAKE_SYSTEM_PROCESSOR}) + + elseif("x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES) + if("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES) + set(_arch_tag "universal2") + + elseif("i386" IN_LIST CMAKE_OSX_ARCHITECTURES AND + "ppc64" IN_LIST CMAKE_OSX_ARCHITECTURES AND + "ppc" IN_LIST CMAKE_OSX_ARCHITECTURES) + set(_arch_tag "universal") + + elseif("i386" IN_LIST CMAKE_OSX_ARCHITECTURES AND + "ppc" IN_LIST CMAKE_OSX_ARCHITECTURES) + set(_arch_tag "fat32") + + elseif("ppc64" IN_LIST CMAKE_OSX_ARCHITECTURES) + set(_arch_tag "fat64") + + elseif("i386" IN_LIST CMAKE_OSX_ARCHITECTURES) + set(_arch_tag "intel") + + else() + set(_arch_tag "x86_64") + + endif() + + elseif("i386" IN_LIST CMAKE_OSX_ARCHITECTURES AND + "ppc" IN_LIST CMAKE_OSX_ARCHITECTURES) + set(_arch_tag "fat") + + else() + list(GET CMAKE_OSX_ARCHITECTURES 0 _arch_tag) + + endif() + + set(_target "${CMAKE_OSX_DEPLOYMENT_TARGET}") + + if(_arch_tag STREQUAL "arm64" AND _target VERSION_LESS "11.0") + set(_target "11.0") + + elseif(PYTHON_VERSION_STRING VERSION_GREATER_EQUAL "3.13" AND _target VERSION_LESS "10.13") + set(_target "10.13") + + elseif(PYTHON_VERSION_STRING VERSION_GREATER_EQUAL "3.8" AND _target VERSION_LESS "10.9") + set(_target "10.9") + + endif() + + set(_platform "macosx-${_target}-${_arch_tag}") + + elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(_platform "linux-${CMAKE_SYSTEM_PROCESSOR}") + + if(IS_DIRECTORY "/opt/python") + # Sloppy detection for manylinux. + if(EXISTS "/lib64/libc-2.5.so" OR EXISTS "/lib/libc-2.5.so") + set(_platform "manylinux1-${CMAKE_SYSTEM_PROCESSOR}") + + elseif(EXISTS "/lib64/libc-2.12.so" OR EXISTS "/lib/libc-2.12.so") + set(_platform "manylinux2010-${CMAKE_SYSTEM_PROCESSOR}") + + elseif(EXISTS "/lib64/libc-2.17.so" OR EXISTS "/lib/libc-2.17.so") + set(_platform "manylinux2014-${CMAKE_SYSTEM_PROCESSOR}") + + elseif(EXISTS "/lib/x86_64-linux-gnu/libc-2.24.so" OR EXISTS "/lib/i386-linux-gnu/libc-2.24.so") + set(_platform "manylinux_2_24-${CMAKE_SYSTEM_PROCESSOR}") + + elseif(EXISTS "/etc/almalinux-release" AND EXISTS "/lib64/libc-2.28.so") + set(_platform "manylinux_2_28-${CMAKE_SYSTEM_PROCESSOR}") + + endif() + endif() + + elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + set(_platform "emscripten-${CMAKE_SYSTEM_PROCESSOR}") + + else() + set(_platform "") + + endif() + + # This is being read out of the CMake cache by makewheel.py. + if(_platform) + set(PYTHON_PLATFORM_TAG "${_platform}" CACHE STRING "" FORCE) + else() + unset(PYTHON_PLATFORM_TAG CACHE) + endif() + endif() if(NOT DEFINED _PREV_PYTHON_VALUES) diff --git a/dtool/metalibs/dtoolconfig/pydtool.cxx b/dtool/metalibs/dtoolconfig/pydtool.cxx deleted file mode 100644 index 38b6e6359a..0000000000 --- a/dtool/metalibs/dtoolconfig/pydtool.cxx +++ /dev/null @@ -1,3112 +0,0 @@ -/* - * This file was generated by: - * interrogate -D EXPCL_DTOOLCONFIG= -nodb -python -promiscuous -I../../../built/include -module panda3d.interrogatedb -library interrogatedb -string -true-names -do-module -oc pydtool.cxx ../../src/interrogatedb/interrogate_interface.h ../../src/interrogatedb/interrogate_request.h - * - */ - -#include - -#include "../../src/interrogatedb/interrogate_interface.h" -#include "../../src/interrogatedb/interrogate_request.h" -#include "dtoolbase.h" - -#undef _POSIX_C_SOURCE -#undef _XOPEN_SOURCE -#define PY_SSIZE_T_CLEAN 1 - -#if PYTHON_FRAMEWORK - #include -#else - #include "Python.h" -#endif - -static PyObject *_inP07yttbRf(PyObject *self, PyObject *args); -static PyObject *_inP07ytda_g(PyObject *self, PyObject *args); -static PyObject *_inP07yt4RgX(PyObject *self, PyObject *args); -static PyObject *_inP07yt3Gip(PyObject *self, PyObject *args); -static PyObject *_inP07ytRKDz(PyObject *self, PyObject *args); -static PyObject *_inP07ytgZ9N(PyObject *self, PyObject *args); -static PyObject *_inP07ytFnRZ(PyObject *self, PyObject *args); -static PyObject *_inP07ytg0Qv(PyObject *self, PyObject *args); -static PyObject *_inP07yttrqw(PyObject *self, PyObject *args); -static PyObject *_inP07ytdmpW(PyObject *self, PyObject *args); -static PyObject *_inP07ytUYgQ(PyObject *self, PyObject *args); -static PyObject *_inP07yt0k7F(PyObject *self, PyObject *args); -static PyObject *_inP07ytfIsr(PyObject *self, PyObject *args); -static PyObject *_inP07ytvysR(PyObject *self, PyObject *args); -static PyObject *_inP07ytYQ_2(PyObject *self, PyObject *args); -static PyObject *_inP07yt3kdv(PyObject *self, PyObject *args); -static PyObject *_inP07ytew01(PyObject *self, PyObject *args); -static PyObject *_inP07ytQna7(PyObject *self, PyObject *args); -static PyObject *_inP07ytkg95(PyObject *self, PyObject *args); -static PyObject *_inP07ytluRc(PyObject *self, PyObject *args); -static PyObject *_inP07yttHdM(PyObject *self, PyObject *args); -static PyObject *_inP07ytDId0(PyObject *self, PyObject *args); -static PyObject *_inP07ytHuAm(PyObject *self, PyObject *args); -static PyObject *_inP07yt_xr0(PyObject *self, PyObject *args); -static PyObject *_inP07ytH5qp(PyObject *self, PyObject *args); -static PyObject *_inP07ytLfJw(PyObject *self, PyObject *args); -static PyObject *_inP07yt_Atg(PyObject *self, PyObject *args); -static PyObject *_inP07ytlBqc(PyObject *self, PyObject *args); -static PyObject *_inP07ytNdUp(PyObject *self, PyObject *args); -static PyObject *_inP07ytlS0p(PyObject *self, PyObject *args); -static PyObject *_inP07ytZZe7(PyObject *self, PyObject *args); -static PyObject *_inP07ytV5S_(PyObject *self, PyObject *args); -static PyObject *_inP07yto9vD(PyObject *self, PyObject *args); -static PyObject *_inP07ytv7tF(PyObject *self, PyObject *args); -static PyObject *_inP07ythOg6(PyObject *self, PyObject *args); -static PyObject *_inP07ytoZUn(PyObject *self, PyObject *args); -static PyObject *_inP07ytq45U(PyObject *self, PyObject *args); -static PyObject *_inP07yt6IPa(PyObject *self, PyObject *args); -static PyObject *_inP07ytU2_B(PyObject *self, PyObject *args); -static PyObject *_inP07ytHFO2(PyObject *self, PyObject *args); -static PyObject *_inP07ytcfjm(PyObject *self, PyObject *args); -static PyObject *_inP07yt3Sjw(PyObject *self, PyObject *args); -static PyObject *_inP07ytgJcX(PyObject *self, PyObject *args); -static PyObject *_inP07ytYlw6(PyObject *self, PyObject *args); -static PyObject *_inP07ytsmnz(PyObject *self, PyObject *args); -static PyObject *_inP07ytxQ10(PyObject *self, PyObject *args); -static PyObject *_inP07yt6gPB(PyObject *self, PyObject *args); -static PyObject *_inP07ytISgV(PyObject *self, PyObject *args); -static PyObject *_inP07ytH3bx(PyObject *self, PyObject *args); -static PyObject *_inP07ytzeUk(PyObject *self, PyObject *args); -static PyObject *_inP07ytUeI5(PyObject *self, PyObject *args); -static PyObject *_inP07ytbmxJ(PyObject *self, PyObject *args); -static PyObject *_inP07ytY8Lc(PyObject *self, PyObject *args); -static PyObject *_inP07ytJAAI(PyObject *self, PyObject *args); -static PyObject *_inP07yt0UXw(PyObject *self, PyObject *args); -static PyObject *_inP07ytuSvx(PyObject *self, PyObject *args); -static PyObject *_inP07ytwpYd(PyObject *self, PyObject *args); -static PyObject *_inP07ytOfNh(PyObject *self, PyObject *args); -static PyObject *_inP07ytf5_U(PyObject *self, PyObject *args); -static PyObject *_inP07ytL3ZB(PyObject *self, PyObject *args); -static PyObject *_inP07ytXw0I(PyObject *self, PyObject *args); -static PyObject *_inP07yt3zru(PyObject *self, PyObject *args); -static PyObject *_inP07ytRrg2(PyObject *self, PyObject *args); -static PyObject *_inP07ytEJCx(PyObject *self, PyObject *args); -static PyObject *_inP07ytWAZr(PyObject *self, PyObject *args); -static PyObject *_inP07ytHQi6(PyObject *self, PyObject *args); -static PyObject *_inP07ytrD_M(PyObject *self, PyObject *args); -static PyObject *_inP07ytYaah(PyObject *self, PyObject *args); -static PyObject *_inP07yt2otr(PyObject *self, PyObject *args); -static PyObject *_inP07ytNP_b(PyObject *self, PyObject *args); -static PyObject *_inP07ytrrrN(PyObject *self, PyObject *args); -static PyObject *_inP07ytjolz(PyObject *self, PyObject *args); -static PyObject *_inP07ytt_JD(PyObject *self, PyObject *args); -static PyObject *_inP07ytwEts(PyObject *self, PyObject *args); -static PyObject *_inP07ytrJWs(PyObject *self, PyObject *args); -static PyObject *_inP07ytpmFD(PyObject *self, PyObject *args); -static PyObject *_inP07ytyYUX(PyObject *self, PyObject *args); -static PyObject *_inP07yt54dn(PyObject *self, PyObject *args); -static PyObject *_inP07ytGMpW(PyObject *self, PyObject *args); -static PyObject *_inP07ytNuBV(PyObject *self, PyObject *args); -static PyObject *_inP07yt9UwA(PyObject *self, PyObject *args); -static PyObject *_inP07yt3FDt(PyObject *self, PyObject *args); -static PyObject *_inP07ytDgOY(PyObject *self, PyObject *args); -static PyObject *_inP07ytf513(PyObject *self, PyObject *args); -static PyObject *_inP07ytsqGH(PyObject *self, PyObject *args); -static PyObject *_inP07yt7shV(PyObject *self, PyObject *args); -static PyObject *_inP07ytA1eF(PyObject *self, PyObject *args); -static PyObject *_inP07yt776V(PyObject *self, PyObject *args); -static PyObject *_inP07ytryup(PyObject *self, PyObject *args); -static PyObject *_inP07ytiytI(PyObject *self, PyObject *args); -static PyObject *_inP07ytZc07(PyObject *self, PyObject *args); -static PyObject *_inP07ytfaH0(PyObject *self, PyObject *args); -static PyObject *_inP07ytGB9D(PyObject *self, PyObject *args); -static PyObject *_inP07ytrppS(PyObject *self, PyObject *args); -static PyObject *_inP07ytO50x(PyObject *self, PyObject *args); -static PyObject *_inP07ytsxxs(PyObject *self, PyObject *args); -static PyObject *_inP07ytMT0z(PyObject *self, PyObject *args); -static PyObject *_inP07ytiW3v(PyObject *self, PyObject *args); -static PyObject *_inP07yt4Px8(PyObject *self, PyObject *args); -static PyObject *_inP07ytNHcs(PyObject *self, PyObject *args); -static PyObject *_inP07ytqHrb(PyObject *self, PyObject *args); -static PyObject *_inP07ytaOqq(PyObject *self, PyObject *args); -static PyObject *_inP07ytpTBb(PyObject *self, PyObject *args); -static PyObject *_inP07ytZUkn(PyObject *self, PyObject *args); -static PyObject *_inP07ytqWOw(PyObject *self, PyObject *args); -static PyObject *_inP07ytHu7x(PyObject *self, PyObject *args); -static PyObject *_inP07ytwGnA(PyObject *self, PyObject *args); -static PyObject *_inP07ytXGxx(PyObject *self, PyObject *args); -static PyObject *_inP07ytj04Z(PyObject *self, PyObject *args); -static PyObject *_inP07ytEOv4(PyObject *self, PyObject *args); -static PyObject *_inP07ytpCqJ(PyObject *self, PyObject *args); -static PyObject *_inP07yt_Pz3(PyObject *self, PyObject *args); -static PyObject *_inP07ytt_06(PyObject *self, PyObject *args); -static PyObject *_inP07ytmuPs(PyObject *self, PyObject *args); -static PyObject *_inP07ytvM8B(PyObject *self, PyObject *args); -static PyObject *_inP07ytap97(PyObject *self, PyObject *args); -static PyObject *_inP07yt0o8D(PyObject *self, PyObject *args); -static PyObject *_inP07ytOoQ2(PyObject *self, PyObject *args); -static PyObject *_inP07ytKuFh(PyObject *self, PyObject *args); -static PyObject *_inP07yto5L6(PyObject *self, PyObject *args); -static PyObject *_inP07ytzgKK(PyObject *self, PyObject *args); -static PyObject *_inP07yt0FIF(PyObject *self, PyObject *args); -static PyObject *_inP07ytZqvD(PyObject *self, PyObject *args); -static PyObject *_inP07ytDyRd(PyObject *self, PyObject *args); -static PyObject *_inP07ytMnKa(PyObject *self, PyObject *args); -static PyObject *_inP07ytRtji(PyObject *self, PyObject *args); -static PyObject *_inP07ytCnbQ(PyObject *self, PyObject *args); -static PyObject *_inP07ytoxqc(PyObject *self, PyObject *args); -static PyObject *_inP07ytZQIS(PyObject *self, PyObject *args); -static PyObject *_inP07ytdUVN(PyObject *self, PyObject *args); -static PyObject *_inP07ytZtNk(PyObject *self, PyObject *args); -static PyObject *_inP07ytihbt(PyObject *self, PyObject *args); -static PyObject *_inP07ytbyPY(PyObject *self, PyObject *args); -static PyObject *_inP07ytAaT6(PyObject *self, PyObject *args); -static PyObject *_inP07ytgL9q(PyObject *self, PyObject *args); -static PyObject *_inP07ytWB97(PyObject *self, PyObject *args); -static PyObject *_inP07ytDUAl(PyObject *self, PyObject *args); -static PyObject *_inP07yt1_Kf(PyObject *self, PyObject *args); -static PyObject *_inP07yt98lD(PyObject *self, PyObject *args); -static PyObject *_inP07yt9SHr(PyObject *self, PyObject *args); -static PyObject *_inP07ytdiZP(PyObject *self, PyObject *args); -static PyObject *_inP07ytTdER(PyObject *self, PyObject *args); -static PyObject *_inP07ytYO56(PyObject *self, PyObject *args); -static PyObject *_inP07ytxtCG(PyObject *self, PyObject *args); -static PyObject *_inP07yt_EB2(PyObject *self, PyObject *args); -static PyObject *_inP07ytEG1l(PyObject *self, PyObject *args); -static PyObject *_inP07yt7tUq(PyObject *self, PyObject *args); -static PyObject *_inP07ytyStU(PyObject *self, PyObject *args); -static PyObject *_inP07ytdM85(PyObject *self, PyObject *args); -static PyObject *_inP07ytk_GN(PyObject *self, PyObject *args); -static PyObject *_inP07yt8QjG(PyObject *self, PyObject *args); -static PyObject *_inP07ytyMtj(PyObject *self, PyObject *args); -static PyObject *_inP07ytHDtN(PyObject *self, PyObject *args); -static PyObject *_inP07ytHFjA(PyObject *self, PyObject *args); -static PyObject *_inP07yt_NPR(PyObject *self, PyObject *args); -static PyObject *_inP07ytcTOH(PyObject *self, PyObject *args); -static PyObject *_inP07ytC5Uk(PyObject *self, PyObject *args); -static PyObject *_inP07ythdU7(PyObject *self, PyObject *args); -static PyObject *_inP07ytQPxU(PyObject *self, PyObject *args); -static PyObject *_inP07ytO7Pz(PyObject *self, PyObject *args); -static PyObject *_inP07ytvu_E(PyObject *self, PyObject *args); -static PyObject *_inP07ytxGUt(PyObject *self, PyObject *args); -static PyObject *_inP07ytzM1P(PyObject *self, PyObject *args); -static PyObject *_inP07ytoY5L(PyObject *self, PyObject *args); -static PyObject *_inP07yte_7S(PyObject *self, PyObject *args); -static PyObject *_inP07ytw_15(PyObject *self, PyObject *args); - - -/* - * Python simple wrapper for - * void interrogate_add_search_directory(char const *dirname) - */ -static PyObject * -_inP07yttbRf(PyObject *, PyObject *args) { - char *param0; - if (PyArg_ParseTuple(args, "s", ¶m0)) { - (::interrogate_add_search_directory)((char const *)param0); - return Py_BuildValue(""); - } - return nullptr; -} - -/* - * Python simple wrapper for - * void interrogate_add_search_path(char const *pathstring) - */ -static PyObject * -_inP07ytda_g(PyObject *, PyObject *args) { - char *param0; - if (PyArg_ParseTuple(args, "s", ¶m0)) { - (::interrogate_add_search_path)((char const *)param0); - return Py_BuildValue(""); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_error_flag(void) - */ -static PyObject * -_inP07yt4RgX(PyObject *, PyObject *args) { - if (PyArg_ParseTuple(args, "")) { - bool return_value = (::interrogate_error_flag)(); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_number_of_manifests(void) - */ -static PyObject * -_inP07yt3Gip(PyObject *, PyObject *args) { - if (PyArg_ParseTuple(args, "")) { - int return_value = (::interrogate_number_of_manifests)(); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * ManifestIndex interrogate_get_manifest(int n) - */ -static PyObject * -_inP07ytRKDz(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - ManifestIndex return_value = (::interrogate_get_manifest)((int)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * ManifestIndex interrogate_get_manifest_by_name(char const *manifest_name) - */ -static PyObject * -_inP07ytgZ9N(PyObject *, PyObject *args) { - char *param0; - if (PyArg_ParseTuple(args, "s", ¶m0)) { - ManifestIndex return_value = (::interrogate_get_manifest_by_name)((char const *)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_manifest_name(ManifestIndex manifest) - */ -static PyObject * -_inP07ytFnRZ(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_manifest_name)((ManifestIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_manifest_definition(ManifestIndex manifest) - */ -static PyObject * -_inP07ytg0Qv(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_manifest_definition)((ManifestIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_manifest_has_type(ManifestIndex manifest) - */ -static PyObject * -_inP07yttrqw(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_manifest_has_type)((ManifestIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_manifest_get_type(ManifestIndex manifest) - */ -static PyObject * -_inP07ytdmpW(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - TypeIndex return_value = (::interrogate_manifest_get_type)((ManifestIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_manifest_has_getter(ManifestIndex manifest) - */ -static PyObject * -_inP07ytUYgQ(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_manifest_has_getter)((ManifestIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_manifest_getter(ManifestIndex manifest) - */ -static PyObject * -_inP07yt0k7F(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_manifest_getter)((ManifestIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_manifest_has_int_value(ManifestIndex manifest) - */ -static PyObject * -_inP07ytfIsr(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_manifest_has_int_value)((ManifestIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_manifest_get_int_value(ManifestIndex manifest) - */ -static PyObject * -_inP07ytvysR(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_manifest_get_int_value)((ManifestIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_element_name(ElementIndex element) - */ -static PyObject * -_inP07ytYQ_2(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_element_name)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_element_scoped_name(ElementIndex element) - */ -static PyObject * -_inP07yt3kdv(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_element_scoped_name)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_element_has_comment(ElementIndex element) - */ -static PyObject * -_inP07ytew01(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_element_has_comment)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_element_comment(ElementIndex element) - */ -static PyObject * -_inP07ytQna7(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_element_comment)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * ElementIndex interrogate_get_element_by_name(char const *element_name) - */ -static PyObject * -_inP07ytkg95(PyObject *, PyObject *args) { - char *param0; - if (PyArg_ParseTuple(args, "s", ¶m0)) { - ElementIndex return_value = (::interrogate_get_element_by_name)((char const *)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * ElementIndex interrogate_get_element_by_scoped_name(char const *element_name) - */ -static PyObject * -_inP07ytluRc(PyObject *, PyObject *args) { - char *param0; - if (PyArg_ParseTuple(args, "s", ¶m0)) { - ElementIndex return_value = (::interrogate_get_element_by_scoped_name)((char const *)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_element_type(ElementIndex element) - */ -static PyObject * -_inP07yttHdM(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - TypeIndex return_value = (::interrogate_element_type)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_element_has_getter(ElementIndex element) - */ -static PyObject * -_inP07ytDId0(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_element_has_getter)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_element_getter(ElementIndex element) - */ -static PyObject * -_inP07ytHuAm(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_element_getter)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_element_has_setter(ElementIndex element) - */ -static PyObject * -_inP07yt_xr0(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_element_has_setter)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_element_setter(ElementIndex element) - */ -static PyObject * -_inP07ytH5qp(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_element_setter)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_element_has_has_function(ElementIndex element) - */ -static PyObject * -_inP07ytLfJw(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_element_has_has_function)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_element_has_function(ElementIndex element) - */ -static PyObject * -_inP07yt_Atg(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_element_has_function)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_element_has_clear_function(ElementIndex element) - */ -static PyObject * -_inP07ytlBqc(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_element_has_clear_function)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_element_clear_function(ElementIndex element) - */ -static PyObject * -_inP07ytNdUp(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_element_clear_function)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_element_has_del_function(ElementIndex element) - */ -static PyObject * -_inP07ytlS0p(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_element_has_del_function)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_element_del_function(ElementIndex element) - */ -static PyObject * -_inP07ytZZe7(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_element_del_function)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_element_has_insert_function(ElementIndex element) - */ -static PyObject * -_inP07ytV5S_(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_element_has_insert_function)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_element_insert_function(ElementIndex element) - */ -static PyObject * -_inP07yto9vD(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_element_insert_function)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_element_has_getkey_function(ElementIndex element) - */ -static PyObject * -_inP07ytv7tF(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_element_has_getkey_function)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_element_getkey_function(ElementIndex element) - */ -static PyObject * -_inP07ythOg6(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_element_getkey_function)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_element_length_function(ElementIndex element) - */ -static PyObject * -_inP07ytoZUn(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_element_length_function)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_element_is_sequence(ElementIndex element) - */ -static PyObject * -_inP07ytq45U(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_element_is_sequence)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_element_is_mapping(ElementIndex element) - */ -static PyObject * -_inP07yt6IPa(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_element_is_mapping)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_number_of_globals(void) - */ -static PyObject * -_inP07ytU2_B(PyObject *, PyObject *args) { - if (PyArg_ParseTuple(args, "")) { - int return_value = (::interrogate_number_of_globals)(); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * ElementIndex interrogate_get_global(int n) - */ -static PyObject * -_inP07ytHFO2(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - ElementIndex return_value = (::interrogate_get_global)((int)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_number_of_global_functions(void) - */ -static PyObject * -_inP07ytcfjm(PyObject *, PyObject *args) { - if (PyArg_ParseTuple(args, "")) { - int return_value = (::interrogate_number_of_global_functions)(); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_get_global_function(int n) - */ -static PyObject * -_inP07yt3Sjw(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_get_global_function)((int)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_number_of_functions(void) - */ -static PyObject * -_inP07ytgJcX(PyObject *, PyObject *args) { - if (PyArg_ParseTuple(args, "")) { - int return_value = (::interrogate_number_of_functions)(); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_get_function(int n) - */ -static PyObject * -_inP07ytYlw6(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_get_function)((int)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_function_name(FunctionIndex function) - */ -static PyObject * -_inP07ytsmnz(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_function_name)((FunctionIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_function_scoped_name(FunctionIndex function) - */ -static PyObject * -_inP07ytxQ10(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_function_scoped_name)((FunctionIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_function_has_comment(FunctionIndex function) - */ -static PyObject * -_inP07yt6gPB(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_function_has_comment)((FunctionIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_function_comment(FunctionIndex function) - */ -static PyObject * -_inP07ytISgV(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_function_comment)((FunctionIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_function_prototype(FunctionIndex function) - */ -static PyObject * -_inP07ytH3bx(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_function_prototype)((FunctionIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_function_is_method(FunctionIndex function) - */ -static PyObject * -_inP07ytzeUk(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_function_is_method)((FunctionIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_function_class(FunctionIndex function) - */ -static PyObject * -_inP07ytUeI5(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - TypeIndex return_value = (::interrogate_function_class)((FunctionIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_function_is_unary_op(FunctionIndex function) - */ -static PyObject * -_inP07ytbmxJ(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_function_is_unary_op)((FunctionIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_function_is_operator_typecast(FunctionIndex function) - */ -static PyObject * -_inP07ytY8Lc(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_function_is_operator_typecast)((FunctionIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_function_is_constructor(FunctionIndex function) - */ -static PyObject * -_inP07ytJAAI(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_function_is_constructor)((FunctionIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_function_is_destructor(FunctionIndex function) - */ -static PyObject * -_inP07yt0UXw(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_function_is_destructor)((FunctionIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_function_has_module_name(FunctionIndex function) - */ -static PyObject * -_inP07ytuSvx(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_function_has_module_name)((FunctionIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_function_module_name(FunctionIndex function) - */ -static PyObject * -_inP07ytwpYd(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_function_module_name)((FunctionIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_function_has_library_name(FunctionIndex function) - */ -static PyObject * -_inP07ytOfNh(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_function_has_library_name)((FunctionIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_function_library_name(FunctionIndex function) - */ -static PyObject * -_inP07ytf5_U(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_function_library_name)((FunctionIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_function_is_virtual(FunctionIndex function) - */ -static PyObject * -_inP07ytL3ZB(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_function_is_virtual)((FunctionIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_function_number_of_c_wrappers(FunctionIndex function) - */ -static PyObject * -_inP07ytXw0I(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_function_number_of_c_wrappers)((FunctionIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionWrapperIndex interrogate_function_c_wrapper(FunctionIndex function, int n) - */ -static PyObject * -_inP07yt3zru(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - FunctionWrapperIndex return_value = (::interrogate_function_c_wrapper)((FunctionIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_function_number_of_python_wrappers(FunctionIndex function) - */ -static PyObject * -_inP07ytRrg2(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_function_number_of_python_wrappers)((FunctionIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionWrapperIndex interrogate_function_python_wrapper(FunctionIndex function, int n) - */ -static PyObject * -_inP07ytEJCx(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - FunctionWrapperIndex return_value = (::interrogate_function_python_wrapper)((FunctionIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_wrapper_name(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytWAZr(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_wrapper_name)((FunctionWrapperIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_wrapper_function(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytHQi6(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_wrapper_function)((FunctionWrapperIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytrD_M(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_wrapper_is_callable_by_name)((FunctionWrapperIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_is_copy_constructor(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytYaah(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_wrapper_is_copy_constructor)((FunctionWrapperIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07yt2otr(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_wrapper_is_coerce_constructor)((FunctionWrapperIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_is_extension(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytNP_b(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_wrapper_is_extension)((FunctionWrapperIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_is_deprecated(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytrrrN(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_wrapper_is_deprecated)((FunctionWrapperIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytjolz(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_wrapper_has_comment)((FunctionWrapperIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_wrapper_comment(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytt_JD(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_wrapper_comment)((FunctionWrapperIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_has_return_value(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytwEts(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_wrapper_has_return_value)((FunctionWrapperIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_wrapper_return_type(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytrJWs(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - TypeIndex return_value = (::interrogate_wrapper_return_type)((FunctionWrapperIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_caller_manages_return_value(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytpmFD(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_wrapper_caller_manages_return_value)((FunctionWrapperIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_wrapper_return_value_destructor(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytyYUX(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_wrapper_return_value_destructor)((FunctionWrapperIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_wrapper_number_of_parameters(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07yt54dn(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_wrapper_number_of_parameters)((FunctionWrapperIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_wrapper_parameter_type(FunctionWrapperIndex wrapper, int n) - */ -static PyObject * -_inP07ytGMpW(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - TypeIndex return_value = (::interrogate_wrapper_parameter_type)((FunctionWrapperIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_parameter_has_name(FunctionWrapperIndex wrapper, int n) - */ -static PyObject * -_inP07ytNuBV(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - bool return_value = (::interrogate_wrapper_parameter_has_name)((FunctionWrapperIndex)param0, (int)param1); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_wrapper_parameter_name(FunctionWrapperIndex wrapper, int n) - */ -static PyObject * -_inP07yt9UwA(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - char const *return_value = (::interrogate_wrapper_parameter_name)((FunctionWrapperIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_parameter_is_this(FunctionWrapperIndex wrapper, int n) - */ -static PyObject * -_inP07yt3FDt(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - bool return_value = (::interrogate_wrapper_parameter_is_this)((FunctionWrapperIndex)param0, (int)param1); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_parameter_is_optional(FunctionWrapperIndex wrapper, int n) - */ -static PyObject * -_inP07ytDgOY(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - bool return_value = (::interrogate_wrapper_parameter_is_optional)((FunctionWrapperIndex)param0, (int)param1); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_wrapper_has_pointer(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytf513(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_wrapper_has_pointer)((FunctionWrapperIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * void *interrogate_wrapper_pointer(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07ytsqGH(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - (::interrogate_wrapper_pointer)((FunctionWrapperIndex)param0); - return Py_BuildValue(""); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_wrapper_unique_name(FunctionWrapperIndex wrapper) - */ -static PyObject * -_inP07yt7shV(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_wrapper_unique_name)((FunctionWrapperIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionWrapperIndex interrogate_get_wrapper_by_unique_name(char const *unique_name) - */ -static PyObject * -_inP07ytA1eF(PyObject *, PyObject *args) { - char *param0; - if (PyArg_ParseTuple(args, "s", ¶m0)) { - FunctionWrapperIndex return_value = (::interrogate_get_wrapper_by_unique_name)((char const *)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_make_seq_seq_name(MakeSeqIndex make_seq) - */ -static PyObject * -_inP07yt776V(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_make_seq_seq_name)((MakeSeqIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_make_seq_scoped_name(MakeSeqIndex make_seq) - */ -static PyObject * -_inP07ytryup(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_make_seq_scoped_name)((MakeSeqIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_make_seq_has_comment(ElementIndex element) - */ -static PyObject * -_inP07ytiytI(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_make_seq_has_comment)((ElementIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_make_seq_comment(ElementIndex element) - */ -static PyObject * -_inP07ytZc07(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_make_seq_comment)((ElementIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_make_seq_num_name(MakeSeqIndex make_seq) - */ -static PyObject * -_inP07ytfaH0(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_make_seq_num_name)((MakeSeqIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_make_seq_element_name(MakeSeqIndex make_seq) - */ -static PyObject * -_inP07ytGB9D(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_make_seq_element_name)((MakeSeqIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_make_seq_num_getter(MakeSeqIndex make_seq) - */ -static PyObject * -_inP07ytrppS(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_make_seq_num_getter)((MakeSeqIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_make_seq_element_getter(MakeSeqIndex make_seq) - */ -static PyObject * -_inP07ytO50x(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_make_seq_element_getter)((MakeSeqIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_number_of_global_types(void) - */ -static PyObject * -_inP07ytsxxs(PyObject *, PyObject *args) { - if (PyArg_ParseTuple(args, "")) { - int return_value = (::interrogate_number_of_global_types)(); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_get_global_type(int n) - */ -static PyObject * -_inP07ytMT0z(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - TypeIndex return_value = (::interrogate_get_global_type)((int)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_number_of_types(void) - */ -static PyObject * -_inP07ytiW3v(PyObject *, PyObject *args) { - if (PyArg_ParseTuple(args, "")) { - int return_value = (::interrogate_number_of_types)(); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_get_type(int n) - */ -static PyObject * -_inP07yt4Px8(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - TypeIndex return_value = (::interrogate_get_type)((int)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_get_type_by_name(char const *type_name) - */ -static PyObject * -_inP07ytNHcs(PyObject *, PyObject *args) { - char *param0; - if (PyArg_ParseTuple(args, "s", ¶m0)) { - TypeIndex return_value = (::interrogate_get_type_by_name)((char const *)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_get_type_by_scoped_name(char const *type_name) - */ -static PyObject * -_inP07ytqHrb(PyObject *, PyObject *args) { - char *param0; - if (PyArg_ParseTuple(args, "s", ¶m0)) { - TypeIndex return_value = (::interrogate_get_type_by_scoped_name)((char const *)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_get_type_by_true_name(char const *type_name) - */ -static PyObject * -_inP07ytaOqq(PyObject *, PyObject *args) { - char *param0; - if (PyArg_ParseTuple(args, "s", ¶m0)) { - TypeIndex return_value = (::interrogate_get_type_by_true_name)((char const *)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_global(TypeIndex type) - */ -static PyObject * -_inP07ytpTBb(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_global)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_deprecated(TypeIndex type) - */ -static PyObject * -_inP07ytZUkn(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_deprecated)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_type_name(TypeIndex type) - */ -static PyObject * -_inP07ytqWOw(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_type_name)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_type_scoped_name(TypeIndex type) - */ -static PyObject * -_inP07ytHu7x(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_type_scoped_name)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_type_true_name(TypeIndex type) - */ -static PyObject * -_inP07ytwGnA(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_type_true_name)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_nested(TypeIndex type) - */ -static PyObject * -_inP07ytXGxx(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_nested)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_type_outer_class(TypeIndex type) - */ -static PyObject * -_inP07ytj04Z(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - TypeIndex return_value = (::interrogate_type_outer_class)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_has_comment(TypeIndex type) - */ -static PyObject * -_inP07ytEOv4(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_has_comment)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_type_comment(TypeIndex type) - */ -static PyObject * -_inP07ytpCqJ(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_type_comment)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_has_module_name(TypeIndex type) - */ -static PyObject * -_inP07yt_Pz3(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_has_module_name)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_type_module_name(TypeIndex type) - */ -static PyObject * -_inP07ytt_06(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_type_module_name)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_has_library_name(TypeIndex type) - */ -static PyObject * -_inP07ytmuPs(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_has_library_name)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_type_library_name(TypeIndex type) - */ -static PyObject * -_inP07ytvM8B(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - char const *return_value = (::interrogate_type_library_name)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_atomic(TypeIndex type) - */ -static PyObject * -_inP07ytap97(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_atomic)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * AtomicToken interrogate_type_atomic_token(TypeIndex type) - */ -static PyObject * -_inP07yt0o8D(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - AtomicToken return_value = (::interrogate_type_atomic_token)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_unsigned(TypeIndex type) - */ -static PyObject * -_inP07ytOoQ2(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_unsigned)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_signed(TypeIndex type) - */ -static PyObject * -_inP07ytKuFh(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_signed)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_long(TypeIndex type) - */ -static PyObject * -_inP07yto5L6(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_long)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_longlong(TypeIndex type) - */ -static PyObject * -_inP07ytzgKK(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_longlong)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_short(TypeIndex type) - */ -static PyObject * -_inP07yt0FIF(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_short)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_wrapped(TypeIndex type) - */ -static PyObject * -_inP07ytZqvD(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_wrapped)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_pointer(TypeIndex type) - */ -static PyObject * -_inP07ytDyRd(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_pointer)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_const(TypeIndex type) - */ -static PyObject * -_inP07ytMnKa(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_const)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_typedef(TypeIndex type) - */ -static PyObject * -_inP07ytRtji(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_typedef)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_type_wrapped_type(TypeIndex type) - */ -static PyObject * -_inP07ytCnbQ(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - TypeIndex return_value = (::interrogate_type_wrapped_type)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_array(TypeIndex type) - */ -static PyObject * -_inP07ytoxqc(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_array)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_type_array_size(TypeIndex type) - */ -static PyObject * -_inP07ytZQIS(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_type_array_size)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_enum(TypeIndex type) - */ -static PyObject * -_inP07ytdUVN(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_enum)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_scoped_enum(TypeIndex type) - */ -static PyObject * -_inP07ytZtNk(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_scoped_enum)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_type_number_of_enum_values(TypeIndex type) - */ -static PyObject * -_inP07ytihbt(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_type_number_of_enum_values)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_type_enum_value_name(TypeIndex type, int n) - */ -static PyObject * -_inP07ytbyPY(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - char const *return_value = (::interrogate_type_enum_value_name)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_type_enum_value_scoped_name(TypeIndex type, int n) - */ -static PyObject * -_inP07ytAaT6(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - char const *return_value = (::interrogate_type_enum_value_scoped_name)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * char const *interrogate_type_enum_value_comment(TypeIndex type, int n) - */ -static PyObject * -_inP07ytgL9q(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - char const *return_value = (::interrogate_type_enum_value_comment)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(return_value); -#else - return PyString_FromString(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_type_enum_value(TypeIndex type, int n) - */ -static PyObject * -_inP07ytWB97(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - int return_value = (::interrogate_type_enum_value)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_struct(TypeIndex type) - */ -static PyObject * -_inP07ytDUAl(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_struct)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_class(TypeIndex type) - */ -static PyObject * -_inP07yt1_Kf(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_class)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_union(TypeIndex type) - */ -static PyObject * -_inP07yt98lD(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_union)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_fully_defined(TypeIndex type) - */ -static PyObject * -_inP07yt9SHr(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_fully_defined)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_unpublished(TypeIndex type) - */ -static PyObject * -_inP07ytdiZP(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_unpublished)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_type_number_of_constructors(TypeIndex type) - */ -static PyObject * -_inP07ytTdER(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_type_number_of_constructors)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_type_get_constructor(TypeIndex type, int n) - */ -static PyObject * -_inP07ytYO56(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - FunctionIndex return_value = (::interrogate_type_get_constructor)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_has_destructor(TypeIndex type) - */ -static PyObject * -_inP07ytxtCG(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_has_destructor)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_destructor_is_inherited(TypeIndex type) - */ -static PyObject * -_inP07yt_EB2(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_destructor_is_inherited)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_type_get_destructor(TypeIndex type) - */ -static PyObject * -_inP07ytEG1l(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - FunctionIndex return_value = (::interrogate_type_get_destructor)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_type_number_of_elements(TypeIndex type) - */ -static PyObject * -_inP07yt7tUq(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_type_number_of_elements)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * ElementIndex interrogate_type_get_element(TypeIndex type, int n) - */ -static PyObject * -_inP07ytyStU(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - ElementIndex return_value = (::interrogate_type_get_element)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_type_number_of_methods(TypeIndex type) - */ -static PyObject * -_inP07ytdM85(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_type_number_of_methods)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_type_get_method(TypeIndex type, int n) - */ -static PyObject * -_inP07ytk_GN(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - FunctionIndex return_value = (::interrogate_type_get_method)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_type_number_of_make_seqs(TypeIndex type) - */ -static PyObject * -_inP07yt8QjG(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_type_number_of_make_seqs)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * MakeSeqIndex interrogate_type_get_make_seq(TypeIndex type, int n) - */ -static PyObject * -_inP07ytyMtj(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - MakeSeqIndex return_value = (::interrogate_type_get_make_seq)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_type_number_of_casts(TypeIndex type) - */ -static PyObject * -_inP07ytHDtN(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_type_number_of_casts)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_type_get_cast(TypeIndex type, int n) - */ -static PyObject * -_inP07ytHFjA(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - FunctionIndex return_value = (::interrogate_type_get_cast)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_type_number_of_derivations(TypeIndex type) - */ -static PyObject * -_inP07yt_NPR(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_type_number_of_derivations)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_type_get_derivation(TypeIndex type, int n) - */ -static PyObject * -_inP07ytcTOH(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - TypeIndex return_value = (::interrogate_type_get_derivation)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_is_final(TypeIndex type) - */ -static PyObject * -_inP07ytC5Uk(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - bool return_value = (::interrogate_type_is_final)((TypeIndex)param0); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_derivation_has_upcast(TypeIndex type, int n) - */ -static PyObject * -_inP07ythdU7(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - bool return_value = (::interrogate_type_derivation_has_upcast)((TypeIndex)param0, (int)param1); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_type_get_upcast(TypeIndex type, int n) - */ -static PyObject * -_inP07ytQPxU(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - FunctionIndex return_value = (::interrogate_type_get_upcast)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_derivation_downcast_is_impossible(TypeIndex type, int n) - */ -static PyObject * -_inP07ytO7Pz(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - bool return_value = (::interrogate_type_derivation_downcast_is_impossible)((TypeIndex)param0, (int)param1); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * bool interrogate_type_derivation_has_downcast(TypeIndex type, int n) - */ -static PyObject * -_inP07ytvu_E(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - bool return_value = (::interrogate_type_derivation_has_downcast)((TypeIndex)param0, (int)param1); - return PyBool_FromLong(return_value); - } - return nullptr; -} - -/* - * Python simple wrapper for - * FunctionIndex interrogate_type_get_downcast(TypeIndex type, int n) - */ -static PyObject * -_inP07ytxGUt(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - FunctionIndex return_value = (::interrogate_type_get_downcast)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * int interrogate_type_number_of_nested_types(TypeIndex type) - */ -static PyObject * -_inP07ytzM1P(PyObject *, PyObject *args) { - int param0; - if (PyArg_ParseTuple(args, "i", ¶m0)) { - int return_value = (::interrogate_type_number_of_nested_types)((TypeIndex)param0); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * TypeIndex interrogate_type_get_nested_type(TypeIndex type, int n) - */ -static PyObject * -_inP07ytoY5L(PyObject *, PyObject *args) { - int param0; - int param1; - if (PyArg_ParseTuple(args, "ii", ¶m0, ¶m1)) { - TypeIndex return_value = (::interrogate_type_get_nested_type)((TypeIndex)param0, (int)param1); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(return_value); -#else - return PyInt_FromLong(return_value); -#endif - } - return nullptr; -} - -/* - * Python simple wrapper for - * void interrogate_request_database(char const *database_filename) - */ -static PyObject * -_inP07yte_7S(PyObject *, PyObject *args) { - char *param0; - if (PyArg_ParseTuple(args, "s", ¶m0)) { - (::interrogate_request_database)((char const *)param0); - return Py_BuildValue(""); - } - return nullptr; -} - -/* - * Python simple wrapper for - * void interrogate_request_module(InterrogateModuleDef *def) - */ -static PyObject * -_inP07ytw_15(PyObject *, PyObject *args) { - Py_ssize_t param0; - if (PyArg_ParseTuple(args, "n", ¶m0)) { - (::interrogate_request_module)((InterrogateModuleDef *)param0); - return Py_BuildValue(""); - } - return nullptr; -} - - -static PyMethodDef python_simple_funcs[] = { - { "interrogate_add_search_directory", &_inP07yttbRf, METH_VARARGS, nullptr }, - { "interrogate_add_search_path", &_inP07ytda_g, METH_VARARGS, nullptr }, - { "interrogate_error_flag", &_inP07yt4RgX, METH_VARARGS, nullptr }, - { "interrogate_number_of_manifests", &_inP07yt3Gip, METH_VARARGS, nullptr }, - { "interrogate_get_manifest", &_inP07ytRKDz, METH_VARARGS, nullptr }, - { "interrogate_get_manifest_by_name", &_inP07ytgZ9N, METH_VARARGS, nullptr }, - { "interrogate_manifest_name", &_inP07ytFnRZ, METH_VARARGS, nullptr }, - { "interrogate_manifest_definition", &_inP07ytg0Qv, METH_VARARGS, nullptr }, - { "interrogate_manifest_has_type", &_inP07yttrqw, METH_VARARGS, nullptr }, - { "interrogate_manifest_get_type", &_inP07ytdmpW, METH_VARARGS, nullptr }, - { "interrogate_manifest_has_getter", &_inP07ytUYgQ, METH_VARARGS, nullptr }, - { "interrogate_manifest_getter", &_inP07yt0k7F, METH_VARARGS, nullptr }, - { "interrogate_manifest_has_int_value", &_inP07ytfIsr, METH_VARARGS, nullptr }, - { "interrogate_manifest_get_int_value", &_inP07ytvysR, METH_VARARGS, nullptr }, - { "interrogate_element_name", &_inP07ytYQ_2, METH_VARARGS, nullptr }, - { "interrogate_element_scoped_name", &_inP07yt3kdv, METH_VARARGS, nullptr }, - { "interrogate_element_has_comment", &_inP07ytew01, METH_VARARGS, nullptr }, - { "interrogate_element_comment", &_inP07ytQna7, METH_VARARGS, nullptr }, - { "interrogate_get_element_by_name", &_inP07ytkg95, METH_VARARGS, nullptr }, - { "interrogate_get_element_by_scoped_name", &_inP07ytluRc, METH_VARARGS, nullptr }, - { "interrogate_element_type", &_inP07yttHdM, METH_VARARGS, nullptr }, - { "interrogate_element_has_getter", &_inP07ytDId0, METH_VARARGS, nullptr }, - { "interrogate_element_getter", &_inP07ytHuAm, METH_VARARGS, nullptr }, - { "interrogate_element_has_setter", &_inP07yt_xr0, METH_VARARGS, nullptr }, - { "interrogate_element_setter", &_inP07ytH5qp, METH_VARARGS, nullptr }, - { "interrogate_element_has_has_function", &_inP07ytLfJw, METH_VARARGS, nullptr }, - { "interrogate_element_has_function", &_inP07yt_Atg, METH_VARARGS, nullptr }, - { "interrogate_element_has_clear_function", &_inP07ytlBqc, METH_VARARGS, nullptr }, - { "interrogate_element_clear_function", &_inP07ytNdUp, METH_VARARGS, nullptr }, - { "interrogate_element_has_del_function", &_inP07ytlS0p, METH_VARARGS, nullptr }, - { "interrogate_element_del_function", &_inP07ytZZe7, METH_VARARGS, nullptr }, - { "interrogate_element_has_insert_function", &_inP07ytV5S_, METH_VARARGS, nullptr }, - { "interrogate_element_insert_function", &_inP07yto9vD, METH_VARARGS, nullptr }, - { "interrogate_element_has_getkey_function", &_inP07ytv7tF, METH_VARARGS, nullptr }, - { "interrogate_element_getkey_function", &_inP07ythOg6, METH_VARARGS, nullptr }, - { "interrogate_element_length_function", &_inP07ytoZUn, METH_VARARGS, nullptr }, - { "interrogate_element_is_sequence", &_inP07ytq45U, METH_VARARGS, nullptr }, - { "interrogate_element_is_mapping", &_inP07yt6IPa, METH_VARARGS, nullptr }, - { "interrogate_number_of_globals", &_inP07ytU2_B, METH_VARARGS, nullptr }, - { "interrogate_get_global", &_inP07ytHFO2, METH_VARARGS, nullptr }, - { "interrogate_number_of_global_functions", &_inP07ytcfjm, METH_VARARGS, nullptr }, - { "interrogate_get_global_function", &_inP07yt3Sjw, METH_VARARGS, nullptr }, - { "interrogate_number_of_functions", &_inP07ytgJcX, METH_VARARGS, nullptr }, - { "interrogate_get_function", &_inP07ytYlw6, METH_VARARGS, nullptr }, - { "interrogate_function_name", &_inP07ytsmnz, METH_VARARGS, nullptr }, - { "interrogate_function_scoped_name", &_inP07ytxQ10, METH_VARARGS, nullptr }, - { "interrogate_function_has_comment", &_inP07yt6gPB, METH_VARARGS, nullptr }, - { "interrogate_function_comment", &_inP07ytISgV, METH_VARARGS, nullptr }, - { "interrogate_function_prototype", &_inP07ytH3bx, METH_VARARGS, nullptr }, - { "interrogate_function_is_method", &_inP07ytzeUk, METH_VARARGS, nullptr }, - { "interrogate_function_class", &_inP07ytUeI5, METH_VARARGS, nullptr }, - { "interrogate_function_is_unary_op", &_inP07ytbmxJ, METH_VARARGS, nullptr }, - { "interrogate_function_is_operator_typecast", &_inP07ytY8Lc, METH_VARARGS, nullptr }, - { "interrogate_function_is_constructor", &_inP07ytJAAI, METH_VARARGS, nullptr }, - { "interrogate_function_is_destructor", &_inP07yt0UXw, METH_VARARGS, nullptr }, - { "interrogate_function_has_module_name", &_inP07ytuSvx, METH_VARARGS, nullptr }, - { "interrogate_function_module_name", &_inP07ytwpYd, METH_VARARGS, nullptr }, - { "interrogate_function_has_library_name", &_inP07ytOfNh, METH_VARARGS, nullptr }, - { "interrogate_function_library_name", &_inP07ytf5_U, METH_VARARGS, nullptr }, - { "interrogate_function_is_virtual", &_inP07ytL3ZB, METH_VARARGS, nullptr }, - { "interrogate_function_number_of_c_wrappers", &_inP07ytXw0I, METH_VARARGS, nullptr }, - { "interrogate_function_c_wrapper", &_inP07yt3zru, METH_VARARGS, nullptr }, - { "interrogate_function_number_of_python_wrappers", &_inP07ytRrg2, METH_VARARGS, nullptr }, - { "interrogate_function_python_wrapper", &_inP07ytEJCx, METH_VARARGS, nullptr }, - { "interrogate_wrapper_name", &_inP07ytWAZr, METH_VARARGS, nullptr }, - { "interrogate_wrapper_function", &_inP07ytHQi6, METH_VARARGS, nullptr }, - { "interrogate_wrapper_is_callable_by_name", &_inP07ytrD_M, METH_VARARGS, nullptr }, - { "interrogate_wrapper_is_copy_constructor", &_inP07ytYaah, METH_VARARGS, nullptr }, - { "interrogate_wrapper_is_coerce_constructor", &_inP07yt2otr, METH_VARARGS, nullptr }, - { "interrogate_wrapper_is_extension", &_inP07ytNP_b, METH_VARARGS, nullptr }, - { "interrogate_wrapper_is_deprecated", &_inP07ytrrrN, METH_VARARGS, nullptr }, - { "interrogate_wrapper_has_comment", &_inP07ytjolz, METH_VARARGS, nullptr }, - { "interrogate_wrapper_comment", &_inP07ytt_JD, METH_VARARGS, nullptr }, - { "interrogate_wrapper_has_return_value", &_inP07ytwEts, METH_VARARGS, nullptr }, - { "interrogate_wrapper_return_type", &_inP07ytrJWs, METH_VARARGS, nullptr }, - { "interrogate_wrapper_caller_manages_return_value", &_inP07ytpmFD, METH_VARARGS, nullptr }, - { "interrogate_wrapper_return_value_destructor", &_inP07ytyYUX, METH_VARARGS, nullptr }, - { "interrogate_wrapper_number_of_parameters", &_inP07yt54dn, METH_VARARGS, nullptr }, - { "interrogate_wrapper_parameter_type", &_inP07ytGMpW, METH_VARARGS, nullptr }, - { "interrogate_wrapper_parameter_has_name", &_inP07ytNuBV, METH_VARARGS, nullptr }, - { "interrogate_wrapper_parameter_name", &_inP07yt9UwA, METH_VARARGS, nullptr }, - { "interrogate_wrapper_parameter_is_this", &_inP07yt3FDt, METH_VARARGS, nullptr }, - { "interrogate_wrapper_parameter_is_optional", &_inP07ytDgOY, METH_VARARGS, nullptr }, - { "interrogate_wrapper_has_pointer", &_inP07ytf513, METH_VARARGS, nullptr }, - { "interrogate_wrapper_pointer", &_inP07ytsqGH, METH_VARARGS, nullptr }, - { "interrogate_wrapper_unique_name", &_inP07yt7shV, METH_VARARGS, nullptr }, - { "interrogate_get_wrapper_by_unique_name", &_inP07ytA1eF, METH_VARARGS, nullptr }, - { "interrogate_make_seq_seq_name", &_inP07yt776V, METH_VARARGS, nullptr }, - { "interrogate_make_seq_scoped_name", &_inP07ytryup, METH_VARARGS, nullptr }, - { "interrogate_make_seq_has_comment", &_inP07ytiytI, METH_VARARGS, nullptr }, - { "interrogate_make_seq_comment", &_inP07ytZc07, METH_VARARGS, nullptr }, - { "interrogate_make_seq_num_name", &_inP07ytfaH0, METH_VARARGS, nullptr }, - { "interrogate_make_seq_element_name", &_inP07ytGB9D, METH_VARARGS, nullptr }, - { "interrogate_make_seq_num_getter", &_inP07ytrppS, METH_VARARGS, nullptr }, - { "interrogate_make_seq_element_getter", &_inP07ytO50x, METH_VARARGS, nullptr }, - { "interrogate_number_of_global_types", &_inP07ytsxxs, METH_VARARGS, nullptr }, - { "interrogate_get_global_type", &_inP07ytMT0z, METH_VARARGS, nullptr }, - { "interrogate_number_of_types", &_inP07ytiW3v, METH_VARARGS, nullptr }, - { "interrogate_get_type", &_inP07yt4Px8, METH_VARARGS, nullptr }, - { "interrogate_get_type_by_name", &_inP07ytNHcs, METH_VARARGS, nullptr }, - { "interrogate_get_type_by_scoped_name", &_inP07ytqHrb, METH_VARARGS, nullptr }, - { "interrogate_get_type_by_true_name", &_inP07ytaOqq, METH_VARARGS, nullptr }, - { "interrogate_type_is_global", &_inP07ytpTBb, METH_VARARGS, nullptr }, - { "interrogate_type_is_deprecated", &_inP07ytZUkn, METH_VARARGS, nullptr }, - { "interrogate_type_name", &_inP07ytqWOw, METH_VARARGS, nullptr }, - { "interrogate_type_scoped_name", &_inP07ytHu7x, METH_VARARGS, nullptr }, - { "interrogate_type_true_name", &_inP07ytwGnA, METH_VARARGS, nullptr }, - { "interrogate_type_is_nested", &_inP07ytXGxx, METH_VARARGS, nullptr }, - { "interrogate_type_outer_class", &_inP07ytj04Z, METH_VARARGS, nullptr }, - { "interrogate_type_has_comment", &_inP07ytEOv4, METH_VARARGS, nullptr }, - { "interrogate_type_comment", &_inP07ytpCqJ, METH_VARARGS, nullptr }, - { "interrogate_type_has_module_name", &_inP07yt_Pz3, METH_VARARGS, nullptr }, - { "interrogate_type_module_name", &_inP07ytt_06, METH_VARARGS, nullptr }, - { "interrogate_type_has_library_name", &_inP07ytmuPs, METH_VARARGS, nullptr }, - { "interrogate_type_library_name", &_inP07ytvM8B, METH_VARARGS, nullptr }, - { "interrogate_type_is_atomic", &_inP07ytap97, METH_VARARGS, nullptr }, - { "interrogate_type_atomic_token", &_inP07yt0o8D, METH_VARARGS, nullptr }, - { "interrogate_type_is_unsigned", &_inP07ytOoQ2, METH_VARARGS, nullptr }, - { "interrogate_type_is_signed", &_inP07ytKuFh, METH_VARARGS, nullptr }, - { "interrogate_type_is_long", &_inP07yto5L6, METH_VARARGS, nullptr }, - { "interrogate_type_is_longlong", &_inP07ytzgKK, METH_VARARGS, nullptr }, - { "interrogate_type_is_short", &_inP07yt0FIF, METH_VARARGS, nullptr }, - { "interrogate_type_is_wrapped", &_inP07ytZqvD, METH_VARARGS, nullptr }, - { "interrogate_type_is_pointer", &_inP07ytDyRd, METH_VARARGS, nullptr }, - { "interrogate_type_is_const", &_inP07ytMnKa, METH_VARARGS, nullptr }, - { "interrogate_type_is_typedef", &_inP07ytRtji, METH_VARARGS, nullptr }, - { "interrogate_type_wrapped_type", &_inP07ytCnbQ, METH_VARARGS, nullptr }, - { "interrogate_type_is_array", &_inP07ytoxqc, METH_VARARGS, nullptr }, - { "interrogate_type_array_size", &_inP07ytZQIS, METH_VARARGS, nullptr }, - { "interrogate_type_is_enum", &_inP07ytdUVN, METH_VARARGS, nullptr }, - { "interrogate_type_is_scoped_enum", &_inP07ytZtNk, METH_VARARGS, nullptr }, - { "interrogate_type_number_of_enum_values", &_inP07ytihbt, METH_VARARGS, nullptr }, - { "interrogate_type_enum_value_name", &_inP07ytbyPY, METH_VARARGS, nullptr }, - { "interrogate_type_enum_value_scoped_name", &_inP07ytAaT6, METH_VARARGS, nullptr }, - { "interrogate_type_enum_value_comment", &_inP07ytgL9q, METH_VARARGS, nullptr }, - { "interrogate_type_enum_value", &_inP07ytWB97, METH_VARARGS, nullptr }, - { "interrogate_type_is_struct", &_inP07ytDUAl, METH_VARARGS, nullptr }, - { "interrogate_type_is_class", &_inP07yt1_Kf, METH_VARARGS, nullptr }, - { "interrogate_type_is_union", &_inP07yt98lD, METH_VARARGS, nullptr }, - { "interrogate_type_is_fully_defined", &_inP07yt9SHr, METH_VARARGS, nullptr }, - { "interrogate_type_is_unpublished", &_inP07ytdiZP, METH_VARARGS, nullptr }, - { "interrogate_type_number_of_constructors", &_inP07ytTdER, METH_VARARGS, nullptr }, - { "interrogate_type_get_constructor", &_inP07ytYO56, METH_VARARGS, nullptr }, - { "interrogate_type_has_destructor", &_inP07ytxtCG, METH_VARARGS, nullptr }, - { "interrogate_type_destructor_is_inherited", &_inP07yt_EB2, METH_VARARGS, nullptr }, - { "interrogate_type_get_destructor", &_inP07ytEG1l, METH_VARARGS, nullptr }, - { "interrogate_type_number_of_elements", &_inP07yt7tUq, METH_VARARGS, nullptr }, - { "interrogate_type_get_element", &_inP07ytyStU, METH_VARARGS, nullptr }, - { "interrogate_type_number_of_methods", &_inP07ytdM85, METH_VARARGS, nullptr }, - { "interrogate_type_get_method", &_inP07ytk_GN, METH_VARARGS, nullptr }, - { "interrogate_type_number_of_make_seqs", &_inP07yt8QjG, METH_VARARGS, nullptr }, - { "interrogate_type_get_make_seq", &_inP07ytyMtj, METH_VARARGS, nullptr }, - { "interrogate_type_number_of_casts", &_inP07ytHDtN, METH_VARARGS, nullptr }, - { "interrogate_type_get_cast", &_inP07ytHFjA, METH_VARARGS, nullptr }, - { "interrogate_type_number_of_derivations", &_inP07yt_NPR, METH_VARARGS, nullptr }, - { "interrogate_type_get_derivation", &_inP07ytcTOH, METH_VARARGS, nullptr }, - { "interrogate_type_is_final", &_inP07ytC5Uk, METH_VARARGS, nullptr }, - { "interrogate_type_derivation_has_upcast", &_inP07ythdU7, METH_VARARGS, nullptr }, - { "interrogate_type_get_upcast", &_inP07ytQPxU, METH_VARARGS, nullptr }, - { "interrogate_type_derivation_downcast_is_impossible", &_inP07ytO7Pz, METH_VARARGS, nullptr }, - { "interrogate_type_derivation_has_downcast", &_inP07ytvu_E, METH_VARARGS, nullptr }, - { "interrogate_type_get_downcast", &_inP07ytxGUt, METH_VARARGS, nullptr }, - { "interrogate_type_number_of_nested_types", &_inP07ytzM1P, METH_VARARGS, nullptr }, - { "interrogate_type_get_nested_type", &_inP07ytoY5L, METH_VARARGS, nullptr }, - { "interrogate_request_database", &_inP07yte_7S, METH_VARARGS, nullptr }, - { "interrogate_request_module", &_inP07ytw_15, METH_VARARGS, nullptr }, - { nullptr, nullptr, 0, nullptr } -}; - -#if PY_MAJOR_VERSION >= 3 -static struct PyModuleDef python_simple_module = { - PyModuleDef_HEAD_INIT, - "panda3d.interrogatedb", - nullptr, - -1, - python_simple_funcs, - nullptr, nullptr, nullptr, nullptr -}; - -#define INIT_FUNC PyObject *PyInit_interrogatedb -#else -#define INIT_FUNC void initinterrogatedb -#endif - -#ifdef _WIN32 -extern "C" __declspec(dllexport) INIT_FUNC(); -#elif __GNUC__ >= 4 -extern "C" __attribute__((visibility("default"))) INIT_FUNC(); -#else -extern "C" INIT_FUNC(); -#endif - -INIT_FUNC() { -#if PY_MAJOR_VERSION >= 3 - return PyModule_Create(&python_simple_module); -#else - Py_InitModule("interrogatedb", python_simple_funcs); -#endif -} - diff --git a/dtool/src/dtoolbase/CMakeLists.txt b/dtool/src/dtoolbase/CMakeLists.txt index 7e9340ec71..d62f879029 100644 --- a/dtool/src/dtoolbase/CMakeLists.txt +++ b/dtool/src/dtoolbase/CMakeLists.txt @@ -24,6 +24,7 @@ set(P3DTOOLBASE_HEADERS deletedChain.h deletedChain.I dtoolbase.h dtoolbase_cc.h dtoolsymbols.h dtool_platform.h + extension.h fakestringstream.h indent.I indent.h memoryBase.h diff --git a/dtool/src/dtoolbase/dtoolbase_cc.h b/dtool/src/dtoolbase/dtoolbase_cc.h index d19db7f5ef..ed55688194 100644 --- a/dtool/src/dtoolbase/dtoolbase_cc.h +++ b/dtool/src/dtoolbase/dtoolbase_cc.h @@ -110,9 +110,9 @@ typedef std::ios::seekdir ios_seekdir; #define INLINE inline #endif -// Determine the availability of C++11 features. -#if defined(_MSC_VER) && _MSC_VER < 1900 // Visual Studio 2015 -#error Microsoft Visual C++ 2015 or later is required to compile Panda3D. +// Determine the availability of C++14 features. +#if defined(_MSC_VER) && _MSC_VER < 1910 // Visual Studio 2017 +#error Microsoft Visual C++ 2017 or later is required to compile Panda3D. #endif // This is just to support code generated with older versions of interrogate. diff --git a/dtool/src/interrogatedb/extension.h b/dtool/src/dtoolbase/extension.h similarity index 100% rename from dtool/src/interrogatedb/extension.h rename to dtool/src/dtoolbase/extension.h diff --git a/dtool/src/dtoolbase/pdtoa.cxx b/dtool/src/dtoolbase/pdtoa.cxx index 8055f6d49d..552391a6fc 100644 --- a/dtool/src/dtoolbase/pdtoa.cxx +++ b/dtool/src/dtoolbase/pdtoa.cxx @@ -32,6 +32,8 @@ THE SOFTWARE. #include #include #define copysign _copysign + +#pragma float_control(precise, on, push) #endif #define UINT64_C2(h, l) ((static_cast(h) << 32) | static_cast(l)) @@ -586,3 +588,7 @@ void pftoa(float value, char *buffer) { } } } + +#ifdef _MSC_VER +#pragma float_control(pop) +#endif diff --git a/dtool/src/dtoolbase/typeHandle_ext.cxx b/dtool/src/dtoolbase/typeHandle_ext.cxx index 5e0d80f2a8..be97efd0a6 100644 --- a/dtool/src/dtoolbase/typeHandle_ext.cxx +++ b/dtool/src/dtoolbase/typeHandle_ext.cxx @@ -49,19 +49,26 @@ __reduce__() const { PyTypeObject *py_type = _this->get_python_type(); if (py_type != nullptr && py_type->tp_dict != nullptr) { // Look for a get_class_type method, if it returns this handle. - PyObject *func = PyDict_GetItemString(py_type->tp_dict, "get_class_type"); - if (func != nullptr && PyCallable_Check(func)) { - PyObject *result = PyObject_CallNoArgs(func); - TypeHandle *result_handle = nullptr; - if (result == nullptr) { - // Never mind. - PyErr_Clear(); - } - else if (DtoolInstance_GetPointer(result, result_handle, Dtool_TypeHandle) && - *result_handle == *_this) { - // It returned the correct result, so we can use this. - return Py_BuildValue("O()", func); + PyObject *func; + int result = PyDict_GetItemStringRef(py_type->tp_dict, "get_class_type", &func); + if (result > 0) { + if (PyCallable_Check(func)) { + PyObject *result = PyObject_CallNoArgs(func); + TypeHandle *result_handle = nullptr; + if (result == nullptr) { + // Never mind. + PyErr_Clear(); + } + else if (DtoolInstance_GetPointer(result, result_handle, Dtool_TypeHandle) && + *result_handle == *_this) { + // It returned the correct result, so we can use this. + return Py_BuildValue("N()", func); + } } + Py_DECREF(func); + } + else if (result < 0) { + PyErr_Clear(); } } diff --git a/dtool/src/dtoolutil/executionEnvironment.cxx b/dtool/src/dtoolutil/executionEnvironment.cxx index eda3dc58fa..71083fa7ab 100644 --- a/dtool/src/dtoolutil/executionEnvironment.cxx +++ b/dtool/src/dtoolutil/executionEnvironment.cxx @@ -72,7 +72,7 @@ extern char **environ; // read environment variables at static init time. In this case, we must read // all of the environment variables directly and cache them locally. -#ifndef STATIC_INIT_GETENV +#if !defined(STATIC_INIT_GETENV) || defined(__EMSCRIPTEN__) #define PREREAD_ENVIRONMENT #endif @@ -123,6 +123,13 @@ static const char *const libp3dtool_filenames[] = { }; #endif /* !LINK_ALL_STATIC */ +#if defined(__EMSCRIPTEN__) && !defined(CPPPARSER) +extern "C" void EMSCRIPTEN_KEEPALIVE +_set_env_var(ExecutionEnvironment *ptr, const char *var, const char *value) { + ptr->_variables[std::string(var)] = std::string(value); +} +#endif + // Linux with GNU libc does have global argvargc variables, but we can't // safely access them at stat init time--at least, not in libc5. (It does seem // to work with glibc2, however.) @@ -449,7 +456,7 @@ ns_set_environment_variable(const string &var, const string &value) { void ExecutionEnvironment:: ns_shadow_environment_variable(const string &var, const string &value) { _variables[var] = value; - string putstr = var + "=" + value; + //string putstr = var + "=" + value; } /** @@ -577,7 +584,17 @@ read_environment_variables() { } } #elif defined(__EMSCRIPTEN__) - // Emscripten has no environment vars. Don't even try. + // We only have environment variables if we're running in node.js. +#ifndef CPPPARSER + EM_ASM({ + if (typeof process === 'object' && typeof process.env === 'object') { + for (var variable in process.env) { + __set_env_var($0, stringToUTF8OnStack(variable), + stringToUTF8OnStack(process.env[variable])); + } + } + }, this); +#endif #elif defined(HAVE_PROC_SELF_ENVIRON) // In some cases, we may have a file called procselfenviron that may be read diff --git a/dtool/src/dtoolutil/executionEnvironment.h b/dtool/src/dtoolutil/executionEnvironment.h index 0ff0814cdd..e54f87c40f 100644 --- a/dtool/src/dtoolutil/executionEnvironment.h +++ b/dtool/src/dtoolutil/executionEnvironment.h @@ -21,6 +21,13 @@ #include +#if defined(__EMSCRIPTEN__) && !defined(CPPPARSER) +class ExecutionEnvironment; + +extern "C" void EMSCRIPTEN_KEEPALIVE +_set_env_var(ExecutionEnvironment *ptr, const char *var, const char *value); +#endif + /** * Encapsulates access to the environment variables and command-line arguments * at the time of execution. This is encapsulated to support accessing these @@ -89,6 +96,10 @@ private: std::string _dtool_name; static ExecutionEnvironment *_global_ptr; + +#ifdef __EMSCRIPTEN__ + friend void ::_set_env_var(ExecutionEnvironment *ptr, const char *var, const char *value); +#endif }; #include "executionEnvironment.I" diff --git a/dtool/src/dtoolutil/filename_ext.cxx b/dtool/src/dtoolutil/filename_ext.cxx index cc67d9dd2e..12b85111d0 100644 --- a/dtool/src/dtoolutil/filename_ext.cxx +++ b/dtool/src/dtoolutil/filename_ext.cxx @@ -33,10 +33,17 @@ __init__(PyObject *path) { Py_ssize_t length; if (PyUnicode_CheckExact(path)) { - wchar_t *data; - data = PyUnicode_AsWideCharString(path, &length); - (*_this) = wstring(data, length); - PyMem_Free(data); + if (Filename::get_filesystem_encoding() == TextEncoder::E_utf8) { + const char *data = PyUnicode_AsUTF8AndSize(path, &length); + if (data != nullptr) { + (*_this) = string(data, length); + } + } else { + wchar_t *data; + data = PyUnicode_AsWideCharString(path, &length); + (*_this) = wstring(data, length); + PyMem_Free(data); + } return; } @@ -47,7 +54,7 @@ __init__(PyObject *path) { return; } - if (Py_TYPE(path) == &Dtool_Filename._PyType) { + if (Py_IS_TYPE(path, Dtool_GetPyTypeObject(&Dtool_Filename))) { // Copy constructor. *_this = *(Filename *)DtoolInstance_VOID_PTR(path); return; @@ -67,10 +74,17 @@ __init__(PyObject *path) { } if (PyUnicode_CheckExact(path_str)) { - wchar_t *data; - data = PyUnicode_AsWideCharString(path_str, &length); - (*_this) = Filename::from_os_specific_w(wstring(data, length)); - PyMem_Free(data); + if (Filename::get_filesystem_encoding() == TextEncoder::E_utf8) { + const char *data = PyUnicode_AsUTF8AndSize(path_str, &length); + if (data != nullptr) { + (*_this) = Filename::from_os_specific(string(data, length)); + } + } else { + wchar_t *data; + data = PyUnicode_AsWideCharString(path_str, &length); + (*_this) = Filename::from_os_specific_w(wstring(data, length)); + PyMem_Free(data); + } } else if (PyBytes_CheckExact(path_str)) { char *data; diff --git a/dtool/src/dtoolutil/pfstreamBuf.cxx b/dtool/src/dtoolutil/pfstreamBuf.cxx index f746ca5ac9..a9a2abd12a 100644 --- a/dtool/src/dtoolutil/pfstreamBuf.cxx +++ b/dtool/src/dtoolutil/pfstreamBuf.cxx @@ -185,7 +185,7 @@ is_open() const { */ bool PipeStreamBuf:: eof_pipe() const { - return (_pipe == nullptr) && feof(_pipe); + return (_pipe == nullptr) || feof(_pipe); } /** diff --git a/dtool/src/interrogatedb/CMakeLists.txt b/dtool/src/interrogatedb/CMakeLists.txt index 4004680279..f137a7b802 100644 --- a/dtool/src/interrogatedb/CMakeLists.txt +++ b/dtool/src/interrogatedb/CMakeLists.txt @@ -1,76 +1,8 @@ -set(P3INTERROGATEDB_HEADERS - config_interrogatedb.h indexRemapper.h interrogateComponent.I - interrogateComponent.h interrogateDatabase.I - interrogateDatabase.h interrogateElement.I - interrogateElement.h interrogateFunction.I - interrogateFunction.h interrogateFunctionWrapper.I - interrogateFunctionWrapper.h - interrogateMakeSeq.I interrogateMakeSeq.h - interrogateManifest.I interrogateManifest.h - interrogateType.I interrogateType.h - interrogate_datafile.I interrogate_datafile.h - interrogate_interface.h interrogate_request.h -) - -set(P3INTERROGATEDB_SOURCES - config_interrogatedb.cxx - indexRemapper.cxx - interrogateComponent.cxx interrogateDatabase.cxx - interrogateElement.cxx interrogateFunction.cxx - interrogateFunctionWrapper.cxx - interrogateMakeSeq.cxx - interrogateManifest.cxx - interrogateType.cxx interrogate_datafile.cxx - interrogate_interface.cxx interrogate_request.cxx -) - -set(P3INTERROGATEDB_IGATE - interrogate_interface.h - interrogate_request.h -) - set(P3IGATERUNTIME_HEADERS - extension.h py_compat.h py_panda.h py_panda.I py_wrappers.h + interrogate_request.h + py_compat.h + py_panda.h py_panda.I + py_wrappers.h ) -composite_sources(p3interrogatedb P3INTERROGATEDB_SOURCES) -add_library(p3interrogatedb - ${P3INTERROGATEDB_HEADERS} ${P3INTERROGATEDB_SOURCES}) -set_target_properties(p3interrogatedb PROPERTIES DEFINE_SYMBOL BUILDING_INTERROGATEDB) -target_link_libraries(p3interrogatedb p3dconfig p3prc) - -install(TARGETS p3interrogatedb - EXPORT Core COMPONENT Core - DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d - ARCHIVE COMPONENT CoreDevel) -install(FILES ${P3INTERROGATEDB_HEADERS} COMPONENT CoreDevel DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d) install(FILES ${P3IGATERUNTIME_HEADERS} COMPONENT CoreDevel DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d) - -# ALSO: This has an Interrogate binding! Take care of that if we want it. -# Note we don't use the regular Interrogate macros; this has some custom flags -# that would make it not worthwhile. - -if(NOT INTERROGATE_PYTHON_INTERFACE) - return() -endif() - -add_custom_command( - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/interrogatedb_module.cxx" - COMMAND interrogate - -D EXPCL_INTERROGATEDB= - -nodb -python -promiscuous - -module panda3d.interrogatedb - -library interrogatedb - -string -true-names -do-module - -srcdir "${CMAKE_CURRENT_SOURCE_DIR}" - -oc "${CMAKE_CURRENT_BINARY_DIR}/interrogatedb_module.cxx" - ${P3INTERROGATEDB_IGATE} - - DEPENDS interrogate ${P3INTERROGATEDB_IGATE} - COMMENT "Interrogating interrogatedb") - -add_python_target(panda3d.interrogatedb - "${CMAKE_CURRENT_BINARY_DIR}/interrogatedb_module.cxx") -target_link_libraries(panda3d.interrogatedb p3interrogatedb) diff --git a/dtool/src/interrogatedb/config_interrogatedb.cxx b/dtool/src/interrogatedb/config_interrogatedb.cxx deleted file mode 100644 index 16986de56b..0000000000 --- a/dtool/src/interrogatedb/config_interrogatedb.cxx +++ /dev/null @@ -1,66 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_interrogatedb.cxx - * @author drose - * @date 2000-08-01 - */ - -#include "config_interrogatedb.h" -#include "interrogate_request.h" -#include "configVariableBool.h" -#include "configVariableSearchPath.h" -#include "dconfig.h" - -#if defined(_MSC_VER) && defined(_DEBUG) -// _DEBUG assumes you are linking to msvcrt70d.dll, not msvcrt70.dll -#define USE_WIN32_DBGHEAP -#include -#endif - -Configure(config_interrogatedb); -NotifyCategoryDef(interrogatedb, ""); - -ConfigureFn(config_interrogatedb) { - // interrogate_request_library("types"); - -#ifdef USE_WIN32_DBGHEAP - ConfigVariableBool use_win32_dbgheap("use-win32-dbgheap", false); - ConfigVariableBool win32_report_leaks("win32-report-leaks", false); - - int dbg_flags = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); - - if (use_win32_dbgheap.get_string_value() == "full") { - // "full" means check the heap after *every* allocdealloc. Expensive. - dbg_flags |= (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | - _CRTDBG_CHECK_CRT_DF); - - } else { - // Otherwise, it's a bool flag. true means check the heap normally, false - // means don't do any debug checking. - if (!use_win32_dbgheap) { - // deflt disable complete heap verify every 1024 allocations (VC7 - // deflt). With vc7 stl small-string-optimization causing more allocs, - // this can cause order-of-magnitude slowdowns in dbg builds - dbg_flags = 0; - } - } - - if (win32_report_leaks) { - // Report memory still allocated at program termination. Not sure how - // useful this is, as many things get allocated once and never freed, but - // they aren't really leaks. - dbg_flags |= _CRTDBG_LEAK_CHECK_DF; - } - - _CrtSetDbgFlag(dbg_flags); -#endif -} - -ConfigVariableSearchPath interrogatedb_path -("interrogatedb-path", "The search path for interrogate's *.in files."); diff --git a/dtool/src/interrogatedb/config_interrogatedb.h b/dtool/src/interrogatedb/config_interrogatedb.h deleted file mode 100644 index 1a99702d0e..0000000000 --- a/dtool/src/interrogatedb/config_interrogatedb.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_interrogatedb.h - * @author drose - * @date 2000-08-01 - */ - -#ifndef CONFIG_INTERROGATEDB_H -#define CONFIG_INTERROGATEDB_H - -#include "dtoolbase.h" -#include "notifyCategoryProxy.h" -#include "configVariableSearchPath.h" - -NotifyCategoryDecl(interrogatedb, EXPCL_INTERROGATEDB, EXPTP_INTERROGATEDB); - -extern ConfigVariableSearchPath interrogatedb_path; - -#endif diff --git a/dtool/src/interrogatedb/dtool_super_base.cxx b/dtool/src/interrogatedb/dtool_super_base.cxx deleted file mode 100644 index 0b7613617e..0000000000 --- a/dtool/src/interrogatedb/dtool_super_base.cxx +++ /dev/null @@ -1,161 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dtool_super_base.cxx - * @author drose - * @date 2005-07-04 - */ - -#include "py_panda.h" - -#ifdef HAVE_PYTHON - -static PyMemberDef standard_type_members[] = { - {(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"}, - {(char *)"this_ownership", T_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"}, - {(char *)"this_const", T_BOOL, offsetof(Dtool_PyInstDef, _is_const), READONLY, (char *)"C++ 'this' const flag"}, -// {(char *)"this_signature", T_INT, offsetof(Dtool_PyInstDef, _signature), -// READONLY, (char *)"A type check signature"}, - {(char *)"this_metatype", T_OBJECT_EX, offsetof(Dtool_PyInstDef, _My_Type), READONLY, (char *)"The dtool meta object"}, - {nullptr} /* Sentinel */ -}; - -static PyObject *GetSuperBase(PyObject *self) { - Dtool_PyTypedObject *super_base = Dtool_GetSuperBase(); - return Py_XNewRef((PyObject *)&super_base->_PyType); -}; - -static void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module) { - if (module != nullptr) { - Dtool_PyTypedObject *super_base = Dtool_GetSuperBase(); - PyModule_AddObjectRef(module, "DTOOL_SUPER_BASE", (PyObject *)&super_base->_PyType); - } -} - -static void *Dtool_UpcastInterface_DTOOL_SUPER_BASE(PyObject *self, Dtool_PyTypedObject *requested_type) { - return nullptr; -} - -static PyObject *Dtool_Wrap_DTOOL_SUPER_BASE(void *from_this, PyTypeObject *from_type) { - return nullptr; -} - -static int Dtool_Init_DTOOL_SUPER_BASE(PyObject *self, PyObject *args, PyObject *kwds) { - assert(self != nullptr); - PyErr_Format(PyExc_TypeError, "cannot init constant class %s", Py_TYPE(self)->tp_name); - return -1; -} - -static void Dtool_FreeInstance_DTOOL_SUPER_BASE(PyObject *self) { - Py_TYPE(self)->tp_free(self); -} - -/** - * Returns a pointer to the DTOOL_SUPER_BASE class that is the base class of - * all Panda types. This pointer is shared by all modules. - */ -Dtool_PyTypedObject *Dtool_GetSuperBase() { - Dtool_TypeMap *type_map = Dtool_GetGlobalTypeMap(); - auto it = type_map->find("DTOOL_SUPER_BASE"); - if (it != type_map->end()) { - return it->second; - } - - static PyMethodDef methods[] = { - { "DtoolGetSuperBase", (PyCFunction)&GetSuperBase, METH_NOARGS, "Will Return SUPERbase Class"}, - { nullptr, nullptr, 0, nullptr } - }; - - static Dtool_PyTypedObject super_base_type = { - { - PyVarObject_HEAD_INIT(nullptr, 0) - "dtoolconfig.DTOOL_SUPER_BASE", - sizeof(Dtool_PyInstDef), - 0, // tp_itemsize - &Dtool_FreeInstance_DTOOL_SUPER_BASE, - 0, // tp_vectorcall_offset - nullptr, // tp_getattr - nullptr, // tp_setattr -#if PY_MAJOR_VERSION >= 3 - nullptr, // tp_compare -#else - &DtoolInstance_ComparePointers, -#endif - nullptr, // tp_repr - nullptr, // tp_as_number - nullptr, // tp_as_sequence - nullptr, // tp_as_mapping - &DtoolInstance_HashPointer, - nullptr, // tp_call - nullptr, // tp_str - PyObject_GenericGetAttr, - PyObject_GenericSetAttr, - nullptr, // tp_as_buffer - (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES), - nullptr, // tp_doc - nullptr, // tp_traverse - nullptr, // tp_clear -#if PY_MAJOR_VERSION >= 3 - &DtoolInstance_RichComparePointers, -#else - nullptr, // tp_richcompare -#endif - 0, // tp_weaklistoffset - nullptr, // tp_iter - nullptr, // tp_iternext - methods, - standard_type_members, - nullptr, // tp_getset - nullptr, // tp_base - nullptr, // tp_dict - nullptr, // tp_descr_get - nullptr, // tp_descr_set - 0, // tp_dictoffset - Dtool_Init_DTOOL_SUPER_BASE, - PyType_GenericAlloc, - nullptr, // tp_new - PyObject_Del, - nullptr, // tp_is_gc - nullptr, // tp_bases - nullptr, // tp_mro - nullptr, // tp_cache - nullptr, // tp_subclasses - nullptr, // tp_weaklist - nullptr, // tp_del - 0, // tp_version_tag, -#if PY_VERSION_HEX >= 0x03040000 - nullptr, // tp_finalize -#endif -#if PY_VERSION_HEX >= 0x03080000 - nullptr, // tp_vectorcall -#endif - }, - TypeHandle::none(), - Dtool_PyModuleClassInit_DTOOL_SUPER_BASE, - Dtool_UpcastInterface_DTOOL_SUPER_BASE, - Dtool_Wrap_DTOOL_SUPER_BASE, - nullptr, - nullptr, - }; - - super_base_type._PyType.tp_dict = PyDict_New(); - PyDict_SetItemString(super_base_type._PyType.tp_dict, "DtoolClassDict", super_base_type._PyType.tp_dict); - - if (PyType_Ready((PyTypeObject *)&super_base_type) < 0) { - PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_DTOOL_SUPER_BASE)"); - return nullptr; - } - Py_INCREF(&super_base_type._PyType); - - PyDict_SetItemString(super_base_type._PyType.tp_dict, "DtoolGetSuperBase", PyCFunction_New(&methods[0], (PyObject *)&super_base_type)); - - (*type_map)["DTOOL_SUPER_BASE"] = &super_base_type; - return &super_base_type; -} - -#endif // HAVE_PYTHON diff --git a/dtool/src/interrogatedb/indexRemapper.cxx b/dtool/src/interrogatedb/indexRemapper.cxx deleted file mode 100644 index 7c606bec06..0000000000 --- a/dtool/src/interrogatedb/indexRemapper.cxx +++ /dev/null @@ -1,68 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file indexRemapper.cxx - * @author drose - * @date 2000-08-05 - */ - -#include "indexRemapper.h" - - -/** - * - */ -IndexRemapper:: -IndexRemapper() { -} - -/** - * - */ -IndexRemapper:: -~IndexRemapper() { -} - -/** - * Removes all mappings from the object. - */ -void IndexRemapper:: -clear() { - _map_int.clear(); -} - -/** - * Adds a mapping from the integer 'from' to 'to'. - */ -void IndexRemapper:: -add_mapping(int from, int to) { - _map_int[from] = to; -} - -/** - * Returns true if the given 'from' integer has been assigned a mapping, false - * if it has not. - */ -bool IndexRemapper:: -in_map(int from) const { - return _map_int.count(from) != 0; -} - -/** - * Returns the integer that the given 'from' integer had been set to map to, - * or the same integer if nothing had been set for it. - */ -int IndexRemapper:: -map_from(int from) const { - std::map::const_iterator mi; - mi = _map_int.find(from); - if (mi == _map_int.end()) { - return from; - } - return (*mi).second; -} diff --git a/dtool/src/interrogatedb/indexRemapper.h b/dtool/src/interrogatedb/indexRemapper.h deleted file mode 100644 index c89a7a2988..0000000000 --- a/dtool/src/interrogatedb/indexRemapper.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file indexRemapper.h - * @author drose - * @date 2000-08-05 - */ - -#ifndef INDEXREMAPPER_H -#define INDEXREMAPPER_H - -#include "dtoolbase.h" - -#include - -/** - * This class manages a mapping of integers to integers. It's used in this - * package to resequence some or all of the index numbers in the database to a - * different sequence. - * - * This class is just a wrapper around STL map. The only reason it exists is - * because Microsoft can't export STL map outside of the DLL. - */ -class EXPCL_INTERROGATEDB IndexRemapper { -public: - IndexRemapper(); - ~IndexRemapper(); - - void clear(); - void add_mapping(int from, int to); - - bool in_map(int from) const; - int map_from(int from) const; - -private: - std::map _map_int; -}; - -#endif diff --git a/dtool/src/interrogatedb/interrogateComponent.I b/dtool/src/interrogatedb/interrogateComponent.I deleted file mode 100644 index dddbb421fb..0000000000 --- a/dtool/src/interrogatedb/interrogateComponent.I +++ /dev/null @@ -1,123 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateComponent.I - * @author drose - * @date 2000-08-08 - */ - -/** - * - */ -INLINE InterrogateComponent:: -InterrogateComponent(InterrogateModuleDef *def) : - _def(def) -{ -} - -/** - * - */ -INLINE InterrogateComponent:: -InterrogateComponent(const InterrogateComponent ©) : - _def(copy._def), - _name(copy._name) -{ -} - -/** - * - */ -INLINE void InterrogateComponent:: -operator = (const InterrogateComponent ©) { - _def = copy._def; - _name = copy._name; -} - -/** - * Returns true if we have a known library name, false if we do not. See - * get_library_name(). - */ -INLINE bool InterrogateComponent:: -has_library_name() const { - const char *name = get_library_name(); - return (name != nullptr && name[0] != '\0'); -} - -/** - * Returns the library name, if it is known, or NULL if it is not. This is - * the name of the library that this particular component was built into. - * Typically this will be a one-to-one correspondance with an invocation of - * the interrogate command. Typical examples are "libutil" and "liblinmath". - */ -INLINE const char *InterrogateComponent:: -get_library_name() const { - if (_def != nullptr) { - return _def->library_name; - } - return nullptr; -} - -/** - * Returns true if we have a known module name, false if we do not. See - * get_module_name(). - */ -INLINE bool InterrogateComponent:: -has_module_name() const { - const char *name = get_module_name(); - return (name != nullptr && name[0] != '\0'); -} - -/** - * Returns the module name, if it is known, or NULL if it is not. This is the - * name of the module that this particular component is associated with. This - * is a higher grouping than library. Typical examples are "panda" and - * "pandaegg". - */ -INLINE const char *InterrogateComponent:: -get_module_name() const { - if (_def != nullptr) { - return _def->module_name; - } - return nullptr; -} - -/** - * - */ -INLINE bool InterrogateComponent:: -has_name() const { - return !_name.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateComponent:: -get_name() const { - return _name; -} - -/** - * - */ -INLINE int InterrogateComponent:: -get_num_alt_names() const { - return _alt_names.size(); -} - -/** - * - */ -INLINE const std::string &InterrogateComponent:: -get_alt_name(int n) const { - if (n >= 0 && n < (int)_alt_names.size()) { - return _alt_names[n]; - } - return _empty_string; -} diff --git a/dtool/src/interrogatedb/interrogateComponent.cxx b/dtool/src/interrogatedb/interrogateComponent.cxx deleted file mode 100644 index 61398f686f..0000000000 --- a/dtool/src/interrogatedb/interrogateComponent.cxx +++ /dev/null @@ -1,50 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateComponent.cxx - * @author drose - * @date 2000-08-08 - */ - -#include "interrogateComponent.h" -#include "interrogate_datafile.h" - -// This static string is just kept around as a handy bogus return value for -// functions that must return a const string reference. -std::string InterrogateComponent::_empty_string; - -/** - * Formats the component for output to a data file. - */ -void InterrogateComponent:: -output(std::ostream &out) const { - idf_output_string(out, _name); - out << _alt_names.size() << " "; - - Strings::const_iterator vi; - for (vi = _alt_names.begin(); vi != _alt_names.end(); ++vi) { - idf_output_string(out, *vi); - } -} - -/** - * Reads the data file as previously formatted by output(). - */ -void InterrogateComponent:: -input(std::istream &in) { - idf_input_string(in, _name); - - int num_alt_names; - in >> num_alt_names; - _alt_names.reserve(num_alt_names); - for (int i = 0; i < num_alt_names; ++i) { - std::string alt_name; - idf_input_string(in, alt_name); - _alt_names.push_back(alt_name); - } -} diff --git a/dtool/src/interrogatedb/interrogateComponent.h b/dtool/src/interrogatedb/interrogateComponent.h deleted file mode 100644 index 2555769756..0000000000 --- a/dtool/src/interrogatedb/interrogateComponent.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateComponent.h - * @author drose - * @date 2000-08-08 - */ - -#ifndef INTERROGATECOMPONENT_H -#define INTERROGATECOMPONENT_H - -#include "dtoolbase.h" - -#include "interrogate_interface.h" -#include "interrogate_request.h" - -#include - -class IndexRemapper; - -/** - * The base class for things that are part of the interrogate database. This - * includes types, functions, and function wrappers. - */ -class EXPCL_INTERROGATEDB InterrogateComponent { -public: - INLINE InterrogateComponent(InterrogateModuleDef *def = nullptr); - INLINE InterrogateComponent(const InterrogateComponent ©); - INLINE void operator = (const InterrogateComponent ©); - - INLINE bool has_library_name() const; - INLINE const char *get_library_name() const; - - INLINE bool has_module_name() const; - INLINE const char *get_module_name() const; - - INLINE bool has_name() const; - INLINE const std::string &get_name() const; - - INLINE int get_num_alt_names() const; - INLINE const std::string &get_alt_name(int n) const; - - void output(std::ostream &out) const; - void input(std::istream &in); - -protected: - static std::string _empty_string; - -private: - InterrogateModuleDef *_def; - std::string _name; - - typedef std::vector Strings; - Strings _alt_names; - - friend class InterrogateBuilder; - friend class FunctionRemap; -}; - -#include "interrogateComponent.I" - -#endif diff --git a/dtool/src/interrogatedb/interrogateDatabase.I b/dtool/src/interrogatedb/interrogateDatabase.I deleted file mode 100644 index cf15d962bf..0000000000 --- a/dtool/src/interrogatedb/interrogateDatabase.I +++ /dev/null @@ -1,89 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateDatabase.I - * @author drose - * @date 2000-08-01 - */ - -/** - * Checks that all the latest data for all the libraries have been loaded. - * Loads them if not. - */ -INLINE void InterrogateDatabase:: -check_latest() { - if (!_requests.empty()) { - load_latest(); - } -} - -/** - * Returns the TypeIndex associated with the first type found with the given - * name, or 0 if no type has this name. - */ -INLINE TypeIndex InterrogateDatabase:: -lookup_type_by_name(const std::string &name) { - check_latest(); - return lookup(name, _types_by_name, LT_type_name, - &InterrogateDatabase::freshen_types_by_name); -} - -/** - * Returns the TypeIndex associated with the first type found with the given - * scoped name, or 0 if no type has this name. - */ -INLINE TypeIndex InterrogateDatabase:: -lookup_type_by_scoped_name(const std::string &name) { - check_latest(); - return lookup(name, _types_by_scoped_name, LT_type_scoped_name, - &InterrogateDatabase::freshen_types_by_scoped_name); -} - -/** - * Returns the TypeIndex associated with the first type found with the given - * true name, or 0 if no type has this name. - */ -INLINE TypeIndex InterrogateDatabase:: -lookup_type_by_true_name(const std::string &name) { - check_latest(); - return lookup(name, _types_by_true_name, LT_type_true_name, - &InterrogateDatabase::freshen_types_by_true_name); -} - -/** - * Returns the ManifestIndex associated with the first manifest found with the - * given name, or 0 if no manifest has this name. - */ -INLINE ManifestIndex InterrogateDatabase:: -lookup_manifest_by_name(const std::string &name) { - check_latest(); - return lookup(name, _manifests_by_name, LT_manifest_name, - &InterrogateDatabase::freshen_manifests_by_name); -} - -/** - * Returns the ElementIndex associated with the first element found with the - * given name, or 0 if no element has this name. - */ -INLINE ElementIndex InterrogateDatabase:: -lookup_element_by_name(const std::string &name) { - check_latest(); - return lookup(name, _elements_by_name, LT_element_name, - &InterrogateDatabase::freshen_elements_by_name); -} - -/** - * Returns the ElementIndex associated with the first element found with the - * given scoped name, or 0 if no element has this name. - */ -INLINE ElementIndex InterrogateDatabase:: -lookup_element_by_scoped_name(const std::string &name) { - check_latest(); - return lookup(name, _elements_by_scoped_name, LT_element_scoped_name, - &InterrogateDatabase::freshen_elements_by_scoped_name); -} diff --git a/dtool/src/interrogatedb/interrogateDatabase.cxx b/dtool/src/interrogatedb/interrogateDatabase.cxx deleted file mode 100644 index afdb7a11f7..0000000000 --- a/dtool/src/interrogatedb/interrogateDatabase.cxx +++ /dev/null @@ -1,1330 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateDatabase.cxx - * @author drose - * @date 2000-08-01 - */ - -#include "interrogateDatabase.h" -#include "config_interrogatedb.h" -#include "indexRemapper.h" -#include "interrogate_datafile.h" - -using std::map; -using std::string; - -InterrogateDatabase *InterrogateDatabase::_global_ptr = nullptr; -int InterrogateDatabase::_file_major_version = 0; -int InterrogateDatabase::_file_minor_version = 0; -int InterrogateDatabase::_current_major_version = 3; -int InterrogateDatabase::_current_minor_version = 3; - -/** - * - */ -InterrogateDatabase:: -InterrogateDatabase() { - _error_flag = false; - _next_index = 1; - _lookups_fresh = 0; -} - -/** - * Returns the global pointer to the one InterrogateDatabase. - */ -InterrogateDatabase *InterrogateDatabase:: -get_ptr() { - if (_global_ptr == nullptr) { - if (interrogatedb_cat->is_debug()) { - interrogatedb_cat->debug() - << "Creating interrogate database\n"; - } - _global_ptr = new InterrogateDatabase; - } - return _global_ptr; -} - -/** - * Requests that the interrogate data for the given module be made available. - * The function pointers will be made available immediately, while the - * database file will be read later, the next time someone asks for - * interrogate data that requires it. - */ -void InterrogateDatabase:: -request_module(InterrogateModuleDef *def) { - if (interrogatedb_cat->is_debug()) { - if (def->library_name == nullptr) { - interrogatedb_cat->debug() - << "Got interrogate data for anonymous module\n"; - } else { - interrogatedb_cat->debug() - << "Got interrogate data for module " << def->library_name << "\n"; - } - } - - int num_indices = def->next_index - def->first_index; - if (num_indices > 0) { - // If the module def has any definitions--any index numbers used--assign - // it to its own unique range of index numbers. - def->first_index = _next_index; - _next_index += num_indices; - def->next_index = _next_index; - - // Assign a reference to the module def by index number. When we need to - // look up a function by its index number, we'll be able to use this. - _modules.push_back(def); - } - - if (def->num_unique_names > 0 && def->library_name != nullptr) { - // Define a lookup by hash for this module, mainly so we can look up - // functions by their unique names. - _modules_by_hash[def->library_hash_name] = def; - } - - if (def->database_filename != nullptr) { - _requests.push_back(def); - } -} - -/** - * Returns the global error flag. This will be set true if there was some - * problem importing the database (e.g. cannot find an .in file), or false if - * everything is ok. - */ -bool InterrogateDatabase:: -get_error_flag() { - return _error_flag; -} - -/** - * Returns the total number of "global" types known to the interrogate - * database. These are types defined at the global level that should be - * considered for exporting, but not the incidental types (like pointers, - * etc.) that must be defined to support these. - */ -int InterrogateDatabase:: -get_num_global_types() { - check_latest(); - return _global_types.size(); -} - -/** - * Returns the index of the nth global type known to the interrogate database. - */ -TypeIndex InterrogateDatabase:: -get_global_type(int n) { - check_latest(); - if (n >= 0 && n < (int)_global_types.size()) { - return _global_types[n]; - } - return 0; -} - -/** - * Returns the total number of types known to the interrogate database. This - * includes all known types, global as well as incidental. See also - * get_num_global_types(). - */ -int InterrogateDatabase:: -get_num_all_types() { - check_latest(); - return _all_types.size(); -} - -/** - * Returns the index of the nth type known to the interrogate database. - */ -TypeIndex InterrogateDatabase:: -get_all_type(int n) { - check_latest(); - if (n >= 0 && n < (int)_all_types.size()) { - return _all_types[n]; - } - return 0; -} - -/** - * Returns the total number of global functions known to the interrogate - * database. These are functions defined at the global level, e.g. non- - * member functions. - */ -int InterrogateDatabase:: -get_num_global_functions() { - check_latest(); - return _global_functions.size(); -} - -/** - * Returns the index of the nth global function known to the interrogate - * database. - */ -FunctionIndex InterrogateDatabase:: -get_global_function(int n) { - check_latest(); - if (n >= 0 && n < (int)_global_functions.size()) { - return _global_functions[n]; - } - return 0; -} - -/** - * Returns the total number of functions known to the interrogate database. - * This includes all known functions, global, method, or synthesized. See - * also get_num_global_functions(). - */ -int InterrogateDatabase:: -get_num_all_functions() { - check_latest(); - return _all_functions.size(); -} - -/** - * Returns the index of the nth function known to the interrogate database. - */ -FunctionIndex InterrogateDatabase:: -get_all_function(int n) { - check_latest(); - if (n >= 0 && n < (int)_all_functions.size()) { - return _all_functions[n]; - } - return 0; -} - -/** - * Returns the total number of global manifest constants known to the - * interrogate database. - */ -int InterrogateDatabase:: -get_num_global_manifests() { - check_latest(); - return _global_manifests.size(); -} - -/** - * Returns the index of the nth global manifest constant known to the - * interrogate database. - */ -ManifestIndex InterrogateDatabase:: -get_global_manifest(int n) { - check_latest(); - if (n >= 0 && n < (int)_global_manifests.size()) { - return _global_manifests[n]; - } - return 0; -} - -/** - * Returns the total number of global data elements known to the interrogate - * database. - */ -int InterrogateDatabase:: -get_num_global_elements() { - check_latest(); - return _global_elements.size(); -} - -/** - * Returns the index of the nth global data element known to the interrogate - * database. - */ -ElementIndex InterrogateDatabase:: -get_global_element(int n) { - check_latest(); - if (n >= 0 && n < (int)_global_elements.size()) { - return _global_elements[n]; - } - return 0; -} - -/** - * Returns the type associated with the given TypeIndex, if there is one. - */ -const InterrogateType &InterrogateDatabase:: -get_type(TypeIndex type) { - static InterrogateType bogus_type; - - check_latest(); - TypeMap::const_iterator ti; - ti = _type_map.find(type); - if (ti == _type_map.end()) { - return bogus_type; - } - return (*ti).second; -} - -/** - * Returns the function associated with the given FunctionIndex, if there is - * one. - */ -const InterrogateFunction &InterrogateDatabase:: -get_function(FunctionIndex function) { - static InterrogateFunction bogus_function; - - check_latest(); - FunctionMap::const_iterator fi; - fi = _function_map.find(function); - if (fi == _function_map.end()) { - return bogus_function; - } - return *(*fi).second; -} - -/** - * Returns the function wrapper associated with the given - * FunctionWrapperIndex, if there is one. - */ -const InterrogateFunctionWrapper &InterrogateDatabase:: -get_wrapper(FunctionWrapperIndex wrapper) { - static InterrogateFunctionWrapper bogus_wrapper; - - check_latest(); - FunctionWrapperMap::const_iterator wi; - wi = _wrapper_map.find(wrapper); - if (wi == _wrapper_map.end()) { - return bogus_wrapper; - } - return (*wi).second; -} - -/** - * Returns the manifest constant associated with the given ManifestIndex, if - * there is one. - */ -const InterrogateManifest &InterrogateDatabase:: -get_manifest(ManifestIndex manifest) { - static InterrogateManifest bogus_manifest; - - check_latest(); - ManifestMap::const_iterator mi; - mi = _manifest_map.find(manifest); - if (mi == _manifest_map.end()) { - return bogus_manifest; - } - return (*mi).second; -} - -/** - * Returns the data element associated with the given ElementIndex, if there - * is one. - */ -const InterrogateElement &InterrogateDatabase:: -get_element(ElementIndex element) { - static InterrogateElement bogus_element; - - check_latest(); - ElementMap::const_iterator ei; - ei = _element_map.find(element); - if (ei == _element_map.end()) { - return bogus_element; - } - return (*ei).second; -} - -/** - * Returns the make_seq associated with the given MakeSeqIndex, if there is - * one. - */ -const InterrogateMakeSeq &InterrogateDatabase:: -get_make_seq(MakeSeqIndex make_seq) { - static InterrogateMakeSeq bogus_make_seq; - - check_latest(); - MakeSeqMap::const_iterator si; - si = _make_seq_map.find(make_seq); - if (si == _make_seq_map.end()) { - return bogus_make_seq; - } - return (*si).second; -} - -/** - * Erases the type from the database. - */ -void InterrogateDatabase:: -remove_type(TypeIndex type) { - _type_map.erase(type); -} - -/** - * Returns the function pointer associated with the given function wrapper, if - * it has a pointer available. Returns NULL if the pointer is not available. - */ -void *InterrogateDatabase:: -get_fptr(FunctionWrapperIndex wrapper) { - InterrogateModuleDef *def; - int module_index; - if (find_module(wrapper, def, module_index)) { - if (module_index >= 0 && module_index < def->num_fptrs) { - return def->fptrs[module_index]; - } - } - return nullptr; -} - -/** - * Looks up the function wrapper corresponding to the given unique name, if - * available. Returns the corresponding wrapper index, or 0 if no such - * wrapper is found. - */ -FunctionWrapperIndex InterrogateDatabase:: -get_wrapper_by_unique_name(const string &unique_name) { - // First, split the unique_name into a library_hash_name and a - // wrapper_hash_name. - - // The first four characters are always the library_name. - string library_hash_name = unique_name.substr(0, 4); - string wrapper_hash_name = unique_name.substr(4); - - // Is the library_name defined? - ModulesByHash::const_iterator mi; - mi = _modules_by_hash.find(library_hash_name); - if (mi == _modules_by_hash.end()) { - return 0; - } - - InterrogateModuleDef *def = (*mi).second; - int index_offset = - binary_search_wrapper_hash(def->unique_names, - def->unique_names + def->num_unique_names, - wrapper_hash_name); - if (index_offset >= 0) { - return def->first_index + index_offset; - } - - return 0; -} - -/** - * Returns the major version number of the interrogate database file currently - * being read. - */ -int InterrogateDatabase:: -get_file_major_version() { - return _file_major_version; -} - -/** - * Returns the minor version number of the interrogate database file currently - * being read. - */ -int InterrogateDatabase:: -get_file_minor_version() { - return _file_minor_version; -} - -/** - * Returns the major version number currently expected in interrogate database - * files generated by this code base. - */ -int InterrogateDatabase:: -get_current_major_version() { - return _current_major_version; -} - -/** - * Returns the minor version number currently expected in interrogate database - * files generated by this code base. - */ -int InterrogateDatabase:: -get_current_minor_version() { - return _current_minor_version; -} - -/** - * Sets the global error flag. This should be set true if there was some - * problem importing the database (e.g. cannot find an .in file). - */ -void InterrogateDatabase:: -set_error_flag(bool error_flag) { - _error_flag = error_flag; -} - -/** - * Returns a new index number suitable for the next thing, that will not be - * shared with any other index numbers. - */ -int InterrogateDatabase:: -get_next_index() { - return _next_index++; -} - -/** - * Adds the indicated type to the database at the given index number. - */ -void InterrogateDatabase:: -add_type(TypeIndex index, const InterrogateType &type) { - assert(index != 0); - bool inserted = - _type_map.insert(TypeMap::value_type(index, type)).second; - - if (!inserted) { - // If there was already a type at that index, maybe it was a forward - // reference. If its _fully_defined bit isn't set, then it's ok. - InterrogateType &old_type = _type_map[index]; - assert(!old_type.is_fully_defined()); - - // It was a forward reference. Merge it with the new one. - old_type.merge_with(type); - } - - if (type.is_global()) { - _global_types.push_back(index); - } - _all_types.push_back(index); -} - -/** - * Adds the indicated function to the database at the given index number. - */ -void InterrogateDatabase:: -add_function(FunctionIndex index, InterrogateFunction *function) { - bool inserted = - _function_map.insert(FunctionMap::value_type(index, function)).second; - assert(inserted); - - if (function->is_global()) { - _global_functions.push_back(index); - } - _all_functions.push_back(index); -} - -/** - * Adds the indicated function wrapper to the database at the given index - * number. - */ -void InterrogateDatabase:: -add_wrapper(FunctionWrapperIndex index, - const InterrogateFunctionWrapper &wrapper) { - bool inserted = - _wrapper_map.insert(FunctionWrapperMap::value_type(index, wrapper)).second; - assert(inserted); -} - -/** - * Adds the indicated manifest constant to the database at the given index - * number. - */ -void InterrogateDatabase:: -add_manifest(ManifestIndex index, const InterrogateManifest &manifest) { - bool inserted = - _manifest_map.insert(ManifestMap::value_type(index, manifest)).second; - assert(inserted); - - _global_manifests.push_back(index); -} - -/** - * Adds the indicated data element to the database at the given index number. - */ -void InterrogateDatabase:: -add_element(ElementIndex index, const InterrogateElement &element) { - bool inserted = - _element_map.insert(ElementMap::value_type(index, element)).second; - assert(inserted); - - if (element.is_global()) { - _global_elements.push_back(index); - } -} - -/** - * Adds the indicated make_seq to the database at the given index number. - */ -void InterrogateDatabase:: -add_make_seq(MakeSeqIndex index, const InterrogateMakeSeq &make_seq) { - bool inserted = - _make_seq_map.insert(MakeSeqMap::value_type(index, make_seq)).second; - assert(inserted); -} - -/** - * Returns a non-const reference to the indicated type, allowing the user to - * update it. - */ -InterrogateType &InterrogateDatabase:: -update_type(TypeIndex type) { - assert(type != 0); - check_latest(); - return _type_map[type]; -} - -/** - * Returns a non-const reference to the indicated function, allowing the user - * to update it. - */ -InterrogateFunction &InterrogateDatabase:: -update_function(FunctionIndex function) { - check_latest(); - return *_function_map[function]; -} - -/** - * Returns a non-const reference to the indicated function wrapper, allowing - * the user to update it. - */ -InterrogateFunctionWrapper &InterrogateDatabase:: -update_wrapper(FunctionWrapperIndex wrapper) { - check_latest(); - return _wrapper_map[wrapper]; -} - -/** - * Returns a non-const reference to the indicated manifest constant, allowing - * the user to update it. - */ -InterrogateManifest &InterrogateDatabase:: -update_manifest(ManifestIndex manifest) { - check_latest(); - return _manifest_map[manifest]; -} - -/** - * Returns a non-const reference to the indicated data element, allowing the - * user to update it. - */ -InterrogateElement &InterrogateDatabase:: -update_element(ElementIndex element) { - check_latest(); - return _element_map[element]; -} - -/** - * Returns a non-const reference to the indicated make_seq, allowing the user - * to update it. - */ -InterrogateMakeSeq &InterrogateDatabase:: -update_make_seq(MakeSeqIndex make_seq) { - check_latest(); - return _make_seq_map[make_seq]; -} - -/** - * Resequences all of the various index numbers so that all of the functions - * start at first_index and increment consecutively from there, and then all - * of the types follow. Returns the next available index number. - */ -int InterrogateDatabase:: -remap_indices(int first_index) { - IndexRemapper remap; - return remap_indices(first_index, remap); -} - -/** - * This flavor of remap_indices() accepts a map that should be empty on - * initial call, and will be filled with the mapping of old index number to - * new index number. This allows the caller to update its own data structures - * to match the new index numbers. - */ -int InterrogateDatabase:: -remap_indices(int first_index, IndexRemapper &remap) { - remap.clear(); - - // First, build up the complete map. - - // Get the wrapper indices first. This is important, because the - // InterrogateBuilder wants these to be first, and consecutive. - FunctionWrapperMap new_wrapper_map; - FunctionWrapperMap::iterator wi; - for (wi = _wrapper_map.begin(); wi != _wrapper_map.end(); ++wi) { - remap.add_mapping((*wi).first, first_index); - new_wrapper_map[first_index] = (*wi).second; - first_index++; - } - - // Everything else can follow; it doesn't matter so much. - FunctionMap new_function_map; - FunctionMap::iterator fi; - for (fi = _function_map.begin(); fi != _function_map.end(); ++fi) { - remap.add_mapping((*fi).first, first_index); - new_function_map[first_index] = (*fi).second; - first_index++; - } - - TypeMap new_type_map; - TypeMap::iterator ti; - for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) { - assert((*ti).first != 0); - remap.add_mapping((*ti).first, first_index); - new_type_map[first_index] = (*ti).second; - first_index++; - } - - ManifestMap new_manifest_map; - ManifestMap::iterator mi; - for (mi = _manifest_map.begin(); mi != _manifest_map.end(); ++mi) { - remap.add_mapping((*mi).first, first_index); - new_manifest_map[first_index] = (*mi).second; - first_index++; - } - - ElementMap new_element_map; - ElementMap::iterator ei; - for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) { - remap.add_mapping((*ei).first, first_index); - new_element_map[first_index] = (*ei).second; - first_index++; - } - - MakeSeqMap new_make_seq_map; - MakeSeqMap::iterator si; - for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) { - remap.add_mapping((*si).first, first_index); - new_make_seq_map[first_index] = (*si).second; - first_index++; - } - - _next_index = first_index; - - _wrapper_map.swap(new_wrapper_map); - _function_map.swap(new_function_map); - _type_map.swap(new_type_map); - _manifest_map.swap(new_manifest_map); - _element_map.swap(new_element_map); - _make_seq_map.swap(new_make_seq_map); - - // Then, go back through and update all of the internal references. - for (wi = _wrapper_map.begin(); wi != _wrapper_map.end(); ++wi) { - (*wi).second.remap_indices(remap); - } - for (fi = _function_map.begin(); fi != _function_map.end(); ++fi) { - (*fi).second->remap_indices(remap); - } - for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) { - (*ti).second.remap_indices(remap); - } - for (mi = _manifest_map.begin(); mi != _manifest_map.end(); ++mi) { - (*mi).second.remap_indices(remap); - } - for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) { - (*ei).second.remap_indices(remap); - } - for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) { - (*si).second.remap_indices(remap); - } - GlobalFunctions::iterator gfi; - for (gfi = _global_functions.begin(); gfi != _global_functions.end(); ++gfi) { - (*gfi) = remap.map_from(*gfi); - } - for (gfi = _all_functions.begin(); gfi != _all_functions.end(); ++gfi) { - (*gfi) = remap.map_from(*gfi); - } - GlobalTypes::iterator gti; - for (gti = _global_types.begin(); gti != _global_types.end(); ++gti) { - (*gti) = remap.map_from(*gti); - } - for (gti = _all_types.begin(); gti != _all_types.end(); ++gti) { - (*gti) = remap.map_from(*gti); - } - GlobalManifests::iterator gmi; - for (gmi = _global_manifests.begin(); gmi != _global_manifests.end(); ++gmi) { - (*gmi) = remap.map_from(*gmi); - } - GlobalElements::iterator gei; - for (gei = _global_elements.begin(); gei != _global_elements.end(); ++gei) { - (*gei) = remap.map_from(*gei); - } - - return _next_index; -} - -/** - * Writes the database to the indicated stream for later reading. - */ -void InterrogateDatabase:: -write(std::ostream &out, InterrogateModuleDef *def) const { - // Write out the file header. - out << def->file_identifier << "\n" - << _current_major_version << " " << _current_minor_version << "\n"; - - // Write out the module definition. - idf_output_string(out, def->library_name); - idf_output_string(out, def->library_hash_name); - idf_output_string(out, def->module_name); - out << "\n"; - - // Now write out the components. - - out << _function_map.size() << "\n"; - FunctionMap::const_iterator fi; - for (fi = _function_map.begin(); fi != _function_map.end(); ++fi) { - out << (*fi).first << " " << *(*fi).second << "\n"; - } - - out << _wrapper_map.size() << "\n"; - FunctionWrapperMap::const_iterator wi; - for (wi = _wrapper_map.begin(); wi != _wrapper_map.end(); ++wi) { - out << (*wi).first << " " << (*wi).second << "\n"; - } - - out << _type_map.size() << "\n"; - TypeMap::const_iterator ti; - for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) { - out << (*ti).first << " " << (*ti).second << "\n"; - } - - out << _manifest_map.size() << "\n"; - ManifestMap::const_iterator mi; - for (mi = _manifest_map.begin(); mi != _manifest_map.end(); ++mi) { - out << (*mi).first << " " << (*mi).second << "\n"; - } - - out << _element_map.size() << "\n"; - ElementMap::const_iterator ei; - for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) { - out << (*ei).first << " " << (*ei).second << "\n"; - } - - out << _make_seq_map.size() << "\n"; - MakeSeqMap::const_iterator si; - for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) { - out << (*si).first << " " << (*si).second << "\n"; - } -} - -/** - * Reads a database from the indicated stream, associated with the indicated - * module definition and merges it with any existing data in the database, - * according to the expected index numbers specified in the module def. The - * header information has already been read. - * - * Returns true if the file is read successfully, false if there is an error. - */ -bool InterrogateDatabase:: -read(std::istream &in, InterrogateModuleDef *def) { - InterrogateDatabase temp; - if (!temp.read_new(in, def)) { - return false; - } - - if (def->first_index == 0 && def->next_index == 0) { - _next_index = temp.remap_indices(_next_index); - - } else { - int next = temp.remap_indices(def->first_index); - if (next != def->next_index) { - interrogatedb_cat->error() - << "Module database file " << def->database_filename - << " is out of date.\n"; - return false; - } - } - - merge_from(temp); - return true; -} - -/** - * Reads in the latest interrogate data. - */ -void InterrogateDatabase:: -load_latest() { - const DSearchPath &searchpath = interrogatedb_path; - - Requests copy_requests; - copy_requests.swap(_requests); - - Requests::const_iterator ri; - for (ri = copy_requests.begin(); ri != copy_requests.end(); ++ri) { - InterrogateModuleDef *def = (*ri); - - if (def->database_filename != nullptr) { - Filename filename = def->database_filename; - Filename pathname = filename; - if (!pathname.empty() && pathname[0] != '/') { - pathname = searchpath.find_file(pathname); - } - - if (pathname.empty()) { - interrogatedb_cat->error() - << "Unable to find " << filename << " on " << searchpath << "\n"; - set_error_flag(true); - - } else { - - pifstream input; - pathname.set_text(); - if (!pathname.open_read(input)) { - interrogatedb_cat->error() << "Unable to read " << pathname << ".\n"; - set_error_flag(true); - - } else { - int file_identifier; - input >> file_identifier - >> _file_major_version >> _file_minor_version; - - if (def->file_identifier != 0 && - file_identifier != def->file_identifier) { - interrogatedb_cat->warning() - << "Interrogate data in " << pathname - << " is out of sync with the compiled-in data" - << " (" << file_identifier << " != " << def->file_identifier << ").\n"; - set_error_flag(true); - } - - if (_file_major_version != _current_major_version || - _file_minor_version > _current_minor_version) { - interrogatedb_cat->error() - << "Cannot read interrogate data in " << pathname - << "; database is version " << _file_major_version << "." - << _file_minor_version << " while we are expecting " - << _current_major_version << "." << _current_minor_version - << ".\n"; - set_error_flag(true); - - } else { - if (interrogatedb_cat->is_debug()) { - interrogatedb_cat->debug() - << "Reading " << filename << "\n"; - } - if (!read(input, def)) { - interrogatedb_cat->error() - << "Error reading " << pathname << ".\n"; - set_error_flag(true); - } - } - } - } - } - } - - _requests.clear(); -} - -/** - * Reads from the indicated stream (the header information has already been - * read) into the newly-created database. It is an error if the database - * already has some data in it. - */ -bool InterrogateDatabase:: -read_new(std::istream &in, InterrogateModuleDef *def) { - // We've already read the header. Read the module definition. - idf_input_string(in, def->library_name); - idf_input_string(in, def->library_hash_name); - idf_input_string(in, def->module_name); - - // Now read all of the components. - - { // Functions. - int num_functions; - in >> num_functions; - if (in.fail()) { - return false; - } - - while (num_functions > 0) { - FunctionIndex index; - InterrogateFunction *function = new InterrogateFunction(def); - in >> index >> *function; - if (in.fail()) { - delete function; - return false; - } - - add_function(index, function); - num_functions--; - } - } - - { // Wrappers. - int num_wrappers; - in >> num_wrappers; - if (in.fail()) { - return false; - } - - while (num_wrappers > 0) { - FunctionWrapperIndex index; - InterrogateFunctionWrapper wrapper(def); - in >> index >> wrapper; - if (in.fail()) { - return false; - } - - add_wrapper(index, wrapper); - num_wrappers--; - } - } - - { // Types. - int num_types; - in >> num_types; - if (in.fail()) { - return false; - } - - while (num_types > 0) { - TypeIndex index; - InterrogateType type(def); - in >> index >> type; - if (in.fail()) { - return false; - } - - add_type(index, type); - num_types--; - - // Older versions of interrogate were not setting these flags. - const InterrogateType &itype = get_type(index); - FunctionIndex dtor = itype.get_destructor(); - if (dtor != 0) { - update_function(dtor)._flags |= InterrogateFunction::F_destructor; - } - for (int i = 0; i < itype.number_of_constructors(); ++i) { - FunctionIndex ctor = itype.get_constructor(i); - update_function(ctor)._flags |= InterrogateFunction::F_constructor; - } - } - } - - { // Manifests. - int num_manifests; - in >> num_manifests; - if (in.fail()) { - return false; - } - - while (num_manifests > 0) { - ManifestIndex index; - InterrogateManifest manifest(def); - in >> index >> manifest; - if (in.fail()) { - return false; - } - - add_manifest(index, manifest); - num_manifests--; - } - } - - { // Elements. - int num_elements; - in >> num_elements; - if (in.fail()) { - return false; - } - - while (num_elements > 0) { - ElementIndex index; - InterrogateElement element(def); - in >> index >> element; - if (in.fail()) { - return false; - } - - add_element(index, element); - num_elements--; - } - } - - { // MakeSeqs. - int num_make_seqs; - in >> num_make_seqs; - if (in.fail()) { - return false; - } - - while (num_make_seqs > 0) { - MakeSeqIndex index; - InterrogateMakeSeq make_seq(def); - in >> index >> make_seq; - if (in.fail()) { - return false; - } - - add_make_seq(index, make_seq); - num_make_seqs--; - } - } - - return true; -} - -/** - * Copies all the data from the indicated database into this one. It is an - * error if any index numbers are shared between the two databases. - */ -void InterrogateDatabase:: -merge_from(const InterrogateDatabase &other) { - // We want to collapse shared types together. - IndexRemapper remap; - - // First, we need to build a set of types by name, so we know what types we - // already have. - map types_by_name; - - TypeMap::const_iterator ti; - for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) { - const InterrogateType &type = (*ti).second; - if (type.has_true_name()) { - types_by_name[type.get_true_name()] = (*ti).first; - } - } - - // Now go through the other set of types and determine the mapping into this - // set. - for (ti = other._type_map.begin(); ti != other._type_map.end(); ++ti) { - TypeIndex other_type_index = (*ti).first; - const InterrogateType &other_type = (*ti).second; - - if (other_type.has_name()) { - map::iterator ni; - ni = types_by_name.find(other_type.get_true_name()); - if (ni != types_by_name.end()) { - // Here's a type that we seem to have in common! We'll have to merge - // them. - TypeIndex this_type_index = (*ni).second; - remap.add_mapping(other_type_index, this_type_index); - } - } - } - - // Now that we know the full type-to-type mapping, we can copy the new - // types, one at a time. - for (ti = other._type_map.begin(); ti != other._type_map.end(); ++ti) { - TypeIndex other_type_index = (*ti).first; - const InterrogateType &other_type = (*ti).second; - - if (!remap.in_map(other_type_index)) { - // Here's a new type. - add_type(other_type_index, other_type); - update_type(other_type_index).remap_indices(remap); - - } else { - // Here's a type to merge. - TypeIndex this_type_index = remap.map_from(other_type_index); - - InterrogateType &this_type = update_type(this_type_index); - if (!this_type.is_global() && other_type.is_global()) { - // If the type is about to become global, we need to add it to our - // global_types list. - _global_types.push_back(this_type_index); - } - - InterrogateType merge_type = other_type; - merge_type.remap_indices(remap); - this_type.merge_with(merge_type); - } - } - - // And copy all of the functions, wrappers, manifests, and elements. - FunctionMap::const_iterator fi; - for (fi = other._function_map.begin(); - fi != other._function_map.end(); - ++fi) { - FunctionIndex other_function_index = (*fi).first; - InterrogateFunction *other_function = (*fi).second; - add_function(other_function_index, other_function); - update_function(other_function_index).remap_indices(remap); - } - - FunctionWrapperMap::const_iterator wi; - for (wi = other._wrapper_map.begin(); - wi != other._wrapper_map.end(); - ++wi) { - FunctionWrapperIndex other_wrapper_index = (*wi).first; - const InterrogateFunctionWrapper &other_wrapper = (*wi).second; - add_wrapper(other_wrapper_index, other_wrapper); - update_wrapper(other_wrapper_index).remap_indices(remap); - } - - ManifestMap::const_iterator mi; - for (mi = other._manifest_map.begin(); - mi != other._manifest_map.end(); - ++mi) { - ManifestIndex other_manifest_index = (*mi).first; - const InterrogateManifest &other_manifest = (*mi).second; - add_manifest(other_manifest_index, other_manifest); - update_manifest(other_manifest_index).remap_indices(remap); - } - - ElementMap::const_iterator ei; - for (ei = other._element_map.begin(); - ei != other._element_map.end(); - ++ei) { - ElementIndex other_element_index = (*ei).first; - const InterrogateElement &other_element = (*ei).second; - add_element(other_element_index, other_element); - update_element(other_element_index).remap_indices(remap); - } - - MakeSeqMap::const_iterator si; - for (si = other._make_seq_map.begin(); - si != other._make_seq_map.end(); - ++si) { - MakeSeqIndex other_make_seq_index = (*si).first; - const InterrogateMakeSeq &other_make_seq = (*si).second; - add_make_seq(other_make_seq_index, other_make_seq); - update_make_seq(other_make_seq_index).remap_indices(remap); - } - - _lookups_fresh = 0; -} - -/** - * Looks up the wrapper definition in the set of module defs that are loaded - * in at runtime and represent the part of the interrogate database that's - * compiled in. - * - * If the wrapper definition is not found, returns false. If it is found, - * returns true and sets def and module_index to the particular module and the - * index within the module where the wrapper is defined. - */ -bool InterrogateDatabase:: -find_module(FunctionWrapperIndex wrapper, InterrogateModuleDef *&def, - int &module_index) { - if (_modules.empty()) { - return false; - } - - int mi = binary_search_module(0, _modules.size(), wrapper); - assert(mi >= 0 && mi < (int)_modules.size()); - def = _modules[mi]; - module_index = wrapper - def->first_index; - - return (wrapper < def->next_index); -} - -/** - * Searches for the function module that includes the given function index by - * binary search. - */ -int InterrogateDatabase:: -binary_search_module(int begin, int end, FunctionIndex function) { - int mid = begin + (end - begin) / 2; - if (mid == begin) { - return mid; - } - - int index = _modules[mid]->first_index; - if (index <= function) { - return binary_search_module(mid, end, function); - - } else { - return binary_search_module(begin, mid, function); - } -} - -/** - * Searches for the particular function wrapper's hash name within a given - * module. Returns the index number local to the module, or -1 if it is not - * found. - */ -int InterrogateDatabase:: -binary_search_wrapper_hash(InterrogateUniqueNameDef *begin, - InterrogateUniqueNameDef *end, - const string &wrapper_hash_name) { - if (end <= begin) { - return -1; - } - - InterrogateUniqueNameDef *mid = begin + (end - begin) / 2; - string name = mid->name; - if (name < wrapper_hash_name) { - return binary_search_wrapper_hash(mid, end, wrapper_hash_name); - - } else if (wrapper_hash_name < name) { - return binary_search_wrapper_hash(begin, mid, wrapper_hash_name); - - } else { - return mid->index_offset; - } -} - -/** - * Builds up the lookup of types by name. - */ -void InterrogateDatabase:: -freshen_types_by_name() { - _types_by_name.clear(); - TypeMap::const_iterator ti; - for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) { - _types_by_name[(*ti).second.get_name()] = (*ti).first; - } -} - -/** - * Builds up the lookup of types by scoped name. - */ -void InterrogateDatabase:: -freshen_types_by_scoped_name() { - _types_by_scoped_name.clear(); - TypeMap::const_iterator ti; - for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) { - _types_by_scoped_name[(*ti).second.get_scoped_name()] = (*ti).first; - } -} - -/** - * Builds up the lookup of types by true name. - */ -void InterrogateDatabase:: -freshen_types_by_true_name() { - _types_by_true_name.clear(); - TypeMap::const_iterator ti; - for (ti = _type_map.begin(); ti != _type_map.end(); ++ti) { - _types_by_true_name[(*ti).second.get_true_name()] = (*ti).first; - } -} - -/** - * Builds up the lookup of manifests by name. - */ -void InterrogateDatabase:: -freshen_manifests_by_name() { - _manifests_by_name.clear(); - ManifestMap::const_iterator ti; - for (ti = _manifest_map.begin(); ti != _manifest_map.end(); ++ti) { - _manifests_by_name[(*ti).second.get_name()] = (*ti).first; - } -} - -/** - * Builds up the lookup of elements by name. - */ -void InterrogateDatabase:: -freshen_elements_by_name() { - _elements_by_name.clear(); - ElementMap::const_iterator ti; - for (ti = _element_map.begin(); ti != _element_map.end(); ++ti) { - _elements_by_name[(*ti).second.get_name()] = (*ti).first; - } -} - -/** - * Builds up the lookup of elements by scoped name. - */ -void InterrogateDatabase:: -freshen_elements_by_scoped_name() { - _elements_by_scoped_name.clear(); - ElementMap::const_iterator ti; - for (ti = _element_map.begin(); ti != _element_map.end(); ++ti) { - _elements_by_scoped_name[(*ti).second.get_scoped_name()] = (*ti).first; - } -} - -/** - * Looks up a type, manifest, or element in the indicated lookup table by - * name. This is an internal support function. - */ -int InterrogateDatabase:: -lookup(const string &name, Lookup &lookup, LookupType type, - void (InterrogateDatabase::*freshen)()) { - if ((_lookups_fresh & (int)type) == 0) { - // The lookup table isn't fresh; we need to freshen it. - (this->*freshen)(); - _lookups_fresh |= (int)type; - } - - Lookup::const_iterator li; - li = lookup.find(name); - if (li != lookup.end()) { - return (*li).second; - } - return 0; -} diff --git a/dtool/src/interrogatedb/interrogateDatabase.h b/dtool/src/interrogatedb/interrogateDatabase.h deleted file mode 100644 index 9c60b0318e..0000000000 --- a/dtool/src/interrogatedb/interrogateDatabase.h +++ /dev/null @@ -1,205 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateDatabase.h - * @author drose - * @date 2000-08-01 - */ - -#ifndef INTERROGATEDATABASE_H -#define INTERROGATEDATABASE_H - -#include "dtoolbase.h" - -#include "interrogate_interface.h" -#include "interrogateType.h" -#include "interrogateFunction.h" -#include "interrogateFunctionWrapper.h" -#include "interrogateManifest.h" -#include "interrogateElement.h" -#include "interrogateMakeSeq.h" -#include "interrogate_request.h" - -#include - -class IndexRemapper; - -/** - * This stores all of the interrogate data and handles reading the data from a - * disk file when necessary. - */ -class EXPCL_INTERROGATEDB InterrogateDatabase { -private: - InterrogateDatabase(); - -public: - static InterrogateDatabase *get_ptr(); - void request_module(InterrogateModuleDef *def); - -public: - // Functions to read the database. - bool get_error_flag(); - - int get_num_global_types(); - TypeIndex get_global_type(int n); - int get_num_all_types(); - TypeIndex get_all_type(int n); - int get_num_global_functions(); - FunctionIndex get_global_function(int n); - int get_num_all_functions(); - FunctionIndex get_all_function(int n); - int get_num_global_manifests(); - ManifestIndex get_global_manifest(int n); - int get_num_global_elements(); - ElementIndex get_global_element(int n); - - const InterrogateType &get_type(TypeIndex type); - const InterrogateFunction &get_function(FunctionIndex function); - const InterrogateFunctionWrapper &get_wrapper(FunctionWrapperIndex wrapper); - const InterrogateManifest &get_manifest(ManifestIndex manifest); - const InterrogateElement &get_element(ElementIndex element); - const InterrogateMakeSeq &get_make_seq(MakeSeqIndex element); - - INLINE TypeIndex lookup_type_by_name(const std::string &name); - INLINE TypeIndex lookup_type_by_scoped_name(const std::string &name); - INLINE TypeIndex lookup_type_by_true_name(const std::string &name); - INLINE ManifestIndex lookup_manifest_by_name(const std::string &name); - INLINE ElementIndex lookup_element_by_name(const std::string &name); - INLINE ElementIndex lookup_element_by_scoped_name(const std::string &name); - - void remove_type(TypeIndex type); - - void *get_fptr(FunctionWrapperIndex wrapper); - - FunctionWrapperIndex get_wrapper_by_unique_name(const std::string &unique_name); - - static int get_file_major_version(); - static int get_file_minor_version(); - static int get_current_major_version(); - static int get_current_minor_version(); - -public: - // Functions to build the database. - void set_error_flag(bool error_flag); - - int get_next_index(); - void add_type(TypeIndex index, const InterrogateType &type); - void add_function(FunctionIndex index, InterrogateFunction *function); - void add_wrapper(FunctionWrapperIndex index, - const InterrogateFunctionWrapper &wrapper); - void add_manifest(ManifestIndex index, const InterrogateManifest &manifest); - void add_element(ElementIndex index, const InterrogateElement &element); - void add_make_seq(MakeSeqIndex index, const InterrogateMakeSeq &make_seq); - - InterrogateType &update_type(TypeIndex type); - InterrogateFunction &update_function(FunctionIndex function); - InterrogateFunctionWrapper &update_wrapper(FunctionWrapperIndex wrapper); - InterrogateManifest &update_manifest(ManifestIndex manifest); - InterrogateElement &update_element(ElementIndex element); - InterrogateMakeSeq &update_make_seq(MakeSeqIndex make_seq); - - int remap_indices(int first_index); - int remap_indices(int first_index, IndexRemapper &remap); - - void write(std::ostream &out, InterrogateModuleDef *def) const; - bool read(std::istream &in, InterrogateModuleDef *def); - -private: - INLINE void check_latest(); - void load_latest(); - - bool read_new(std::istream &in, InterrogateModuleDef *def); - void merge_from(const InterrogateDatabase &other); - - bool find_module(FunctionWrapperIndex wrapper, - InterrogateModuleDef *&def, int &module_index); - int binary_search_module(int begin, int end, FunctionIndex function); - int binary_search_wrapper_hash(InterrogateUniqueNameDef *begin, - InterrogateUniqueNameDef *end, - const std::string &wrapper_hash_name); - - // This data is loaded from the various database files. - typedef std::map TypeMap; - TypeMap _type_map; - typedef std::map FunctionMap; - FunctionMap _function_map; - typedef std::map FunctionWrapperMap; - FunctionWrapperMap _wrapper_map; - - typedef std::map ManifestMap; - ManifestMap _manifest_map; - typedef std::map ElementMap; - ElementMap _element_map; - - typedef std::map MakeSeqMap; - MakeSeqMap _make_seq_map; - - typedef std::vector GlobalTypes; - GlobalTypes _global_types; - GlobalTypes _all_types; - typedef std::vector GlobalFunctions; - GlobalFunctions _global_functions; - GlobalFunctions _all_functions; - typedef std::vector GlobalManifests; - GlobalManifests _global_manifests; - typedef std::vector GlobalElements; - GlobalElements _global_elements; - - // This data is compiled in directly to the shared libraries that we link - // with. - typedef std::vector Modules; - Modules _modules; - typedef std::map ModulesByHash; - ModulesByHash _modules_by_hash; - - // This records the set of database files that are still to be loaded. - typedef std::vector Requests; - Requests _requests; - - bool _error_flag; - int _next_index; - - enum LookupType { - LT_type_name = 0x001, - LT_type_scoped_name = 0x002, - LT_type_true_name = 0x004, - LT_manifest_name = 0x008, - LT_element_name = 0x010, - LT_element_scoped_name = 0x020, - }; - - int _lookups_fresh; - typedef std::map Lookup; - Lookup _types_by_name; - Lookup _types_by_scoped_name; - Lookup _types_by_true_name; - Lookup _manifests_by_name; - Lookup _elements_by_name; - Lookup _elements_by_scoped_name; - - void freshen_types_by_name(); - void freshen_types_by_scoped_name(); - void freshen_types_by_true_name(); - void freshen_manifests_by_name(); - void freshen_elements_by_name(); - void freshen_elements_by_scoped_name(); - - int lookup(const std::string &name, - Lookup &lookup, LookupType type, - void (InterrogateDatabase::*freshen)()); - - static InterrogateDatabase *_global_ptr; - static int _file_major_version; - static int _file_minor_version; - static int _current_major_version; - static int _current_minor_version; -}; - -#include "interrogateDatabase.I" - -#endif diff --git a/dtool/src/interrogatedb/interrogateElement.I b/dtool/src/interrogatedb/interrogateElement.I deleted file mode 100644 index 93e6889b16..0000000000 --- a/dtool/src/interrogatedb/interrogateElement.I +++ /dev/null @@ -1,259 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateElement.I - * @author drose - * @date 2000-08-11 - */ - -/** - * - */ -INLINE InterrogateElement:: -InterrogateElement(InterrogateModuleDef *def) : - InterrogateComponent(def) -{ - _flags = 0; - _type = 0; - _getter = 0; - _setter = 0; - _has_function = 0; - _clear_function = 0; - _del_function = 0; - _insert_function = 0; - _getkey_function = 0; - _length_function = 0; - _make_property = nullptr; -} - -/** - * - */ -INLINE InterrogateElement:: -InterrogateElement(const InterrogateElement ©) { - (*this) = copy; -} - -/** - * - */ -INLINE void InterrogateElement:: -operator = (const InterrogateElement ©) { - InterrogateComponent::operator = (copy); - _flags = copy._flags; - _scoped_name = copy._scoped_name; - _comment = copy._comment; - _type = copy._type; - _getter = copy._getter; - _setter = copy._setter; - _has_function = copy._has_function; - _clear_function = copy._clear_function; - _del_function = copy._del_function; - _insert_function = copy._insert_function; - _getkey_function = copy._getkey_function; - _length_function = copy._length_function; - _make_property = copy._make_property; -} - -/** - * Returns true if the element is marked as 'global'. This means only that it - * should appear in the global element list. - */ -INLINE bool InterrogateElement:: -is_global() const { - return (_flags & F_global) != 0; -} - -/** - * - */ -INLINE bool InterrogateElement:: -has_scoped_name() const { - return !_scoped_name.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateElement:: -get_scoped_name() const { - return _scoped_name; -} - -/** - * - */ -INLINE bool InterrogateElement:: -has_comment() const { - return !_comment.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateElement:: -get_comment() const { - return _comment; -} - -/** - * - */ -INLINE TypeIndex InterrogateElement:: -get_type() const { - return _type; -} - -/** - * - */ -INLINE bool InterrogateElement:: -has_getter() const { - return (_flags & F_has_getter) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateElement:: -get_getter() const { - return _getter; -} - -/** - * - */ -INLINE bool InterrogateElement:: -has_setter() const { - return (_flags & F_has_setter) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateElement:: -get_setter() const { - return _setter; -} - -/** - * - */ -INLINE bool InterrogateElement:: -has_has_function() const { - return (_flags & F_has_has_function) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateElement:: -get_has_function() const { - return _has_function; -} - -/** - * - */ -INLINE bool InterrogateElement:: -has_clear_function() const { - return (_flags & F_has_clear_function) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateElement:: -get_clear_function() const { - return _clear_function; -} - -/** - * - */ -INLINE bool InterrogateElement:: -has_del_function() const { - return (_flags & F_has_del_function) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateElement:: -get_del_function() const { - return _del_function; -} - -/** - * - */ -INLINE bool InterrogateElement:: -has_insert_function() const { - return (_flags & F_has_insert_function) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateElement:: -get_insert_function() const { - return _insert_function; -} - -/** - * - */ -INLINE bool InterrogateElement:: -has_getkey_function() const { - return (_flags & F_has_getkey_function) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateElement:: -get_getkey_function() const { - return _getkey_function; -} - -/** - * - */ -INLINE bool InterrogateElement:: -is_sequence() const { - return (_flags & F_sequence) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateElement:: -get_length_function() const { - return _length_function; -} - -/** - * - */ -INLINE bool InterrogateElement:: -is_mapping() const { - return (_flags & F_mapping) != 0; -} - - -INLINE std::ostream & -operator << (std::ostream &out, const InterrogateElement &element) { - element.output(out); - return out; -} - -INLINE std::istream & -operator >> (std::istream &in, InterrogateElement &element) { - element.input(in); - return in; -} diff --git a/dtool/src/interrogatedb/interrogateElement.cxx b/dtool/src/interrogatedb/interrogateElement.cxx deleted file mode 100644 index 4b6b3d948f..0000000000 --- a/dtool/src/interrogatedb/interrogateElement.cxx +++ /dev/null @@ -1,74 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateElement.cxx - * @author drose - * @date 2000-08-11 - */ - -#include "interrogateElement.h" -#include "interrogateDatabase.h" -#include "indexRemapper.h" -#include "interrogate_datafile.h" - -/** - * Formats the InterrogateElement data for output to a data file. - */ -void InterrogateElement:: -output(std::ostream &out) const { - InterrogateComponent::output(out); - out << _flags << " " - << _type << " " - << _getter << " " - << _setter << " " - << _has_function << " " - << _clear_function << " " - << _del_function << " " - << _length_function << " " - << _insert_function << " " - << _getkey_function << " "; - idf_output_string(out, _scoped_name); - idf_output_string(out, _comment, '\n'); -} - -/** - * Reads the data file as previously formatted by output(). - */ -void InterrogateElement:: -input(std::istream &in) { - InterrogateComponent::input(in); - in >> _flags >> _type >> _getter >> _setter; - if (InterrogateDatabase::get_file_minor_version() >= 1) { - in >> _has_function >> _clear_function; - if (InterrogateDatabase::get_file_minor_version() >= 2) { - in >> _del_function >> _length_function; - if (InterrogateDatabase::get_file_minor_version() >= 3) { - in >> _insert_function >> _getkey_function; - } - } - } - idf_input_string(in, _scoped_name); - idf_input_string(in, _comment); -} - -/** - * Remaps all internal index numbers according to the indicated map. This - * called from InterrogateDatabase::remap_indices(). - */ -void InterrogateElement:: -remap_indices(const IndexRemapper &remap) { - _type = remap.map_from(_type); - _getter = remap.map_from(_getter); - _setter = remap.map_from(_setter); - _has_function = remap.map_from(_has_function); - _clear_function = remap.map_from(_clear_function); - _del_function = remap.map_from(_del_function); - _insert_function = remap.map_from(_insert_function); - _getkey_function = remap.map_from(_getkey_function); - _length_function = remap.map_from(_length_function); -} diff --git a/dtool/src/interrogatedb/interrogateElement.h b/dtool/src/interrogatedb/interrogateElement.h deleted file mode 100644 index e3d55569f0..0000000000 --- a/dtool/src/interrogatedb/interrogateElement.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateElement.h - * @author drose - * @date 2000-08-11 - */ - -#ifndef INTERROGATEELEMENT_H -#define INTERROGATEELEMENT_H - -#include "dtoolbase.h" - -#include "interrogateComponent.h" - -class IndexRemapper; -class CPPMakeProperty; - -/** - * An internal representation of a data element, like a data member or a - * global variable. - */ -class EXPCL_INTERROGATEDB InterrogateElement : public InterrogateComponent { -public: - INLINE InterrogateElement(InterrogateModuleDef *def = nullptr); - INLINE InterrogateElement(const InterrogateElement ©); - INLINE void operator = (const InterrogateElement ©); - - INLINE bool is_global() const; - - INLINE bool has_scoped_name() const; - INLINE const std::string &get_scoped_name() const; - - INLINE bool has_comment() const; - INLINE const std::string &get_comment() const; - - INLINE TypeIndex get_type() const; - INLINE bool has_getter() const; - INLINE FunctionIndex get_getter() const; - INLINE bool has_setter() const; - INLINE FunctionIndex get_setter() const; - INLINE bool has_has_function() const; - INLINE FunctionIndex get_has_function() const; - INLINE bool has_clear_function() const; - INLINE FunctionIndex get_clear_function() const; - INLINE bool has_del_function() const; - INLINE FunctionIndex get_del_function() const; - INLINE bool has_insert_function() const; - INLINE FunctionIndex get_insert_function() const; - INLINE bool has_getkey_function() const; - INLINE FunctionIndex get_getkey_function() const; - INLINE bool is_sequence() const; - INLINE FunctionIndex get_length_function() const; - INLINE bool is_mapping() const; - - void output(std::ostream &out) const; - void input(std::istream &in); - - void remap_indices(const IndexRemapper &remap); - -private: - enum Flags { - F_global = 0x0001, - F_has_getter = 0x0002, - F_has_setter = 0x0004, - F_has_has_function= 0x0008, - F_has_clear_function= 0x0010, - F_has_del_function= 0x0020, - F_sequence = 0x0040, - F_mapping = 0x0080, - F_has_insert_function= 0x0100, - F_has_getkey_function= 0x0200, - }; - - int _flags; - std::string _scoped_name; - std::string _comment; - TypeIndex _type; - FunctionIndex _length_function; - FunctionIndex _getter; - FunctionIndex _setter; - FunctionIndex _has_function; - FunctionIndex _clear_function; - FunctionIndex _del_function; - FunctionIndex _insert_function; - FunctionIndex _getkey_function; - - CPPMakeProperty *_make_property; - - friend class InterrogateBuilder; -}; - -INLINE std::ostream &operator << (std::ostream &out, const InterrogateElement &element); -INLINE std::istream &operator >> (std::istream &in, InterrogateElement &element); - -#include "interrogateElement.I" - -#endif diff --git a/dtool/src/interrogatedb/interrogateFunction.I b/dtool/src/interrogatedb/interrogateFunction.I deleted file mode 100644 index 6c36fec5d3..0000000000 --- a/dtool/src/interrogatedb/interrogateFunction.I +++ /dev/null @@ -1,178 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateFunction.I - * @author drose - * @date 2000-08-01 - */ - -/** - * Returns true if the function is marked as 'global'. This means only that it - * should appear in the global function list. - */ -INLINE bool InterrogateFunction:: -is_global() const { - return (_flags & F_global) != 0; -} - -/** - * Returns true if the function is virtual, for whatever that's worth. - */ -INLINE bool InterrogateFunction:: -is_virtual() const { - return (_flags & F_virtual) != 0; -} - -/** - * Returns true if the function is a class method. - */ -INLINE bool InterrogateFunction:: -is_method() const { - return (_flags & F_method) != 0; -} - -/** - * Returns true if the function is flagged as a special unary operator, like - * operator -() with no parameters. - */ -INLINE bool InterrogateFunction:: -is_unary_op() const { - return (_flags & F_unary_op) != 0; -} - -/** - * Returns true if the function is a special typecast operator, like operator - * bool(). - */ -INLINE bool InterrogateFunction:: -is_operator_typecast() const { - return (_flags & F_operator_typecast) != 0; -} - -/** - * Returns true if the function is a constructor. - */ -INLINE bool InterrogateFunction:: -is_constructor() const { - return (_flags & F_constructor) != 0; -} - -/** - * Returns true if the function is a destructor. - */ -INLINE bool InterrogateFunction:: -is_destructor() const { - return (_flags & F_destructor) != 0; -} - -/** - * Return the class that owns the method, if is_method() returns true. - */ -INLINE TypeIndex InterrogateFunction:: -get_class() const { - return _class; -} - -/** - * - */ -INLINE bool InterrogateFunction:: -has_scoped_name() const { - return !_scoped_name.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateFunction:: -get_scoped_name() const { - return _scoped_name; -} - -/** - * - */ -INLINE bool InterrogateFunction:: -has_comment() const { - return !_comment.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateFunction:: -get_comment() const { - return _comment; -} - -/** - * - */ -INLINE bool InterrogateFunction:: -has_prototype() const { - return !_prototype.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateFunction:: -get_prototype() const { - return _prototype; -} - -/** - * - */ -INLINE int InterrogateFunction:: -number_of_c_wrappers() const { - return _c_wrappers.size(); -} - -/** - * - */ -INLINE FunctionWrapperIndex InterrogateFunction:: -get_c_wrapper(int n) const { - if (n >= 0 && n < (int)_c_wrappers.size()) { - return _c_wrappers[n]; - } - return 0; -} - -/** - * - */ -INLINE int InterrogateFunction:: -number_of_python_wrappers() const { - return _python_wrappers.size(); -} - -/** - * - */ -INLINE FunctionWrapperIndex InterrogateFunction:: -get_python_wrapper(int n) const { - if (n >= 0 && n < (int)_python_wrappers.size()) { - return _python_wrappers[n]; - } - return 0; -} - - -INLINE std::ostream & -operator << (std::ostream &out, const InterrogateFunction &function) { - function.output(out); - return out; -} - -INLINE std::istream & -operator >> (std::istream &in, InterrogateFunction &function) { - function.input(in); - return in; -} diff --git a/dtool/src/interrogatedb/interrogateFunction.cxx b/dtool/src/interrogatedb/interrogateFunction.cxx deleted file mode 100644 index db70cc0b9c..0000000000 --- a/dtool/src/interrogatedb/interrogateFunction.cxx +++ /dev/null @@ -1,100 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateFunction.cxx - * @author drose - * @date 2000-08-01 - */ - -#include "interrogateFunction.h" -#include "indexRemapper.h" -#include "interrogate_datafile.h" -#include "interrogateDatabase.h" - -/** - * - */ -InterrogateFunction:: -InterrogateFunction(InterrogateModuleDef *def) : - InterrogateComponent(def) -{ - _flags = 0; - _class = 0; - _instances = nullptr; -} - -/** - * - */ -InterrogateFunction:: -InterrogateFunction(const InterrogateFunction ©) { - (*this) = copy; -} - -/** - * - */ -void InterrogateFunction:: -operator = (const InterrogateFunction ©) { - InterrogateComponent::operator = (copy); - _flags = copy._flags; - _scoped_name = copy._scoped_name; - _comment = copy._comment; - _prototype = copy._prototype; - _class = copy._class; - _c_wrappers = copy._c_wrappers; - _python_wrappers = copy._python_wrappers; - - _instances = copy._instances; - _expression = copy._expression; -} - -/** - * Formats the InterrogateFunction data for output to a data file. - */ -void InterrogateFunction:: -output(std::ostream &out) const { - InterrogateComponent::output(out); - out << _flags << " " - << _class << " "; - idf_output_string(out, _scoped_name); - idf_output_vector(out, _c_wrappers); - idf_output_vector(out, _python_wrappers); - idf_output_string(out, _comment, '\n'); - idf_output_string(out, _prototype, '\n'); -} - -/** - * Reads the data file as previously formatted by output(). - */ -void InterrogateFunction:: -input(std::istream &in) { - InterrogateComponent::input(in); - in >> _flags >> _class; - idf_input_string(in, _scoped_name); - idf_input_vector(in, _c_wrappers); - idf_input_vector(in, _python_wrappers); - idf_input_string(in, _comment); - idf_input_string(in, _prototype); -} - -/** - * Remaps all internal index numbers according to the indicated map. This - * called from InterrogateDatabase::remap_indices(). - */ -void InterrogateFunction:: -remap_indices(const IndexRemapper &remap) { - _class = remap.map_from(_class); - Wrappers::iterator wi; - for (wi = _c_wrappers.begin(); wi != _c_wrappers.end(); ++wi) { - (*wi) = remap.map_from(*wi); - } - for (wi = _python_wrappers.begin(); wi != _python_wrappers.end(); ++wi) { - (*wi) = remap.map_from(*wi); - } -} diff --git a/dtool/src/interrogatedb/interrogateFunction.h b/dtool/src/interrogatedb/interrogateFunction.h deleted file mode 100644 index 76f4f20ccd..0000000000 --- a/dtool/src/interrogatedb/interrogateFunction.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateFunction.h - * @author drose - * @date 2000-08-01 - */ - -#ifndef INTERROGATEFUNCTION_H -#define INTERROGATEFUNCTION_H - -#include "dtoolbase.h" - -#include "interrogateComponent.h" - -#include -#include - -class IndexRemapper; -class CPPInstance; - -/** - * An internal representation of a function. - */ -class EXPCL_INTERROGATEDB InterrogateFunction : public InterrogateComponent { -public: - InterrogateFunction(InterrogateModuleDef *def = nullptr); - InterrogateFunction(const InterrogateFunction ©); - void operator = (const InterrogateFunction ©); - - INLINE bool is_global() const; - INLINE bool is_virtual() const; - INLINE bool is_method() const; - INLINE bool is_unary_op() const; - INLINE bool is_operator_typecast() const; - INLINE bool is_constructor() const; - INLINE bool is_destructor() const; - INLINE TypeIndex get_class() const; - - INLINE bool has_scoped_name() const; - INLINE const std::string &get_scoped_name() const; - - INLINE bool has_comment() const; - INLINE const std::string &get_comment() const; - - INLINE bool has_prototype() const; - INLINE const std::string &get_prototype() const; - - INLINE int number_of_c_wrappers() const; - INLINE FunctionWrapperIndex get_c_wrapper(int n) const; - - INLINE int number_of_python_wrappers() const; - INLINE FunctionWrapperIndex get_python_wrapper(int n) const; - - void output(std::ostream &out) const; - void input(std::istream &in); - - void remap_indices(const IndexRemapper &remap); - -private: - enum Flags { - F_global = 0x0001, - F_virtual = 0x0002, - F_method = 0x0004, - F_typecast = 0x0008, - F_getter = 0x0010, - F_setter = 0x0020, - F_unary_op = 0x0040, - F_operator_typecast = 0x0080, - F_constructor = 0x0100, - F_destructor = 0x0200, - F_item_assignment = 0x0400, - }; - - int _flags; - std::string _scoped_name; - std::string _comment; - std::string _prototype; - TypeIndex _class; - - typedef std::vector Wrappers; - Wrappers _c_wrappers; - Wrappers _python_wrappers; - -public: - // The rest of the members in this class aren't part of the public interface - // to interrogate, but are used internally as the interrogate database is - // built. They are valid only during the session of interrogate that - // generates the database, and will not be filled in when the database is - // reloaded from disk. - - // This must be a pointer, rather than a concrete map, so we don't risk - // trying to create a map in one DLL and access it in another. Silly - // Windows. - typedef std::map Instances; - Instances *_instances; - std::string _expression; - - friend class InterrogateBuilder; - friend class InterrogateDatabase; - friend class InterfaceMakerC; - friend class InterfaceMakerPythonSimple; - friend class InterfaceMakerPythonNative; - friend class FunctionRemap; -}; - -INLINE std::ostream &operator << (std::ostream &out, const InterrogateFunction &function); -INLINE std::istream &operator >> (std::istream &in, InterrogateFunction &function); - -#include "interrogateFunction.I" - -#endif diff --git a/dtool/src/interrogatedb/interrogateFunctionWrapper.I b/dtool/src/interrogatedb/interrogateFunctionWrapper.I deleted file mode 100644 index 93fff488b0..0000000000 --- a/dtool/src/interrogatedb/interrogateFunctionWrapper.I +++ /dev/null @@ -1,240 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateFunctionWrapper.I - * @author drose - * @date 2000-08-06 - */ - -/** - * - */ -INLINE InterrogateFunctionWrapper:: -InterrogateFunctionWrapper(InterrogateModuleDef *def) : - InterrogateComponent(def) -{ - _flags = 0; - _function = 0; - _return_type = 0; - _return_value_destructor = 0; -} - -/** - * - */ -INLINE InterrogateFunctionWrapper:: -InterrogateFunctionWrapper(const InterrogateFunctionWrapper ©) { - (*this) = copy; -} - -/** - * - */ -INLINE void InterrogateFunctionWrapper:: -operator = (const InterrogateFunctionWrapper ©) { - InterrogateComponent::operator = (copy); - _flags = copy._flags; - _function = copy._function; - _return_type = copy._return_type; - _return_value_destructor = copy._return_value_destructor; - _unique_name = copy._unique_name; - _comment = copy._comment; - _parameters = copy._parameters; -} - -/** - * Returns the FunctionIndex of the function that this wrapper corresponds to. - */ -INLINE FunctionIndex InterrogateFunctionWrapper:: -get_function() const { - return _function; -} - -/** - * - */ -INLINE bool InterrogateFunctionWrapper:: -is_callable_by_name() const { - return (_flags & F_callable_by_name) != 0; -} - -/** - * @since 1.10.13 - */ -INLINE bool InterrogateFunctionWrapper:: -is_copy_constructor() const { - return (_flags & F_copy_constructor) != 0; -} - -/** - * @since 1.10.13 - */ -INLINE bool InterrogateFunctionWrapper:: -is_coerce_constructor() const { - return (_flags & F_coerce_constructor) != 0; -} - -/** - * @since 1.10.13 - */ -INLINE bool InterrogateFunctionWrapper:: -is_extension() const { - return (_flags & F_extension) != 0; -} - -/** - * @since 1.11.0 - */ -INLINE bool InterrogateFunctionWrapper:: -is_deprecated() const { - return (_flags & F_deprecated) != 0; -} - -/** - * - */ -INLINE bool InterrogateFunctionWrapper:: -has_return_value() const { - return (_flags & F_has_return) != 0; -} - -/** - * - */ -INLINE TypeIndex InterrogateFunctionWrapper:: -get_return_type() const { - return _return_type; -} - -/** - * - */ -INLINE bool InterrogateFunctionWrapper:: -caller_manages_return_value() const { - return (_flags & F_caller_manages) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateFunctionWrapper:: -get_return_value_destructor() const { - return _return_value_destructor; -} - -/** - * - */ -INLINE int InterrogateFunctionWrapper:: -number_of_parameters() const { - return _parameters.size(); -} - -/** - * - */ -INLINE TypeIndex InterrogateFunctionWrapper:: -parameter_get_type(int n) const { - if (n >= 0 && n < (int)_parameters.size()) { - return _parameters[n]._type; - } - return 0; -} - -/** - * - */ -INLINE bool InterrogateFunctionWrapper:: -parameter_has_name(int n) const { - if (n >= 0 && n < (int)_parameters.size()) { - return (_parameters[n]._parameter_flags & PF_has_name) != 0; - } - return false; -} - -/** - * - */ -INLINE const std::string &InterrogateFunctionWrapper:: -parameter_get_name(int n) const { - static std::string bogus_string; - if (n >= 0 && n < (int)_parameters.size()) { - return _parameters[n]._name; - } - return bogus_string; -} - -/** - * - */ -INLINE bool InterrogateFunctionWrapper:: -parameter_is_this(int n) const { - if (n >= 0 && n < (int)_parameters.size()) { - return (_parameters[n]._parameter_flags & PF_is_this) != 0; - } - return false; -} - -/** - * - */ -INLINE bool InterrogateFunctionWrapper:: -parameter_is_optional(int n) const { - if (n >= 0 && n < (int)_parameters.size()) { - return (_parameters[n]._parameter_flags & PF_is_optional) != 0; - } - return false; -} - -/** - * - */ -INLINE const std::string &InterrogateFunctionWrapper:: -get_unique_name() const { - return _unique_name; -} - -/** - * - */ -INLINE bool InterrogateFunctionWrapper:: -has_comment() const { - return !_comment.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateFunctionWrapper:: -get_comment() const { - return _comment; -} - -INLINE std::ostream & -operator << (std::ostream &out, const InterrogateFunctionWrapper &wrapper) { - wrapper.output(out); - return out; -} - -INLINE std::istream & -operator >> (std::istream &in, InterrogateFunctionWrapper &wrapper) { - wrapper.input(in); - return in; -} - -INLINE std::ostream & -operator << (std::ostream &out, const InterrogateFunctionWrapper::Parameter &p) { - p.output(out); - return out; -} - -INLINE std::istream & -operator >> (std::istream &in, InterrogateFunctionWrapper::Parameter &p) { - p.input(in); - return in; -} diff --git a/dtool/src/interrogatedb/interrogateFunctionWrapper.cxx b/dtool/src/interrogatedb/interrogateFunctionWrapper.cxx deleted file mode 100644 index 9cad10ef4e..0000000000 --- a/dtool/src/interrogatedb/interrogateFunctionWrapper.cxx +++ /dev/null @@ -1,84 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateFunctionWrapper.cxx - * @author drose - * @date 2000-08-06 - */ - -#include "interrogateFunctionWrapper.h" -#include "indexRemapper.h" -#include "interrogate_datafile.h" - -#include - -using std::istream; -using std::ostream; - -/** - * - */ -void InterrogateFunctionWrapper::Parameter:: -output(ostream &out) const { - idf_output_string(out, _name); - out << _parameter_flags << " " << _type << " "; -} - -/** - * - */ -void InterrogateFunctionWrapper::Parameter:: -input(istream &in) { - idf_input_string(in, _name); - in >> _parameter_flags >> _type; -} - -/** - * Formats the InterrogateFunctionWrapper data for output to a data file. - */ -void InterrogateFunctionWrapper:: -output(ostream &out) const { - InterrogateComponent::output(out); - out << _flags << " " - << _function << " " - << _return_type << " " - << _return_value_destructor << " "; - idf_output_string(out, _unique_name); - idf_output_string(out, _comment); - idf_output_vector(out, _parameters); -} - -/** - * Reads the data file as previously formatted by output(). - */ -void InterrogateFunctionWrapper:: -input(istream &in) { - InterrogateComponent::input(in); - in >> _flags - >> _function - >> _return_type - >> _return_value_destructor; - idf_input_string(in, _unique_name); - idf_input_string(in, _comment); - idf_input_vector(in, _parameters); -} - -/** - * Remaps all internal index numbers according to the indicated map. This - * called from InterrogateDatabase::remap_indices(). - */ -void InterrogateFunctionWrapper:: -remap_indices(const IndexRemapper &remap) { - _return_value_destructor = remap.map_from(_return_value_destructor); - _return_type = remap.map_from(_return_type); - - Parameters::iterator pi; - for (pi = _parameters.begin(); pi != _parameters.end(); ++pi) { - (*pi)._type = remap.map_from((*pi)._type); - } -} diff --git a/dtool/src/interrogatedb/interrogateFunctionWrapper.h b/dtool/src/interrogatedb/interrogateFunctionWrapper.h deleted file mode 100644 index 3fca6f3400..0000000000 --- a/dtool/src/interrogatedb/interrogateFunctionWrapper.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateFunctionWrapper.h - * @author drose - * @date 2000-08-06 - */ - -#ifndef INTERROGATEFUNCTIONWRAPPER_H -#define INTERROGATEFUNCTIONWRAPPER_H - -#include "dtoolbase.h" - -#include "interrogateComponent.h" - -#include - -class IndexRemapper; - -/** - * An internal representation of a callable function. - */ -class EXPCL_INTERROGATEDB InterrogateFunctionWrapper : public InterrogateComponent { -public: - INLINE InterrogateFunctionWrapper(InterrogateModuleDef *def = nullptr); - INLINE InterrogateFunctionWrapper(const InterrogateFunctionWrapper ©); - INLINE void operator = (const InterrogateFunctionWrapper ©); - - INLINE FunctionIndex get_function() const; - - INLINE bool is_callable_by_name() const; - INLINE bool is_copy_constructor() const; - INLINE bool is_coerce_constructor() const; - INLINE bool is_extension() const; - INLINE bool is_deprecated() const; - - INLINE bool has_return_value() const; - INLINE TypeIndex get_return_type() const; - INLINE bool caller_manages_return_value() const; - INLINE FunctionIndex get_return_value_destructor() const; - - INLINE int number_of_parameters() const; - INLINE TypeIndex parameter_get_type(int n) const; - INLINE bool parameter_has_name(int n) const; - INLINE const std::string ¶meter_get_name(int n) const; - INLINE bool parameter_is_this(int n) const; - INLINE bool parameter_is_optional(int n) const; - - INLINE const std::string &get_unique_name() const; - - INLINE bool has_comment() const; - INLINE const std::string &get_comment() const; - - void output(std::ostream &out) const; - void input(std::istream &in); - - void remap_indices(const IndexRemapper &remap); - -private: - enum Flags { - F_caller_manages = 0x0001, - F_has_return = 0x0002, - F_callable_by_name = 0x0004, - F_copy_constructor = 0x0008, - F_coerce_constructor = 0x0010, - F_extension = 0x0020, - F_deprecated = 0x0040, - }; - - enum ParameterFlags { - PF_has_name = 0x0001, - PF_is_this = 0x0002, - PF_is_optional = 0x0004, - }; - - int _flags; - FunctionIndex _function; - TypeIndex _return_type; - FunctionIndex _return_value_destructor; - std::string _unique_name; - std::string _comment; - -public: - // This nested class must be declared public just so we can declare the - // external ostream and istream IO operator functions, on the SGI compiler. - // Arguably a compiler bug, but what can you do. - class Parameter { - public: - void output(std::ostream &out) const; - void input(std::istream &in); - - int _parameter_flags; - TypeIndex _type; - std::string _name; - }; - -private: - typedef std::vector Parameters; - Parameters _parameters; - - friend class InterrogateBuilder; - friend class FunctionRemap; -}; - -INLINE std::ostream &operator << (std::ostream &out, const InterrogateFunctionWrapper &wrapper); -INLINE std::istream &operator >> (std::istream &in, InterrogateFunctionWrapper &wrapper); - -INLINE std::ostream &operator << (std::ostream &out, const InterrogateFunctionWrapper::Parameter &p); -INLINE std::istream &operator >> (std::istream &in, InterrogateFunctionWrapper::Parameter &p); - -#include "interrogateFunctionWrapper.I" - -#endif diff --git a/dtool/src/interrogatedb/interrogateMakeSeq.I b/dtool/src/interrogatedb/interrogateMakeSeq.I deleted file mode 100644 index 82e01761ea..0000000000 --- a/dtool/src/interrogatedb/interrogateMakeSeq.I +++ /dev/null @@ -1,103 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateMakeSeq.I - * @author drose - * @date 2009-09-15 - */ - -/** - * - */ -INLINE InterrogateMakeSeq:: -InterrogateMakeSeq(InterrogateModuleDef *def) : - InterrogateComponent(def) -{ - _length_getter = 0; - _element_getter = 0; -} - -/** - * - */ -INLINE InterrogateMakeSeq:: -InterrogateMakeSeq(const InterrogateMakeSeq ©) { - (*this) = copy; -} - -/** - * - */ -INLINE void InterrogateMakeSeq:: -operator = (const InterrogateMakeSeq ©) { - InterrogateComponent::operator = (copy); - _scoped_name = copy._scoped_name; - _comment = copy._comment; - _length_getter = copy._length_getter; - _element_getter = copy._element_getter; -} - -/** - * - */ -INLINE bool InterrogateMakeSeq:: -has_scoped_name() const { - return !_scoped_name.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateMakeSeq:: -get_scoped_name() const { - return _scoped_name; -} - -/** - * - */ -INLINE bool InterrogateMakeSeq:: -has_comment() const { - return !_comment.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateMakeSeq:: -get_comment() const { - return _comment; -} - -/** - * - */ -INLINE FunctionIndex InterrogateMakeSeq:: -get_length_getter() const { - return _length_getter; -} - -/** - * - */ -INLINE FunctionIndex InterrogateMakeSeq:: -get_element_getter() const { - return _element_getter; -} - -INLINE std::ostream & -operator << (std::ostream &out, const InterrogateMakeSeq &make_seq) { - make_seq.output(out); - return out; -} - -INLINE std::istream & -operator >> (std::istream &in, InterrogateMakeSeq &make_seq) { - make_seq.input(in); - return in; -} diff --git a/dtool/src/interrogatedb/interrogateMakeSeq.cxx b/dtool/src/interrogatedb/interrogateMakeSeq.cxx deleted file mode 100644 index d875a91809..0000000000 --- a/dtool/src/interrogatedb/interrogateMakeSeq.cxx +++ /dev/null @@ -1,50 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateMakeSeq.cxx - * @author drose - * @date 2009-09-15 - */ - -#include "interrogateMakeSeq.h" -#include "indexRemapper.h" -#include "interrogate_datafile.h" - -/** - * Formats the InterrogateMakeSeq data for output to a data file. - */ -void InterrogateMakeSeq:: -output(std::ostream &out) const { - InterrogateComponent::output(out); - out << _length_getter << " " - << _element_getter << " "; - idf_output_string(out, _scoped_name); - idf_output_string(out, _comment, '\n'); -} - -/** - * Reads the data file as previously formatted by output(). - */ -void InterrogateMakeSeq:: -input(std::istream &in) { - InterrogateComponent::input(in); - - in >> _length_getter >> _element_getter; - idf_input_string(in, _scoped_name); - idf_input_string(in, _comment); -} - -/** - * Remaps all internal index numbers according to the indicated map. This - * called from InterrogateDatabase::remap_indices(). - */ -void InterrogateMakeSeq:: -remap_indices(const IndexRemapper &remap) { - _length_getter = remap.map_from(_length_getter); - _element_getter = remap.map_from(_element_getter); -} diff --git a/dtool/src/interrogatedb/interrogateMakeSeq.h b/dtool/src/interrogatedb/interrogateMakeSeq.h deleted file mode 100644 index 5d6e1858b2..0000000000 --- a/dtool/src/interrogatedb/interrogateMakeSeq.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateMakeSeq.h - * @author drose - * @date 2009-09-15 - */ - -#ifndef INTERROGATEMAKESEQ_H -#define INTERROGATEMAKESEQ_H - -#include "dtoolbase.h" - -#include "interrogateComponent.h" - -class IndexRemapper; - -/** - * Represents a synthetic method created via the MAKE_SEQ() macro. - */ -class EXPCL_INTERROGATEDB InterrogateMakeSeq : public InterrogateComponent { -public: - INLINE InterrogateMakeSeq(InterrogateModuleDef *def = nullptr); - INLINE InterrogateMakeSeq(const InterrogateMakeSeq ©); - INLINE void operator = (const InterrogateMakeSeq ©); - - INLINE bool has_scoped_name() const; - INLINE const std::string &get_scoped_name() const; - - INLINE bool has_comment() const; - INLINE const std::string &get_comment() const; - - INLINE FunctionIndex get_length_getter() const; - INLINE FunctionIndex get_element_getter() const; - - void output(std::ostream &out) const; - void input(std::istream &in); - - void remap_indices(const IndexRemapper &remap); - -private: - std::string _scoped_name; - std::string _comment; - FunctionIndex _length_getter; - FunctionIndex _element_getter; - - friend class InterrogateBuilder; -}; - -INLINE std::ostream &operator << (std::ostream &out, const InterrogateMakeSeq &make_seq); -INLINE std::istream &operator >> (std::istream &in, InterrogateMakeSeq &make_seq); - -#include "interrogateMakeSeq.I" - -#endif diff --git a/dtool/src/interrogatedb/interrogateManifest.I b/dtool/src/interrogatedb/interrogateManifest.I deleted file mode 100644 index 2aedf8a682..0000000000 --- a/dtool/src/interrogatedb/interrogateManifest.I +++ /dev/null @@ -1,116 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateManifest.I - * @author drose - * @date 2000-08-11 - */ - -/** - * - */ -INLINE InterrogateManifest:: -InterrogateManifest(InterrogateModuleDef *def) : - InterrogateComponent(def) -{ - _flags = 0; - _int_value = 0; - _type = 0; - _getter = 0; -} - -/** - * - */ -INLINE InterrogateManifest:: -InterrogateManifest(const InterrogateManifest ©) { - (*this) = copy; -} - -/** - * - */ -INLINE void InterrogateManifest:: -operator = (const InterrogateManifest ©) { - InterrogateComponent::operator = (copy); - _flags = copy._flags; - _definition = copy._definition; - _int_value = copy._int_value; - _type = copy._type; - _getter = copy._getter; -} - - -/** - * - */ -INLINE const std::string &InterrogateManifest:: -get_definition() const { - return _definition; -} - -/** - * - */ -INLINE bool InterrogateManifest:: -has_type() const { - return (_flags & F_has_type) != 0; -} - -/** - * - */ -INLINE TypeIndex InterrogateManifest:: -get_type() const { - return _type; -} - -/** - * - */ -INLINE bool InterrogateManifest:: -has_getter() const { - return (_flags & F_has_getter) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateManifest:: -get_getter() const { - return _getter; -} - -/** - * - */ -INLINE bool InterrogateManifest:: -has_int_value() const { - return (_flags & F_has_int_value) != 0; -} - -/** - * - */ -INLINE int InterrogateManifest:: -get_int_value() const { - return _int_value; -} - - -INLINE std::ostream & -operator << (std::ostream &out, const InterrogateManifest &manifest) { - manifest.output(out); - return out; -} - -INLINE std::istream & -operator >> (std::istream &in, InterrogateManifest &manifest) { - manifest.input(in); - return in; -} diff --git a/dtool/src/interrogatedb/interrogateManifest.cxx b/dtool/src/interrogatedb/interrogateManifest.cxx deleted file mode 100644 index a078e868f4..0000000000 --- a/dtool/src/interrogatedb/interrogateManifest.cxx +++ /dev/null @@ -1,49 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateManifest.cxx - * @author drose - * @date 2000-08-11 - */ - -#include "interrogateManifest.h" -#include "indexRemapper.h" -#include "interrogate_datafile.h" - -/** - * Formats the InterrogateManifest data for output to a data file. - */ -void InterrogateManifest:: -output(std::ostream &out) const { - InterrogateComponent::output(out); - out << _flags << " " - << _int_value << " " - << _type << " " - << _getter << " "; - idf_output_string(out, _definition); -} - -/** - * Reads the data file as previously formatted by output(). - */ -void InterrogateManifest:: -input(std::istream &in) { - InterrogateComponent::input(in); - in >> _flags >> _int_value >> _type >> _getter; - idf_input_string(in, _definition); -} - -/** - * Remaps all internal index numbers according to the indicated map. This - * called from InterrogateDatabase::remap_indices(). - */ -void InterrogateManifest:: -remap_indices(const IndexRemapper &remap) { - _type = remap.map_from(_type); - _getter = remap.map_from(_getter); -} diff --git a/dtool/src/interrogatedb/interrogateManifest.h b/dtool/src/interrogatedb/interrogateManifest.h deleted file mode 100644 index a038cc0ce1..0000000000 --- a/dtool/src/interrogatedb/interrogateManifest.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateManifest.h - * @author drose - * @date 2000-08-11 - */ - -#ifndef INTERROGATEMANIFEST_H -#define INTERROGATEMANIFEST_H - -#include "dtoolbase.h" - -#include "interrogateComponent.h" - -class IndexRemapper; - -/** - * An internal representation of a manifest constant. - */ -class EXPCL_INTERROGATEDB InterrogateManifest : public InterrogateComponent { -public: - INLINE InterrogateManifest(InterrogateModuleDef *def = nullptr); - INLINE InterrogateManifest(const InterrogateManifest ©); - INLINE void operator = (const InterrogateManifest ©); - - INLINE const std::string &get_definition() const; - INLINE bool has_type() const; - INLINE TypeIndex get_type() const; - INLINE bool has_getter() const; - INLINE FunctionIndex get_getter() const; - INLINE bool has_int_value() const; - INLINE int get_int_value() const; - - void output(std::ostream &out) const; - void input(std::istream &in); - - void remap_indices(const IndexRemapper &remap); - -private: - enum Flags { - F_has_type = 0x0001, - F_has_getter = 0x0002, - F_has_int_value = 0x0004 - }; - - int _flags; - std::string _definition; - int _int_value; - TypeIndex _type; - FunctionIndex _getter; - - friend class InterrogateBuilder; -}; - -INLINE std::ostream &operator << (std::ostream &out, const InterrogateManifest &manifest); -INLINE std::istream &operator >> (std::istream &in, InterrogateManifest &manifest); - -#include "interrogateManifest.I" - -#endif diff --git a/dtool/src/interrogatedb/interrogateType.I b/dtool/src/interrogatedb/interrogateType.I deleted file mode 100644 index 64c164e83e..0000000000 --- a/dtool/src/interrogatedb/interrogateType.I +++ /dev/null @@ -1,594 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateType.I - * @author drose - * @date 2000-07-31 - */ - -/** - * Returns true if the type is marked as 'global'. This means only that it - * should appear in the global type list. - */ -INLINE bool InterrogateType:: -is_global() const { - return (_flags & F_global) != 0; -} - -/** - * Returns true if the type is marked as 'deprecated'. - * - * @since 1.11.0 - */ -INLINE bool InterrogateType:: -is_deprecated() const { - return (_flags & F_deprecated) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -has_scoped_name() const { - return !_scoped_name.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateType:: -get_scoped_name() const { - return _scoped_name; -} - -/** - * - */ -INLINE bool InterrogateType:: -has_true_name() const { - return !_true_name.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateType:: -get_true_name() const { - return _true_name; -} - -/** - * - */ -INLINE bool InterrogateType:: -has_comment() const { - return !_comment.empty(); -} - -/** - * - */ -INLINE const std::string &InterrogateType:: -get_comment() const { - return _comment; -} - -/** - * Returns true if this type is nested within some class definition. - */ -INLINE bool InterrogateType:: -is_nested() const { - return (_flags & F_nested) != 0; -} - -/** - * If is_nested() returns true, this is the class within which this type is - * defined. - */ -INLINE TypeIndex InterrogateType:: -get_outer_class() const { - return _outer_class; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_atomic() const { - return (_flags & F_atomic) != 0; -} - -/** - * - */ -INLINE AtomicToken InterrogateType:: -get_atomic_token() const { - return _atomic_token; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_unsigned() const { - return (_flags & F_unsigned) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_signed() const { - return (_flags & F_signed) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_long() const { - return (_flags & F_long) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_longlong() const { - return (_flags & F_longlong) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_short() const { - return (_flags & F_short) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_wrapped() const { - return (_flags & F_wrapped) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_pointer() const { - return (_flags & F_pointer) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_const() const { - return (_flags & F_const) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_typedef() const { - return (_flags & F_typedef) != 0; -} - -/** - * - */ -INLINE TypeIndex InterrogateType:: -get_wrapped_type() const { - return _wrapped_type; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_array() const { - return (_flags & F_array) != 0; -} - -/** - * - */ -INLINE int InterrogateType:: -get_array_size() const { - return _array_size; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_enum() const { - return (_flags & F_enum) != 0; -} - -/** - * Returns true if enum values are only available under a scope. - */ -INLINE bool InterrogateType:: -is_scoped_enum() const { - return (_flags & F_scoped_enum) != 0; -} - -/** - * - */ -INLINE int InterrogateType:: -number_of_enum_values() const { - return _enum_values.size(); -} - -/** - * - */ -INLINE const std::string &InterrogateType:: -get_enum_value_name(int n) const { - if (n >= 0 && n < (int)_enum_values.size()) { - return _enum_values[n]._name; - } - return _empty_string; -} - -/** - * - */ -INLINE const std::string &InterrogateType:: -get_enum_value_scoped_name(int n) const { - if (n >= 0 && n < (int)_enum_values.size()) { - return _enum_values[n]._scoped_name; - } - return _empty_string; -} - -/** - * - */ -INLINE const std::string &InterrogateType:: -get_enum_value_comment(int n) const { - if (n >= 0 && n < (int)_enum_values.size()) { - return _enum_values[n]._comment; - } - return _empty_string; -} - -/** - * - */ -INLINE int InterrogateType:: -get_enum_value(int n) const { - if (n >= 0 && n < (int)_enum_values.size()) { - return _enum_values[n]._value; - } - return 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_struct() const { - return (_flags & F_struct) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_class() const { - return (_flags & F_class) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_union() const { - return (_flags & F_union) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_final() const { - return (_flags & F_final) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -is_fully_defined() const { - return (_flags & F_fully_defined) != 0; -} - -/** - * Returns true if the type is an unpublished type. This either means the - * type is a nested type, and it is protected or private within its scope, or - * that its definition is simply not marked as 'published'. - */ -INLINE bool InterrogateType:: -is_unpublished() const { - return (_flags & F_unpublished) != 0; -} - -/** - * - */ -INLINE int InterrogateType:: -number_of_constructors() const { - return _constructors.size(); -} - -/** - * - */ -INLINE FunctionIndex InterrogateType:: -get_constructor(int n) const { - if (n >= 0 && n < (int)_constructors.size()) { - return _constructors[n]; - } else { - return 0; - } -} - -/** - * - */ -INLINE bool InterrogateType:: -has_destructor() const { - return (_destructor != 0); -} - -/** - * - */ -INLINE bool InterrogateType:: -destructor_is_inherited() const { - return (_flags & F_inherited_destructor) != 0; -} - -/** - * - */ -INLINE bool InterrogateType:: -destructor_is_implicit() const { - return (_flags & F_implicit_destructor) != 0; -} - -/** - * - */ -INLINE FunctionIndex InterrogateType:: -get_destructor() const { - return _destructor; -} - -/** - * - */ -INLINE int InterrogateType:: -number_of_elements() const { - return _elements.size(); -} - -/** - * - */ -INLINE ElementIndex InterrogateType:: -get_element(int n) const { - if (n >= 0 && n < (int)_elements.size()) { - return _elements[n]; - } else { - return 0; - } -} - -/** - * - */ -INLINE int InterrogateType:: -number_of_methods() const { - return _methods.size(); -} - -/** - * - */ -INLINE FunctionIndex InterrogateType:: -get_method(int n) const { - if (n >= 0 && n < (int)_methods.size()) { - return _methods[n]; - } else { - return 0; - } -} - -/** - * - */ -INLINE int InterrogateType:: -number_of_make_seqs() const { - return _make_seqs.size(); -} - -/** - * - */ -INLINE MakeSeqIndex InterrogateType:: -get_make_seq(int n) const { - if (n >= 0 && n < (int)_make_seqs.size()) { - return _make_seqs[n]; - } else { - return 0; - } -} - -/** - * - */ -INLINE int InterrogateType:: -number_of_casts() const { - return _casts.size(); -} - -/** - * - */ -INLINE FunctionIndex InterrogateType:: -get_cast(int n) const { - if (n >= 0 && n < (int)_casts.size()) { - return _casts[n]; - } else { - return 0; - } -} - -/** - * - */ -INLINE int InterrogateType:: -number_of_derivations() const { - return _derivations.size(); -} - -/** - * - */ -INLINE TypeIndex InterrogateType:: -get_derivation(int n) const { - if (n >= 0 && n < (int)_derivations.size()) { - return _derivations[n]._base; - } else { - return 0; - } -} - -/** - * - */ -INLINE bool InterrogateType:: -derivation_has_upcast(int n) const { - if (n >= 0 && n < (int)_derivations.size()) { - return (_derivations[n]._flags & DF_upcast) != 0; - } else { - return false; - } -} - -/** - * - */ -INLINE TypeIndex InterrogateType:: -derivation_get_upcast(int n) const { - if (n >= 0 && n < (int)_derivations.size()) { - return _derivations[n]._upcast; - } else { - return 0; - } -} - -/** - * - */ -INLINE bool InterrogateType:: -derivation_downcast_is_impossible(int n) const { - if (n >= 0 && n < (int)_derivations.size()) { - return (_derivations[n]._flags & DF_downcast_impossible) != 0; - } else { - return false; - } -} - -/** - * - */ -INLINE bool InterrogateType:: -derivation_has_downcast(int n) const { - if (n >= 0 && n < (int)_derivations.size()) { - return (_derivations[n]._flags & DF_downcast) != 0; - } else { - return false; - } -} - -/** - * - */ -INLINE TypeIndex InterrogateType:: -derivation_get_downcast(int n) const { - if (n >= 0 && n < (int)_derivations.size()) { - return _derivations[n]._downcast; - } else { - return 0; - } -} - -/** - * - */ -INLINE int InterrogateType:: -number_of_nested_types() const { - return _nested_types.size(); -} - -/** - * - */ -INLINE TypeIndex InterrogateType:: -get_nested_type(int n) const { - if (n >= 0 && n < (int)_nested_types.size()) { - return _nested_types[n]; - } else { - return 0; - } -} - -INLINE std::ostream & -operator << (std::ostream &out, const InterrogateType &type) { - type.output(out); - return out; -} - -INLINE std::istream & -operator >> (std::istream &in, InterrogateType &type) { - type.input(in); - return in; -} - -INLINE std::ostream & -operator << (std::ostream &out, const InterrogateType::Derivation &d) { - d.output(out); - return out; -} - -INLINE std::istream & -operator >> (std::istream &in, InterrogateType::Derivation &d) { - d.input(in); - return in; -} - -INLINE std::ostream & -operator << (std::ostream &out, const InterrogateType::EnumValue &ev) { - ev.output(out); - return out; -} - -INLINE std::istream & -operator >> (std::istream &in, InterrogateType::EnumValue &ev) { - ev.input(in); - return in; -} diff --git a/dtool/src/interrogatedb/interrogateType.cxx b/dtool/src/interrogatedb/interrogateType.cxx deleted file mode 100644 index a9b9404cd4..0000000000 --- a/dtool/src/interrogatedb/interrogateType.cxx +++ /dev/null @@ -1,247 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateType.cxx - * @author drose - * @date 2000-07-31 - */ - -#include "interrogateType.h" -#include "indexRemapper.h" -#include "interrogate_datafile.h" -#include "interrogateDatabase.h" - -#include - -using std::istream; -using std::ostream; - -/** - * - */ -InterrogateType:: -InterrogateType(InterrogateModuleDef *def) : - InterrogateComponent(def) -{ - _flags = 0; - _outer_class = 0; - _atomic_token = AT_not_atomic; - _wrapped_type = 0; - _array_size = 1; - _destructor = 0; - - _cpptype = nullptr; - _cppscope = nullptr; -} - -/** - * - */ -InterrogateType:: -InterrogateType(const InterrogateType ©) { - (*this) = copy; -} - -/** - * - */ -void InterrogateType::Derivation:: -output(ostream &out) const { - out << _flags << " " << _base << " " << _upcast << " " << _downcast; -} - -/** - * - */ -void InterrogateType::Derivation:: -input(istream &in) { - in >> _flags >> _base >> _upcast >> _downcast; -} - -/** - * - */ -void InterrogateType::EnumValue:: -output(ostream &out) const { - idf_output_string(out, _name); - idf_output_string(out, _scoped_name); - idf_output_string(out, _comment, '\n'); - out << _value; -} - -/** - * - */ -void InterrogateType::EnumValue:: -input(istream &in) { - idf_input_string(in, _name); - idf_input_string(in, _scoped_name); - idf_input_string(in, _comment); - in >> _value; -} - -/** - * - */ -void InterrogateType:: -operator = (const InterrogateType ©) { - InterrogateComponent::operator = (copy); - _flags = copy._flags; - _scoped_name = copy._scoped_name; - _true_name = copy._true_name; - _comment = copy._comment; - _outer_class = copy._outer_class; - _atomic_token = copy._atomic_token; - _wrapped_type = copy._wrapped_type; - _array_size = copy._array_size; - _constructors = copy._constructors; - _destructor = copy._destructor; - _elements = copy._elements; - _methods = copy._methods; - _make_seqs = copy._make_seqs; - _casts = copy._casts; - _derivations = copy._derivations; - _enum_values = copy._enum_values; - _nested_types = copy._nested_types; - - _cpptype = copy._cpptype; - _cppscope = copy._cppscope; -} - -/** - * Combines type with the other similar definition. If one type is "fully - * defined" and the other one isn't, the fully-defined type wins. If both - * types are fully defined, whichever type is marked "global" wins. - */ -void InterrogateType:: -merge_with(const InterrogateType &other) { - // The only thing we care about copying from the non-fully-defined type - // right now is the global flag. - - if (is_fully_defined() && - (!other.is_fully_defined() || (other._flags & F_global) == 0)) { - // We win. - _flags |= (other._flags & F_global); - - } else { - // They win. - int old_flags = (_flags & F_global); - (*this) = other; - _flags |= old_flags; - } -} - -/** - * Formats the InterrogateType data for output to a data file. - */ -void InterrogateType:: -output(ostream &out) const { - InterrogateComponent::output(out); - - out << _flags << " "; - idf_output_string(out, _scoped_name); - idf_output_string(out, _true_name); - out << _outer_class << " " - << (int)_atomic_token << " " - << _wrapped_type << " "; - - if (is_array()) { - out << _array_size << " "; - } - - idf_output_vector(out, _constructors); - out << _destructor << " "; - idf_output_vector(out, _elements); - idf_output_vector(out, _methods); - idf_output_vector(out, _make_seqs); - idf_output_vector(out, _casts); - idf_output_vector(out, _derivations); - idf_output_vector(out, _enum_values); - idf_output_vector(out, _nested_types); - idf_output_string(out, _comment, '\n'); -} - -/** - * Reads the data file as previously formatted by output(). - */ -void InterrogateType:: -input(istream &in) { - InterrogateComponent::input(in); - - in >> _flags; - idf_input_string(in, _scoped_name); - idf_input_string(in, _true_name); - - in >> _outer_class; - int token; - in >> token; - _atomic_token = (AtomicToken)token; - in >> _wrapped_type; - - if (is_array()) { - in >> _array_size; - } - - idf_input_vector(in, _constructors); - in >> _destructor; - - idf_input_vector(in, _elements); - idf_input_vector(in, _methods); - idf_input_vector(in, _make_seqs); - idf_input_vector(in, _casts); - idf_input_vector(in, _derivations); - idf_input_vector(in, _enum_values); - idf_input_vector(in, _nested_types); - idf_input_string(in, _comment); -} - -/** - * Remaps all internal index numbers according to the indicated map. This - * called from InterrogateDatabase::remap_indices(). - */ -void InterrogateType:: -remap_indices(const IndexRemapper &remap) { - _outer_class = remap.map_from(_outer_class); - _wrapped_type = remap.map_from(_wrapped_type); - - Functions::iterator fi; - for (fi = _constructors.begin(); fi != _constructors.end(); ++fi) { - (*fi) = remap.map_from(*fi); - } - _destructor = remap.map_from(_destructor); - - Elements::iterator ei; - for (ei = _elements.begin(); ei != _elements.end(); ++ei) { - (*ei) = remap.map_from(*ei); - } - - for (fi = _methods.begin(); fi != _methods.end(); ++fi) { - (*fi) = remap.map_from(*fi); - } - for (fi = _casts.begin(); fi != _casts.end(); ++fi) { - (*fi) = remap.map_from(*fi); - } - - MakeSeqs::iterator si; - for (si = _make_seqs.begin(); si != _make_seqs.end(); ++si) { - (*si) = remap.map_from(*si); - } - - Derivations::iterator di; - for (di = _derivations.begin(); di != _derivations.end(); ++di) { - (*di)._base = remap.map_from((*di)._base); - (*di)._upcast = remap.map_from((*di)._upcast); - (*di)._downcast = remap.map_from((*di)._downcast); - } - - Types::iterator ti; - for (ti = _nested_types.begin(); ti != _nested_types.end(); ++ti) { - (*ti) = remap.map_from(*ti); - } - -} diff --git a/dtool/src/interrogatedb/interrogateType.h b/dtool/src/interrogatedb/interrogateType.h deleted file mode 100644 index c9f67aff26..0000000000 --- a/dtool/src/interrogatedb/interrogateType.h +++ /dev/null @@ -1,239 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateType.h - * @author drose - * @date 2000-07-31 - */ - -#ifndef INTERROGATETYPE_H -#define INTERROGATETYPE_H - -#include "dtoolbase.h" - -#include "interrogateComponent.h" - -#include - -class IndexRemapper; -class CPPType; -class CPPScope; - -/** - * An internal representation of a type. - */ -class EXPCL_INTERROGATEDB InterrogateType : public InterrogateComponent { -public: - InterrogateType(InterrogateModuleDef *def = nullptr); - InterrogateType(const InterrogateType ©); - void operator = (const InterrogateType ©); - - INLINE bool is_global() const; - INLINE bool is_deprecated() const; - - INLINE bool has_scoped_name() const; - INLINE const std::string &get_scoped_name() const; - - INLINE bool has_true_name() const; - INLINE const std::string &get_true_name() const; - - INLINE bool has_comment() const; - INLINE const std::string &get_comment() const; - - INLINE bool is_nested() const; - INLINE TypeIndex get_outer_class() const; - - INLINE bool is_atomic() const; - INLINE AtomicToken get_atomic_token() const; - INLINE bool is_unsigned() const; - INLINE bool is_signed() const; - INLINE bool is_long() const; - INLINE bool is_longlong() const; - INLINE bool is_short() const; - - INLINE bool is_wrapped() const; - INLINE bool is_pointer() const; - INLINE bool is_const() const; - INLINE bool is_typedef() const; - INLINE TypeIndex get_wrapped_type() const; - - INLINE bool is_array() const; - INLINE int get_array_size() const; - - INLINE bool is_enum() const; - INLINE bool is_scoped_enum() const; - INLINE int number_of_enum_values() const; - INLINE const std::string &get_enum_value_name(int n) const; - INLINE const std::string &get_enum_value_scoped_name(int n) const; - INLINE const std::string &get_enum_value_comment(int n) const; - INLINE int get_enum_value(int n) const; - - INLINE bool is_struct() const; - INLINE bool is_class() const; - INLINE bool is_union() const; - INLINE bool is_final() const; - - INLINE bool is_fully_defined() const; - INLINE bool is_unpublished() const; - INLINE int number_of_constructors() const; - INLINE FunctionIndex get_constructor(int n) const; - INLINE bool has_destructor() const; - INLINE bool destructor_is_inherited() const; - INLINE bool destructor_is_implicit() const; - INLINE FunctionIndex get_destructor() const; - INLINE int number_of_elements() const; - INLINE ElementIndex get_element(int n) const; - INLINE int number_of_methods() const; - INLINE FunctionIndex get_method(int n) const; - INLINE int number_of_make_seqs() const; - INLINE MakeSeqIndex get_make_seq(int n) const; - - INLINE int number_of_casts() const; - INLINE FunctionIndex get_cast(int n) const; - - INLINE int number_of_derivations() const; - INLINE TypeIndex get_derivation(int n) const; - - INLINE bool derivation_has_upcast(int n) const; - INLINE FunctionIndex derivation_get_upcast(int n) const; - - INLINE bool derivation_downcast_is_impossible(int n) const; - INLINE bool derivation_has_downcast(int n) const; - INLINE FunctionIndex derivation_get_downcast(int n) const; - - INLINE int number_of_nested_types() const; - INLINE TypeIndex get_nested_type(int n) const; - - void merge_with(const InterrogateType &other); - void output(std::ostream &out) const; - void input(std::istream &in); - - void remap_indices(const IndexRemapper &remap); - -private: - enum Flags { - F_global = 0x000001, - F_atomic = 0x000002, - F_unsigned = 0x000004, - F_signed = 0x000008, - F_long = 0x000010, - F_longlong = 0x000020, - F_short = 0x000040, - F_wrapped = 0x000080, - F_pointer = 0x000100, - F_const = 0x000200, - F_struct = 0x000400, - F_class = 0x000800, - F_union = 0x001000, - F_fully_defined = 0x002000, - F_true_destructor = 0x004000, - F_private_destructor = 0x008000, - F_inherited_destructor = 0x010000, - F_implicit_destructor = 0x020000, - F_nested = 0x040000, - F_enum = 0x080000, - F_unpublished = 0x100000, - F_typedef = 0x200000, - F_array = 0x400000, - F_scoped_enum = 0x800000, - F_final =0x1000000, - F_deprecated =0x2000000, - }; - -public: - int _flags; - - std::string _scoped_name; - std::string _true_name; - std::string _comment; - TypeIndex _outer_class; - AtomicToken _atomic_token; - TypeIndex _wrapped_type; - int _array_size; - - typedef std::vector Functions; - Functions _constructors; - FunctionIndex _destructor; - - typedef std::vector Elements; - Elements _elements; - Functions _methods; - Functions _casts; - - typedef std::vector MakeSeqs; - MakeSeqs _make_seqs; - - enum DerivationFlags { - DF_upcast = 0x01, - DF_downcast = 0x02, - DF_downcast_impossible = 0x04 - }; - -public: - // This nested class must be declared public just so we can declare the - // external ostream and istream IO operator functions, on the SGI compiler. - // Arguably a compiler bug, but what can you do. - class Derivation { - public: - void output(std::ostream &out) const; - void input(std::istream &in); - - int _flags; - TypeIndex _base; - FunctionIndex _upcast; - FunctionIndex _downcast; - }; - -private: - typedef std::vector Derivations; - Derivations _derivations; - -public: - // This nested class must also be public, for the same reason. - class EnumValue { - public: - void output(std::ostream &out) const; - void input(std::istream &in); - - std::string _name; - std::string _scoped_name; - std::string _comment; - int _value; - }; - -private: - typedef std::vector EnumValues; - EnumValues _enum_values; - - typedef std::vector Types; - Types _nested_types; - -public: - // The rest of the members in this class aren't part of the public interface - // to interrogate, but are used internally as the interrogate database is - // built. They are valid only during the session of interrogate that - // generates the database, and will not be filled in when the database is - // reloaded from disk. - CPPType *_cpptype; - CPPScope *_cppscope; - - friend class InterrogateBuilder; -}; - -INLINE std::ostream &operator << (std::ostream &out, const InterrogateType &type); -INLINE std::istream &operator >> (std::istream &in, InterrogateType &type); - -INLINE std::ostream &operator << (std::ostream &out, const InterrogateType::Derivation &d); -INLINE std::istream &operator >> (std::istream &in, InterrogateType::Derivation &d); - -INLINE std::ostream &operator << (std::ostream &out, const InterrogateType::EnumValue &d); -INLINE std::istream &operator >> (std::istream &in, InterrogateType::EnumValue &d); - -#include "interrogateType.I" - -#endif diff --git a/dtool/src/interrogatedb/interrogate_datafile.I b/dtool/src/interrogatedb/interrogate_datafile.I deleted file mode 100644 index cb020861e2..0000000000 --- a/dtool/src/interrogatedb/interrogate_datafile.I +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogate_datafile.I - * @author drose - * @date 2000-08-09 - */ - -/** - * Writes the indicated vector to the output file. Each component is written - * using its normal ostream output operator. - */ -template -void -idf_output_vector(std::ostream &out, const std::vector &vec) { - out << vec.size() << " "; - typename std::vector::const_iterator vi; - for (vi = vec.begin(); vi != vec.end(); ++vi) { - out << (*vi) << " "; - } -} - - -/** - * Reads the given vector from the input file, as previously written by - * output_string(). Each component is read using its normal istream input - * operator. - */ -template -void -idf_input_vector(std::istream &in, std::vector &vec) { - int length; - in >> length; - if (in.fail()) { - return; - } - - vec.clear(); - vec.reserve(length); - while (length > 0) { - Element elem; - in >> elem; - vec.push_back(elem); - length--; - } -} diff --git a/dtool/src/interrogatedb/interrogate_datafile.cxx b/dtool/src/interrogatedb/interrogate_datafile.cxx deleted file mode 100644 index a61defb368..0000000000 --- a/dtool/src/interrogatedb/interrogate_datafile.cxx +++ /dev/null @@ -1,98 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogate_datafile.cxx - * @author drose - * @date 2000-08-09 - */ - -#include "interrogate_datafile.h" - -using std::istream; -using std::ostream; -using std::string; - - -/** - * Writes the indicated string to the output file. Uses the given whitespace - * character to separate the string's length and its contents. - */ -void -idf_output_string(ostream &out, const string &str, char whitespace) { - out << str.length() << whitespace; - if (!str.empty()) { - out << str << whitespace; - } -} - -/** - * Reads the given string from the input file, as previously written by - * output_string(). - */ -void -idf_input_string(istream &in, string &str) { - int length; - in >> length; - if (in.fail()) { - return; - } - - // Skip one character of whitespace, and then read the string. - in.get(); - str = ""; - while (length > 0) { - str += in.get(); - length--; - } -} - -/** - * Writes the indicated string to the output file. Uses the given whitespace - * character to separate the string's length and its contents. - */ -void -idf_output_string(ostream &out, const char *str, char whitespace) { - if (str == nullptr) { - out << "0 "; - } else { - out << strlen(str) << whitespace; - if (str[0] != '\0') { - out << str << whitespace; - } - } -} - -/** - * Reads the given string from the input file, as previously written by - * output_string(). - */ -void -idf_input_string(istream &in, const char *&str) { - int length; - in >> length; - if (in.fail()) { - return; - } - - if (length == 0) { - // Don't change the string if the input length is zero. - return; - } - - // Skip one character of whitespace, and then read the string. - in.get(); - char *readstr = new char[length + 1]; - int p = 0; - while (p < length) { - readstr[p] = in.get(); - p++; - } - readstr[p] = '\0'; - - str = readstr; -} diff --git a/dtool/src/interrogatedb/interrogate_datafile.h b/dtool/src/interrogatedb/interrogate_datafile.h deleted file mode 100644 index 8432123fdf..0000000000 --- a/dtool/src/interrogatedb/interrogate_datafile.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogate_datafile.h - * @author drose - * @date 2000-08-09 - */ - -#ifndef INTERROGATE_DATAFILE_H -#define INTERROGATE_DATAFILE_H - -// This file defines some convenience functions for reading and writing the -// interrogate database files. - -#include "dtoolbase.h" -#include - -void idf_output_string(std::ostream &out, const std::string &str, char whitespace = ' '); -void idf_input_string(std::istream &in, std::string &str); - -void idf_output_string(std::ostream &out, const char *str, char whitespace = ' '); -void idf_input_string(std::istream &in, const char *&str); - -template -void idf_output_vector(std::ostream &out, const std::vector &vec); - -template -void idf_input_vector(std::istream &in, std::vector &vec); - -#include "interrogate_datafile.I" - -#endif diff --git a/dtool/src/interrogatedb/interrogate_interface.cxx b/dtool/src/interrogatedb/interrogate_interface.cxx deleted file mode 100644 index a0b4ff356a..0000000000 --- a/dtool/src/interrogatedb/interrogate_interface.cxx +++ /dev/null @@ -1,1043 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogate_interface.cxx - * @author drose - * @date 2000-07-31 - */ - -#include "interrogate_interface.h" -#include "interrogateDatabase.h" -#include "interrogateType.h" -#include "interrogateFunction.h" -#include "config_interrogatedb.h" - -using std::string; - -// This function adds one more directory to the list of directories search for -// interrogate (*.in) files. In the past, this list has been defined the -// environment variable ETC_PATH, but now it is passed in by the code -// generator. -void -interrogate_add_search_directory(const char *dirname) { - // cerr << "interrogate_add_search_directory(" << dirname << ")\n"; - interrogatedb_path.append_directory(Filename::from_os_specific(dirname)); -} - -// This function works similar to the above, but adds a complete path string-- -// a list of multiple directories, separated by the standard delimiter--to the -// search path. -void -interrogate_add_search_path(const char *pathstring) { - // cerr << "interrogate_add_search_path(" << pathstring << ")\n"; - interrogatedb_path.append_path(pathstring); -} - -bool interrogate_error_flag() { - // cerr << "interrogate_error_flag\n"; - return InterrogateDatabase::get_ptr()->get_error_flag(); -} - -int -interrogate_number_of_manifests() { - // cerr << "interrogate_number_of_manifests\n"; - return InterrogateDatabase::get_ptr()->get_num_global_manifests(); -} - -ManifestIndex -interrogate_get_manifest(int n) { - // cerr << "interrogate_get_manifest(" << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_global_manifest(n); -} - -ManifestIndex -interrogate_get_manifest_by_name(const char *manifest_name) { - // cerr << "interrogate_get_manifest_by_name(" << manifest_name << ")\n"; - return InterrogateDatabase::get_ptr()->lookup_manifest_by_name(manifest_name); -} - -const char * -interrogate_manifest_name(ManifestIndex manifest) { - // cerr << "interrogate_manifest_name(" << manifest << ")\n"; - return InterrogateDatabase::get_ptr()->get_manifest(manifest).get_name().c_str(); -} - -const char * -interrogate_manifest_definition(ManifestIndex manifest) { - // cerr << "interrogate_manifest_definition(" << manifest << ")\n"; - return InterrogateDatabase::get_ptr()->get_manifest(manifest).get_definition().c_str(); -} - -bool -interrogate_manifest_has_type(ManifestIndex manifest) { - // cerr << "interrogate_manifest_has_type(" << manifest << ")\n"; - return InterrogateDatabase::get_ptr()->get_manifest(manifest).has_type(); -} - -TypeIndex -interrogate_manifest_get_type(ManifestIndex manifest) { - // cerr << "interrogate_manifest_get_type(" << manifest << ")\n"; - return InterrogateDatabase::get_ptr()->get_manifest(manifest).get_type(); -} - -bool -interrogate_manifest_has_getter(ManifestIndex manifest) { - // cerr << "interrogate_manifest_has_getter(" << manifest << ")\n"; - return InterrogateDatabase::get_ptr()->get_manifest(manifest).has_getter(); -} - -FunctionIndex -interrogate_manifest_getter(ManifestIndex manifest) { - // cerr << "interrogate_manifest_getter(" << manifest << ")\n"; - return InterrogateDatabase::get_ptr()->get_manifest(manifest).get_getter(); -} - -bool -interrogate_manifest_has_int_value(ManifestIndex manifest) { - // cerr << "interrogate_manifest_has_int_value(" << manifest << ")\n"; - return InterrogateDatabase::get_ptr()->get_manifest(manifest).has_int_value(); -} - -int -interrogate_manifest_get_int_value(ManifestIndex manifest) { - // cerr << "interrogate_manifest_get_int_value(" << manifest << ")\n"; - return InterrogateDatabase::get_ptr()->get_manifest(manifest).get_int_value(); -} - -const char * -interrogate_element_name(ElementIndex element) { - // cerr << "interrogate_element_name(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_name().c_str(); -} - -const char * -interrogate_element_scoped_name(ElementIndex element) { - // cerr << "interrogate_element_scoped_name(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_scoped_name().c_str(); -} - -bool -interrogate_element_has_comment(ElementIndex element) { - // cerr << "interrogate_element_has_comment(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).has_comment(); -} - -const char * -interrogate_element_comment(ElementIndex element) { - // cerr << "interrogate_element_comment(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_comment().c_str(); -} - -ElementIndex -interrogate_get_element_by_name(const char *element_name) { - // cerr << "interrogate_get_element_by_name(" << element_name << ")\n"; - return InterrogateDatabase::get_ptr()->lookup_element_by_name(element_name); -} - -ElementIndex -interrogate_get_element_by_scoped_name(const char *element_name) { - // cerr << "interrogate_get_element_by_scoped_name(" << element_name << - // ")\n"; - return InterrogateDatabase::get_ptr()->lookup_element_by_scoped_name(element_name); -} - -TypeIndex -interrogate_element_type(ElementIndex element) { - // cerr << "interrogate_element_type(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_type(); -} - -bool -interrogate_element_has_getter(ElementIndex element) { - // cerr << "interrogate_element_has_getter(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).has_getter(); -} - -FunctionIndex -interrogate_element_getter(ElementIndex element) { - // cerr << "interrogate_element_getter(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_getter(); -} - -bool -interrogate_element_has_setter(ElementIndex element) { - // cerr << "interrogate_element_has_setter(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).has_setter(); -} - -FunctionIndex -interrogate_element_setter(ElementIndex element) { - // cerr << "interrogate_element_setter(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_setter(); -} - -bool -interrogate_element_has_has_function(ElementIndex element) { - // cerr << "interrogate_element_has_has_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).has_has_function(); -} - -FunctionIndex -interrogate_element_has_function(ElementIndex element) { - // cerr << "interrogate_element_has_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_has_function(); -} - -bool -interrogate_element_has_clear_function(ElementIndex element) { - // cerr << "interrogate_element_has_clear_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).has_clear_function(); -} - -FunctionIndex -interrogate_element_clear_function(ElementIndex element) { - // cerr << "interrogate_element_clear_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_clear_function(); -} - -bool -interrogate_element_has_del_function(ElementIndex element) { - // cerr << "interrogate_element_has_del_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).has_del_function(); -} - -FunctionIndex -interrogate_element_del_function(ElementIndex element) { - // cerr << "interrogate_element_del_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_del_function(); -} - -bool -interrogate_element_has_insert_function(ElementIndex element) { - // cerr << "interrogate_element_has_insert_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).has_insert_function(); -} - -FunctionIndex -interrogate_element_insert_function(ElementIndex element) { - // cerr << "interrogate_element_insert_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_insert_function(); -} - -bool -interrogate_element_has_getkey_function(ElementIndex element) { - // cerr << "interrogate_element_has_getkey_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).has_getkey_function(); -} - -FunctionIndex -interrogate_element_getkey_function(ElementIndex element) { - // cerr << "interrogate_element_getkey_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_getkey_function(); -} - -FunctionIndex -interrogate_element_length_function(ElementIndex element) { - // cerr << "interrogate_element_length_function(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).get_length_function(); -} - -bool -interrogate_element_is_sequence(ElementIndex element) { - // cerr << "interrogate_element_is_sequence(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).is_sequence(); -} - -bool -interrogate_element_is_mapping(ElementIndex element) { - // cerr << "interrogate_element_is_mapping(" << element << ")\n"; - return InterrogateDatabase::get_ptr()->get_element(element).is_mapping(); -} - -int -interrogate_number_of_globals() { - // cerr << "interrogate_number_of_globals()\n"; - return InterrogateDatabase::get_ptr()->get_num_global_elements(); -} - -ElementIndex -interrogate_get_global(int n) { - // cerr << "interrogate_get_global(" << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_global_element(n); -} - -int -interrogate_number_of_global_functions() { - // cerr << "interrogate_number_of_global_functions()\n"; - return InterrogateDatabase::get_ptr()->get_num_global_functions(); -} - -FunctionIndex -interrogate_get_global_function(int n) { - // cerr << "interrogate_get_global_function(" << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_global_function(n); -} - -int -interrogate_number_of_functions() { - // cerr << "interrogate_number_of_functions()\n"; - return InterrogateDatabase::get_ptr()->get_num_all_functions(); -} - -FunctionIndex -interrogate_get_function(int n) { - // cerr << "interrogate_get_function(" << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_all_function(n); -} - -const char * -interrogate_function_name(FunctionIndex function) { - // cerr << "interrogate_function_name(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).get_name().c_str(); -} - -const char * -interrogate_function_scoped_name(FunctionIndex function) { - // cerr << "interrogate_function_scoped_name(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).get_scoped_name().c_str(); -} - -bool -interrogate_function_has_comment(FunctionIndex function) { - // cerr << "interrogate_function_has_comment(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).has_comment(); -} - -const char * -interrogate_function_comment(FunctionIndex function) { - // cerr << "interrogate_function_comment(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).get_comment().c_str(); -} - -const char * -interrogate_function_prototype(FunctionIndex function) { - // cerr << "interrogate_function_prototype(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).get_prototype().c_str(); -} - -bool -interrogate_function_is_method(FunctionIndex function) { - // cerr << "interrogate_function_is_method(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).is_method(); -} - -TypeIndex -interrogate_function_class(FunctionIndex function) { - // cerr << "interrogate_function_class(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).get_class(); -} - -bool -interrogate_function_is_unary_op(FunctionIndex function) { - // cerr << "interrogate_function_is_unary_op(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).is_unary_op(); -} - -bool -interrogate_function_is_operator_typecast(FunctionIndex function) { - // cerr << "interrogate_function_is_operator_typecast(" << function << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).is_operator_typecast(); -} - -bool -interrogate_function_is_constructor(FunctionIndex function) { - // cerr << "interrogate_function_is_constructor(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).is_constructor(); -} - -bool -interrogate_function_is_destructor(FunctionIndex function) { - // cerr << "interrogate_function_is_destructor(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).is_destructor(); -} - -bool -interrogate_function_has_module_name(FunctionIndex function) { - // cerr << "interrogate_function_has_module_name(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).has_module_name(); -} - -const char * -interrogate_function_module_name(FunctionIndex function) { - // cerr << "interrogate_function_module_name(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).get_module_name(); -} - -bool -interrogate_function_has_library_name(FunctionIndex function) { - // cerr << "interrogate_function_has_library_name(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).has_library_name(); -} - -const char * -interrogate_function_library_name(FunctionIndex function) { - // cerr << "interrogate_function_library_name(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).get_library_name(); -} - - - -bool -interrogate_function_is_virtual(FunctionIndex function) { - // cerr << "interrogate_function_is_virtual(" << function << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).is_virtual(); -} - -int -interrogate_function_number_of_c_wrappers(FunctionIndex function) { - // cerr << "interrogate_function_number_of_c_wrappers(" << function << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).number_of_c_wrappers(); -} - -FunctionWrapperIndex -interrogate_function_c_wrapper(FunctionIndex function, int n) { - // cerr << "interrogate_function_c_wrapper(" << function << ", " << n << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).get_c_wrapper(n); -} - -int -interrogate_function_number_of_python_wrappers(FunctionIndex function) { - // cerr << "interrogate_function_number_of_python_wrappers(" << function << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).number_of_python_wrappers(); -} - -FunctionWrapperIndex -interrogate_function_python_wrapper(FunctionIndex function, int n) { - // cerr << "interrogate_function_python_wrapper(" << function << ", " << n - // << ")\n"; - return InterrogateDatabase::get_ptr()->get_function(function).get_python_wrapper(n); -} - -const char * -interrogate_wrapper_name(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_name(" << wrapper << ")\n"; - static string result; - result = InterrogateDatabase::get_ptr()->get_wrapper(wrapper).get_name(); - return result.c_str(); -} - -FunctionIndex -interrogate_wrapper_function(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_function(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).get_function(); -} - -bool -interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_is_callable_by_name(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_callable_by_name(); -} - -bool -interrogate_wrapper_is_copy_constructor(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_is_copy_constructor(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_copy_constructor(); -} - -bool -interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_is_coerce_constructor(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_coerce_constructor(); -} - -bool -interrogate_wrapper_is_extension(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_is_extension(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_extension(); -} - -bool -interrogate_wrapper_is_deprecated(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_is_deprecated(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_deprecated(); -} - -bool -interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_has_comment(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).has_comment(); -} - -const char * -interrogate_wrapper_comment(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_comment(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).get_comment().c_str(); -} - -bool -interrogate_wrapper_has_return_value(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_has_return_value(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).has_return_value(); -} - -TypeIndex -interrogate_wrapper_return_type(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_return_type(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).get_return_type(); -} - -bool -interrogate_wrapper_caller_manages_return_value(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_caller_manages_return_value(" << wrapper << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).caller_manages_return_value(); -} - -FunctionIndex -interrogate_wrapper_return_value_destructor(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_return_value_destructor(" << wrapper << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).get_return_value_destructor(); -} - -int -interrogate_wrapper_number_of_parameters(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_number_of_parameters(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).number_of_parameters(); -} - -TypeIndex -interrogate_wrapper_parameter_type(FunctionWrapperIndex wrapper, int n) { - // cerr << "interrogate_wrapper_parameter_type(" << wrapper << ", " << n << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).parameter_get_type(n); -} - -bool -interrogate_wrapper_parameter_has_name(FunctionWrapperIndex wrapper, int n) { - // cerr << "interrogate_wrapper_parameter_has_name(" << wrapper << ", " << n - // << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).parameter_has_name(n); -} - -const char * -interrogate_wrapper_parameter_name(FunctionWrapperIndex wrapper, int n) { - // cerr << "interrogate_wrapper_parameter_name(" << wrapper << ", " << n << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).parameter_get_name(n).c_str(); -} - -bool -interrogate_wrapper_parameter_is_this(FunctionWrapperIndex wrapper, int n) { - // cerr << "interrogate_wrapper_is_this(" << wrapper << ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).parameter_is_this(n); -} - -bool -interrogate_wrapper_parameter_is_optional(FunctionWrapperIndex wrapper, int n) { - // cerr << "interrogate_wrapper_is_optional(" << wrapper << ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).parameter_is_optional(n); -} - -bool -interrogate_wrapper_has_pointer(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_has_pointer(" << wrapper << ")\n"; - return (InterrogateDatabase::get_ptr()->get_fptr(wrapper) != nullptr); -} - -void * -interrogate_wrapper_pointer(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_pointer(" << wrapper << ")\n"; - return InterrogateDatabase::get_ptr()->get_fptr(wrapper); -} - -const char * -interrogate_wrapper_unique_name(FunctionWrapperIndex wrapper) { - // cerr << "interrogate_wrapper_unique_name(" << wrapper << ")\n"; - static string result; - result = InterrogateDatabase::get_ptr()->get_wrapper(wrapper).get_unique_name(); - return result.c_str(); -} - -FunctionWrapperIndex -interrogate_get_wrapper_by_unique_name(const char *unique_name) { - // cerr << "interrogate_get_wrapper_by_unique_name(" << unique_name << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_wrapper_by_unique_name(unique_name); -} - -const char * -interrogate_make_seq_seq_name(MakeSeqIndex make_seq) { - // cerr << "interrogate_make_seq_seq_name(" << make_seq << ")\n"; - static string result; - result = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_name(); - return result.c_str(); -} - -const char * -interrogate_make_seq_scoped_name(MakeSeqIndex make_seq) { - // cerr << "interrogate_make_seq_seq_name(" << make_seq << ")\n"; - static string result; - result = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_scoped_name(); - return result.c_str(); -} - -bool -interrogate_make_seq_has_comment(MakeSeqIndex make_seq) { - // cerr << "interrogate_make_seq_has_comment(" << make_seq << ")\n"; - return InterrogateDatabase::get_ptr()->get_make_seq(make_seq).has_comment(); -} - -const char * -interrogate_make_seq_comment(MakeSeqIndex make_seq) { - // cerr << "interrogate_make_seq_comment(" << make_seq << ")\n"; - return InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_comment().c_str(); -} - -const char * -interrogate_make_seq_num_name(MakeSeqIndex make_seq) { - // cerr << "interrogate_make_seq_num_name(" << make_seq << ")\n"; - FunctionIndex function = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_length_getter(); - return interrogate_function_name(function); -} - -const char * -interrogate_make_seq_element_name(MakeSeqIndex make_seq) { - // cerr << "interrogate_make_seq_element_name(" << make_seq << ")\n"; - FunctionIndex function = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_element_getter(); - return interrogate_function_name(function); -} - -FunctionIndex -interrogate_make_seq_num_getter(MakeSeqIndex make_seq) { - // cerr << "interrogate_make_seq_num_getter(" << make_seq << ")\n"; - return InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_length_getter(); -} - -FunctionIndex -interrogate_make_seq_element_getter(MakeSeqIndex make_seq) { - // cerr << "interrogate_make_seq_element_getter(" << make_seq << ")\n"; - return InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_element_getter(); -} - -int -interrogate_number_of_global_types() { - // cerr << "interrogate_number_of_global_types()\n"; - return InterrogateDatabase::get_ptr()->get_num_global_types(); -} - -TypeIndex -interrogate_get_global_type(int n) { - // cerr << "interrogate_get_global_type(" << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_global_type(n); -} - -int -interrogate_number_of_types() { - // cerr << "interrogate_number_of_types()\n"; - return InterrogateDatabase::get_ptr()->get_num_all_types(); -} - -TypeIndex -interrogate_get_type(int n) { - // cerr << "interrogate_get_type(" << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_all_type(n); -} - -TypeIndex -interrogate_get_type_by_name(const char *type_name) { - // cerr << "interrogate_get_type_by_name(" << type_name << ")\n"; - return InterrogateDatabase::get_ptr()->lookup_type_by_name(type_name); -} - -TypeIndex -interrogate_get_type_by_scoped_name(const char *type_name) { - // cerr << "interrogate_get_type_by_scoped_name(" << type_name << ")\n"; - return InterrogateDatabase::get_ptr()->lookup_type_by_scoped_name(type_name); -} - -TypeIndex -interrogate_get_type_by_true_name(const char *type_name) { - // cerr << "interrogate_get_type_by_true_name(" << type_name << ")\n"; - return InterrogateDatabase::get_ptr()->lookup_type_by_true_name(type_name); -} - -bool -interrogate_type_is_global(TypeIndex type) { - // cerr << "interrogate_type_is_global(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_global(); -} - -bool -interrogate_type_is_deprecated(TypeIndex type) { - // cerr << "interrogate_type_is_deprecated(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_deprecated(); -} - -const char * -interrogate_type_name(TypeIndex type) { - // cerr << "interrogate_type_name(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_name().c_str(); -} - -const char * -interrogate_type_scoped_name(TypeIndex type) { - // cerr << "interrogate_type_scoped_name(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_scoped_name().c_str(); -} - -const char * -interrogate_type_true_name(TypeIndex type) { - // cerr << "interrogate_type_true_name(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_true_name().c_str(); -} - -bool -interrogate_type_is_nested(TypeIndex type) { - // cerr << "interrogate_type_is_nested(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_nested(); -} - -TypeIndex -interrogate_type_outer_class(TypeIndex type) { - // cerr << "interrogate_type_outer_class(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_outer_class(); -} - -bool -interrogate_type_has_comment(TypeIndex type) { - // cerr << "interrogate_type_has_comment(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).has_comment(); -} - -const char * -interrogate_type_comment(TypeIndex type) { - // cerr << "interrogate_type_comment(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_comment().c_str(); -} - -bool -interrogate_type_has_module_name(TypeIndex type) { - // cerr << "interrogate_type_has_module_name(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).has_module_name(); -} - -const char * -interrogate_type_module_name(TypeIndex type) { - // cerr << "interrogate_type_module_name(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_module_name(); -} - -bool -interrogate_type_has_library_name(TypeIndex type) { - // cerr << "interrogate_type_has_library_name(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).has_library_name(); -} - -const char * -interrogate_type_library_name(TypeIndex type) { - // cerr << "interrogate_type_library_name(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_library_name(); -} - - -bool -interrogate_type_is_atomic(TypeIndex type) { - // cerr << "interrogate_type_is_atomic(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_atomic(); -} - -AtomicToken -interrogate_type_atomic_token(TypeIndex type) { - // cerr << "interrogate_type_atomic_token(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_atomic_token(); -} - -bool -interrogate_type_is_unsigned(TypeIndex type) { - // cerr << "interrogate_type_is_unsigned(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_unsigned(); -} - -bool -interrogate_type_is_signed(TypeIndex type) { - // cerr << "interrogate_type_is_signed(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_signed(); -} - -bool -interrogate_type_is_long(TypeIndex type) { - // cerr << "interrogate_type_is_long(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_long(); -} - -bool -interrogate_type_is_longlong(TypeIndex type) { - // cerr << "interrogate_type_is_longlong(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_longlong(); -} - -bool -interrogate_type_is_short(TypeIndex type) { - // cerr << "interrogate_type_is_short(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_short(); -} - -bool -interrogate_type_is_wrapped(TypeIndex type) { - // cerr << "interrogate_type_is_wrapped(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_wrapped(); -} - -bool -interrogate_type_is_pointer(TypeIndex type) { - // cerr << "interrogate_type_is_pointer(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_pointer(); -} - -bool -interrogate_type_is_const(TypeIndex type) { - // cerr << "interrogate_type_is_const(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_const(); -} - -bool -interrogate_type_is_typedef(TypeIndex type) { - // cerr << "interrogate_type_is_typedef(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_typedef(); -} - -TypeIndex -interrogate_type_wrapped_type(TypeIndex type) { - // cerr << "interrogate_type_wrapped_type(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_wrapped_type(); -} - -bool -interrogate_type_is_array(TypeIndex type) { - // cerr << "interrogate_type_is_array(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_array(); -} - -int -interrogate_type_array_size(TypeIndex type) { - // cerr << "interrogate_type_array_size(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_array_size(); -} - -bool -interrogate_type_is_enum(TypeIndex type) { - // cerr << "interrogate_type_is_enum(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_enum(); -} - -bool -interrogate_type_is_scoped_enum(TypeIndex type) { - // cerr << "interrogate_type_is_scoped_enum(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_scoped_enum(); -} - -int -interrogate_type_number_of_enum_values(TypeIndex type) { - // cerr << "interrogate_type_number_of_enum_values(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).number_of_enum_values(); -} - -const char * -interrogate_type_enum_value_name(TypeIndex type, int n) { - // cerr << "interrogate_type_enum_value_name(" << type << ", " << n << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_enum_value_name(n).c_str(); -} - -const char * -interrogate_type_enum_value_scoped_name(TypeIndex type, int n) { - // cerr << "interrogate_type_enum_value_scoped_name(" << type << ", " << n - // << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_enum_value_scoped_name(n).c_str(); -} - -const char * -interrogate_type_enum_value_comment(TypeIndex type, int n) { - // cerr << "interrogate_type_enum_value_comment(" << type << ", " << n << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_enum_value_comment(n).c_str(); -} - -int -interrogate_type_enum_value(TypeIndex type, int n) { - // cerr << "interrogate_type_enum_value(" << type << ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_enum_value(n); -} - -bool -interrogate_type_is_struct(TypeIndex type) { - // cerr << "interrogate_type_is_struct(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_struct(); -} - -bool -interrogate_type_is_class(TypeIndex type) { - // cerr << "interrogate_type_is_class(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_class(); -} - -bool -interrogate_type_is_union(TypeIndex type) { - // cerr << "interrogate_type_is_union(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_union(); -} - -bool -interrogate_type_is_fully_defined(TypeIndex type) { - // cerr << "interrogate_type_is_fully_defined(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_fully_defined(); -} - -bool -interrogate_type_is_unpublished(TypeIndex type) { - // cerr << "interrogate_type_is_unpublished(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_unpublished(); -} - -int -interrogate_type_number_of_constructors(TypeIndex type) { - // cerr << "interrogate_type_number_of_constructors(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).number_of_constructors(); -} - -FunctionIndex -interrogate_type_get_constructor(TypeIndex type, int n) { - // cerr << "interrogate_type_get_constructor(" << type << ", " << n << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_constructor(n); -} - -bool -interrogate_type_has_destructor(TypeIndex type) { - // cerr << "interrogate_type_has_destructor(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).has_destructor(); -} - -bool -interrogate_type_destructor_is_inherited(TypeIndex type) { - // cerr << "interrogate_type_destructor_is_inherited(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).destructor_is_inherited(); -} - -FunctionIndex -interrogate_type_get_destructor(TypeIndex type) { - // cerr << "interrogate_type_get_destructor(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_destructor(); -} - -int -interrogate_type_number_of_elements(TypeIndex type) { - // cerr << "interrogate_type_number_of_elements(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).number_of_elements(); -} - -ElementIndex -interrogate_type_get_element(TypeIndex type, int n) { - // cerr << "interrogate_type_get_element(" << type << ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_element(n); -} - -int -interrogate_type_number_of_methods(TypeIndex type) { - // cerr << "interrogate_type_number_of_methods(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).number_of_methods(); -} - -FunctionIndex -interrogate_type_get_method(TypeIndex type, int n) { - // cerr << "interrogate_type_get_method(" << type << ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_method(n); -} - -int -interrogate_type_number_of_make_seqs(TypeIndex type) { - // cerr << "interrogate_type_number_of_make_seqs(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).number_of_make_seqs(); -} - -MakeSeqIndex -interrogate_type_get_make_seq(TypeIndex type, int n) { - // cerr << "interrogate_type_get_make_seq(" << type << ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_make_seq(n); -} - -int -interrogate_type_number_of_casts(TypeIndex type) { - // cerr << "interrogate_type_number_of_casts(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).number_of_casts(); -} - -FunctionIndex -interrogate_type_get_cast(TypeIndex type, int n) { - // cerr << "interrogate_type_get_cast(" << type << ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_cast(n); -} - -int -interrogate_type_number_of_derivations(TypeIndex type) { - // cerr << "interrogate_type_number_of_derivations(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).number_of_derivations(); -} - -TypeIndex -interrogate_type_get_derivation(TypeIndex type, int n) { - // cerr << "interrogate_type_get_derivation(" << type << ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_derivation(n); -} - -bool -interrogate_type_is_final(TypeIndex type) { - // cerr << "interrogate_type_is_final(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).is_final(); -} - -bool -interrogate_type_derivation_has_upcast(TypeIndex type, int n) { - // cerr << "interrogate_type_derivation_has_upcast(" << type << ", " << n << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).derivation_has_upcast(n); -} - -FunctionIndex -interrogate_type_get_upcast(TypeIndex type, int n) { - // cerr << "interrogate_type_get_upcast(" << type << ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).derivation_get_upcast(n); -} - -bool -interrogate_type_derivation_downcast_is_impossible(TypeIndex type, int n) { - // cerr << "interrogate_type_derivation_downcast_is_impossible(" << type << - // ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).derivation_downcast_is_impossible(n); -} - -bool -interrogate_type_derivation_has_downcast(TypeIndex type, int n) { - // cerr << "interrogate_type_derivation_has_downcast(" << type << ", " << n - // << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).derivation_has_downcast(n); -} - -FunctionIndex -interrogate_type_get_downcast(TypeIndex type, int n) { - // cerr << "interrogate_type_get_downcast(" << type << ", " << n << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).derivation_get_downcast(n); -} - -int -interrogate_type_number_of_nested_types(TypeIndex type) { - // cerr << "interrogate_type_number_of_nested_types(" << type << ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).number_of_nested_types(); -} - -TypeIndex -interrogate_type_get_nested_type(TypeIndex type, int n) { - // cerr << "interrogate_type_get_nested_type(" << type << ", " << n << - // ")\n"; - return InterrogateDatabase::get_ptr()->get_type(type).get_nested_type(n); -} diff --git a/dtool/src/interrogatedb/interrogate_interface.h b/dtool/src/interrogatedb/interrogate_interface.h deleted file mode 100644 index 6ae1bdcb24..0000000000 --- a/dtool/src/interrogatedb/interrogate_interface.h +++ /dev/null @@ -1,581 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogate_interface.h - * @author frang - * @date 1999-11-09 - */ - -#ifndef INTERROGATE_INTERFACE_H -#define INTERROGATE_INTERFACE_H - -#include "dtoolbase.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// This file defines the interface to the interrogate database. This database -// is generated by running interrogate on a package's source code; interrogate -// parses the C++ syntax, determines the public interface, generates C-style -// wrapper functions where necessary, and builds up a table of functions and -// classes and their relationships. - -/* - * Some of this data (in particular, the wrapper functions, and the table of - * unique names for these functions) is linked in along with the codebase, - * permanently a part of the library file, and is always available; the rest - * of it is stored in external files (named *.in) and read in when needed. - * For this reason, most of the interface functions defined here will force a - * load of the complete interrogate database the first time any of them are - * called. The three exceptions are noted below; they are - * interrogate_wrapper_has_pointer(), interrogate_wrapper_pointer(), and - * interrogate_get_wrapper_by_unique_name(). - */ - - -// The interface here is intentionally made to be as simple as possible, to -// maximize portability. All that is required of a scripting language is a -// foreign function interface capable of calling C functions. - - -// In general, the interrogate database consists of a number of query -// functions that allow the caller to walk through the list of available -// types, functions, manifests, etc. For each of these, a unique index number -// is returned; this index number may then be used to query details about the -// type, function, etc. The index numbers are only guaranteed to remain -// unchanged during a particular session; from one session to another they may -// differ. - -// All index numbers are ordinary integers. Each has a unique typedef here -// for clarity of meaning, but they may be treated as ordinary integers by the -// caller. -typedef int ManifestIndex; -typedef int ElementIndex; -typedef int TypeIndex; -typedef int FunctionIndex; -typedef int FunctionWrapperIndex; -typedef int MakeSeqIndex; - -// Atomic types are those that are built in to C. This enumerated value is -// returned by interrogate_type_atomic_token() when a type is known to be one -// of the atomic types. -enum AtomicToken { - AT_not_atomic = 0, - AT_int = 1, - AT_float = 2, - AT_double = 3, - AT_bool = 4, - AT_char = 5, - AT_void = 6, - - // There isn't an atomic string type in C, but there is one in almost all - // other languages. If -string is supplied to the interrogate command line, - // functions may be reported as returning and accepting objects of type - // atomic string. For the C calling convention wrappers, atomic string - // means (const char *); for other calling convention wrappers, atomic - // string means whatever the native string representation is. - AT_string = 7, - - AT_longlong = 8, - - // This is not a type that C has, but C++ and many scripting languages do; - // it indicates a null value, or the absence of any value. - AT_null = 9, -}; - -EXPCL_INTERROGATEDB void interrogate_add_search_directory(const char *dirname); -EXPCL_INTERROGATEDB void interrogate_add_search_path(const char *pathstring); -EXPCL_INTERROGATEDB bool interrogate_error_flag(); - -// Manifest Symbols - -/* - * These correspond to #define constants that appear in the C code. (These - * are only the manifest constants--those #define's that take no parameters. - * Manifest functions, #define's that take one or more parameters, are not - * exported.) They cannot be set, of course, but they often have a meaningful - * value that may be get. The scripting language may choose to get the value - * as a literal string via interrogate_manifest_definition(), or as a value of - * a particular type (whatever type interrogate thinks it is), as returned by - * the getter function given by interrogate_manifest_getter(). - */ - -EXPCL_INTERROGATEDB int interrogate_number_of_manifests(); -EXPCL_INTERROGATEDB ManifestIndex interrogate_get_manifest(int n); -EXPCL_INTERROGATEDB ManifestIndex interrogate_get_manifest_by_name(const char *manifest_name); -EXPCL_INTERROGATEDB const char *interrogate_manifest_name(ManifestIndex manifest); -EXPCL_INTERROGATEDB const char *interrogate_manifest_definition(ManifestIndex manifest); -EXPCL_INTERROGATEDB bool interrogate_manifest_has_type(ManifestIndex manifest); -EXPCL_INTERROGATEDB TypeIndex interrogate_manifest_get_type(ManifestIndex manifest); -EXPCL_INTERROGATEDB bool interrogate_manifest_has_getter(ManifestIndex manifest); -EXPCL_INTERROGATEDB FunctionIndex interrogate_manifest_getter(ManifestIndex manifest); - -// An exception is made for manifest constants that have an integer type -// value, since these are so common. The scripting language can query these -// values directly, which saves having to generate a wrapper function for each -// stupid little manifest. In this case, there will be no getter function -// available. -EXPCL_INTERROGATEDB bool interrogate_manifest_has_int_value(ManifestIndex manifest); -EXPCL_INTERROGATEDB int interrogate_manifest_get_int_value(ManifestIndex manifest); - - -// Data Elements - -// These correspond to data members of a class, or global data elements. -// Interrogate automatically generates a getter function and, if possible, a -// setter function. - -EXPCL_INTERROGATEDB const char *interrogate_element_name(ElementIndex element); -EXPCL_INTERROGATEDB const char *interrogate_element_scoped_name(ElementIndex element); -EXPCL_INTERROGATEDB bool interrogate_element_has_comment(ElementIndex element); -EXPCL_INTERROGATEDB const char *interrogate_element_comment(ElementIndex element); -EXPCL_INTERROGATEDB ElementIndex interrogate_get_element_by_name(const char *element_name); -EXPCL_INTERROGATEDB ElementIndex interrogate_get_element_by_scoped_name(const char *element_name); - -// Be careful with this function. The element's bare type is not likely to be -// directly useful to the scripting language. This is a different answer than -// the return value of the getter. - -// The element type might well be something concrete that the scripting -// language can't handle directly, e.g. a Node, while the getter will return -// (and the setter accept) a pointer to a Node, which is what the scripting -// language actually works with. -EXPCL_INTERROGATEDB TypeIndex interrogate_element_type(ElementIndex element); - -EXPCL_INTERROGATEDB bool interrogate_element_has_getter(ElementIndex element); -EXPCL_INTERROGATEDB FunctionIndex interrogate_element_getter(ElementIndex element); -EXPCL_INTERROGATEDB bool interrogate_element_has_setter(ElementIndex element); -EXPCL_INTERROGATEDB FunctionIndex interrogate_element_setter(ElementIndex element); -EXPCL_INTERROGATEDB bool interrogate_element_has_has_function(ElementIndex element); -EXPCL_INTERROGATEDB FunctionIndex interrogate_element_has_function(ElementIndex element); -EXPCL_INTERROGATEDB bool interrogate_element_has_clear_function(ElementIndex element); -EXPCL_INTERROGATEDB FunctionIndex interrogate_element_clear_function(ElementIndex element); -EXPCL_INTERROGATEDB bool interrogate_element_has_del_function(ElementIndex element); -EXPCL_INTERROGATEDB FunctionIndex interrogate_element_del_function(ElementIndex element); -EXPCL_INTERROGATEDB bool interrogate_element_has_insert_function(ElementIndex element); -EXPCL_INTERROGATEDB FunctionIndex interrogate_element_insert_function(ElementIndex element); -EXPCL_INTERROGATEDB bool interrogate_element_has_getkey_function(ElementIndex element); -EXPCL_INTERROGATEDB FunctionIndex interrogate_element_getkey_function(ElementIndex element); -EXPCL_INTERROGATEDB FunctionIndex interrogate_element_length_function(ElementIndex element); - -EXPCL_INTERROGATEDB bool interrogate_element_is_sequence(ElementIndex element); -EXPCL_INTERROGATEDB bool interrogate_element_is_mapping(ElementIndex element); - -// Global Data - -// This is the list of global data elements. - -EXPCL_INTERROGATEDB int interrogate_number_of_globals(); -EXPCL_INTERROGATEDB ElementIndex interrogate_get_global(int n); - -// Functions - -// There is a unique FunctionIndex associated with each of the functions that -// interrogate knows about. This includes member functions, nonmember -// functions, synthesized getters and setters, and upcastdowncast functions. - - -// These are the global (nonmember) functions that appear outside of any class -// definition. -EXPCL_INTERROGATEDB int interrogate_number_of_global_functions(); -EXPCL_INTERROGATEDB FunctionIndex interrogate_get_global_function(int n); - -// This can be used to traverse through *all* the functions known to -// interrogate. It's usually not what you want, since this includes global -// functions, class methods, and synthesized functions like upcasts and -// downcasts. You probably want to use instead -// interrogate_number_of_global_functions(), above. -EXPCL_INTERROGATEDB int interrogate_number_of_functions(); -EXPCL_INTERROGATEDB FunctionIndex interrogate_get_function(int n); - -// This is the function's name. It is not unique; it may be shared between -// multiple different functions that have the same name but different -// parameter types (this is C++'s function overloading). Two different classes -// might also have member functions that have the same name, or the same name -// as a global function (but also see the scoped_name, below). -EXPCL_INTERROGATEDB const char *interrogate_function_name(FunctionIndex function); - -// The scoped name is the function name prefixed with the name of the class -// that includes the function, if the function is a class method. If it is a -// global function, the scoped name is the same as the name returned above. -// In the absence of C++ function overloading, this name will be unique to -// each function. -EXPCL_INTERROGATEDB const char *interrogate_function_scoped_name(FunctionIndex function); - -// This returns the C++ comment written for the function, either in the header -// file or in the .C file, or both. -EXPCL_INTERROGATEDB bool interrogate_function_has_comment(FunctionIndex function); -EXPCL_INTERROGATEDB const char *interrogate_function_comment(FunctionIndex function); - -// This defines the function prototype as it appears in the C++ source, useful -// primarily for documentation purposes. -EXPCL_INTERROGATEDB const char *interrogate_function_prototype(FunctionIndex function); - -// This can be used to determine the class that the function is a method for, -// if the function is a class method. -EXPCL_INTERROGATEDB bool interrogate_function_is_method(FunctionIndex function); -EXPCL_INTERROGATEDB TypeIndex interrogate_function_class(FunctionIndex function); -EXPCL_INTERROGATEDB bool interrogate_function_is_unary_op(FunctionIndex function); -EXPCL_INTERROGATEDB bool interrogate_function_is_operator_typecast(FunctionIndex function); -EXPCL_INTERROGATEDB bool interrogate_function_is_constructor(FunctionIndex function); -EXPCL_INTERROGATEDB bool interrogate_function_is_destructor(FunctionIndex function); - -// This returns the module name reported for the function, if available. -EXPCL_INTERROGATEDB bool interrogate_function_has_module_name(FunctionIndex function); -EXPCL_INTERROGATEDB const char *interrogate_function_module_name(FunctionIndex function); - -// This returns the library name reported for the function, if available. -EXPCL_INTERROGATEDB bool interrogate_function_has_library_name(FunctionIndex function); -EXPCL_INTERROGATEDB const char *interrogate_function_library_name(FunctionIndex function); - -// This is true for virtual member functions. It's not likely that this will -// be important to the scripting language. -EXPCL_INTERROGATEDB bool interrogate_function_is_virtual(FunctionIndex function); - - -// The actual callable function interface is defined via one or more wrappers -// for each function. (There might be multiple wrappers for the same function -// to allow for default parameter values.) - -// At present, interrogate can generate wrappers that use the C calling -// convention or the Python calling convention. The set of wrappers that will -// actually be available depends on the parameters passed to the interrogate -// command line. -EXPCL_INTERROGATEDB int interrogate_function_number_of_c_wrappers(FunctionIndex function); -EXPCL_INTERROGATEDB FunctionWrapperIndex interrogate_function_c_wrapper(FunctionIndex function, int n); - -EXPCL_INTERROGATEDB int interrogate_function_number_of_python_wrappers(FunctionIndex function); -EXPCL_INTERROGATEDB FunctionWrapperIndex interrogate_function_python_wrapper(FunctionIndex function, int n); - -// Function wrappers - -// These define the way to call a given function. Depending on the parameters -// supplied to interrogate, a function wrapper may be able to supply either a -// void * pointer to the function, or the name of the function in the library, -// or both. - - -// This returns the actual name of the wrapper function, as opposed to the -// name of the function it wraps. It's probably not terribly useful to the -// scripting language, unless the -fnames option was given to interrogate, in -// which case this name may be used to call the wrapper function (see -// is_callable_by_name, below). It will usually be an ugly hashed name, not -// intended for human consumption. - -// Don't confuse this with the unique_name, below. The two are related, but -// not identical. -EXPCL_INTERROGATEDB const char *interrogate_wrapper_name(FunctionWrapperIndex wrapper); - -// Returns the function that this wrapper belongs to. -EXPCL_INTERROGATEDB FunctionIndex interrogate_wrapper_function(FunctionWrapperIndex wrapper); - -// This returns true if -fnames was given to interrogate, making the wrapper -// function callable directly by its name. -EXPCL_INTERROGATEDB bool interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper); - -// This returns true if this is a copy constructor. -EXPCL_INTERROGATEDB bool interrogate_wrapper_is_copy_constructor(FunctionWrapperIndex wrapper); - -// This returns true if this is a constructor that is not marked "explicit". -EXPCL_INTERROGATEDB bool interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper); - -// This returns true if this is an extension function, rather than a real -// function defined in the C++ code. -EXPCL_INTERROGATEDB bool interrogate_wrapper_is_extension(FunctionWrapperIndex wrapper); - -// This returns true if function is marked as deprecated. -EXPCL_INTERROGATEDB bool interrogate_wrapper_is_deprecated(FunctionWrapperIndex wrapper); - -// This returns the C++ comment written for the function wrapper, usually from -// the .cpp file. There may be a different comment for each overload of a -// given function. -EXPCL_INTERROGATEDB bool interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper); -EXPCL_INTERROGATEDB const char *interrogate_wrapper_comment(FunctionWrapperIndex wrapper); - -// Every function wrapper has zero or more parameters and may or may not have -// a return value. Each parameter has a type and may or may not have a name. -// For member functions, the first parameter may be a 'this' parameter, which -// should receive a pointer to the class object. (If a member function does -// not have a 'this' parameter as its first parameter, it is a static member -// function, also called a class method.) - -EXPCL_INTERROGATEDB bool interrogate_wrapper_has_return_value(FunctionWrapperIndex wrapper); -EXPCL_INTERROGATEDB TypeIndex interrogate_wrapper_return_type(FunctionWrapperIndex wrapper); - -/* - * Sometimes interrogate must synthesize a wrapper that allocates its return - * value from the free store. Other times (especially if -refcount is - * supplied to interrogate), interrogate will automatically increment the - * count of a reference-counted object that it returns. In cases like these, - * interrogate_wrapper_caller_manages_return_value() will return true, and it - * is the responsibility of the scripting language to eventually call the - * destructor supplied by interrogate_wrapper_return_value_destructor() on - * this value when it is no longer needed (which will generally be the same - * destructor as that for the class). Otherwise, this function will return - * false, and the scripting language should *not* call any destructor on this - * value. - */ -EXPCL_INTERROGATEDB bool interrogate_wrapper_caller_manages_return_value(FunctionWrapperIndex wrapper); -EXPCL_INTERROGATEDB FunctionIndex interrogate_wrapper_return_value_destructor(FunctionWrapperIndex wrapper); - -// These define the parameters of the function. -EXPCL_INTERROGATEDB int interrogate_wrapper_number_of_parameters(FunctionWrapperIndex wrapper); -EXPCL_INTERROGATEDB TypeIndex interrogate_wrapper_parameter_type(FunctionWrapperIndex wrapper, int n); -EXPCL_INTERROGATEDB bool interrogate_wrapper_parameter_has_name(FunctionWrapperIndex wrapper, int n); -EXPCL_INTERROGATEDB const char *interrogate_wrapper_parameter_name(FunctionWrapperIndex wrapper, int n); -EXPCL_INTERROGATEDB bool interrogate_wrapper_parameter_is_this(FunctionWrapperIndex wrapper, int n); -EXPCL_INTERROGATEDB bool interrogate_wrapper_parameter_is_optional(FunctionWrapperIndex wrapper, int n); - -// This returns a pointer to a function that may be called to invoke the -// function, if the -fptrs option to return function pointers was specified to -// interrogate. Be sure to push the required parameters on the stack, -// according to the calling convention, before calling the function. - -// These two functions may be called without forcing a load of the complete -// interrogate database. -EXPCL_INTERROGATEDB bool interrogate_wrapper_has_pointer(FunctionWrapperIndex wrapper); -EXPCL_INTERROGATEDB void *interrogate_wrapper_pointer(FunctionWrapperIndex wrapper); - -// This function will return a name that is guaranteed to be unique to this -// particular function wrapper, and that will (usually) be consistent across -// multiple runtime sessions. (It will only change between sessions if the -// database was regenerated in the interim with some new function that -// happened to introduce a hash conflict.) - -// The unique name is an ugly hashed name, not safe for human consumption. -// Its sole purpose is to provide some consistent way to identify function -// wrappers between sessions. -EXPCL_INTERROGATEDB const char *interrogate_wrapper_unique_name(FunctionWrapperIndex wrapper); - -// This function provides a reverse-lookup on the above unique name, returning -// the wrapper index corresponding to the given name. It depends on data -// having been compiled directly into the library, and thus is only available -// if the option -unique-names was given to interrogate. - -// This function may be called without forcing a load of the complete -// interrogate database. -EXPCL_INTERROGATEDB FunctionWrapperIndex interrogate_get_wrapper_by_unique_name(const char *unique_name); - -// MakeSeqs - -// These are special synthesized methods that iterate through a list. They -// are generated in C++ code via the MAKE_SEQ macro. The normal pattern is -// that a pair of actual C++ methods like get_num_things() and get_thing(n) -// are used to synthesize a new method called get_things(). - -EXPCL_INTERROGATEDB const char *interrogate_make_seq_seq_name(MakeSeqIndex make_seq); -EXPCL_INTERROGATEDB const char *interrogate_make_seq_scoped_name(MakeSeqIndex make_seq); -EXPCL_INTERROGATEDB bool interrogate_make_seq_has_comment(ElementIndex element); -EXPCL_INTERROGATEDB const char *interrogate_make_seq_comment(ElementIndex element); -// The name of the real method that returns the length, e.g. "get_num_things" -EXPCL_INTERROGATEDB const char *interrogate_make_seq_num_name(MakeSeqIndex make_seq); -// The name of the real method that returns the nth element, e.g. "get_thing" -EXPCL_INTERROGATEDB const char *interrogate_make_seq_element_name(MakeSeqIndex make_seq); -EXPCL_INTERROGATEDB FunctionIndex interrogate_make_seq_num_getter(MakeSeqIndex make_seq); -EXPCL_INTERROGATEDB FunctionIndex interrogate_make_seq_element_getter(MakeSeqIndex make_seq); - -// Types - -// These are all the types that interrogate knows about. This includes atomic -// types like ints and floats, type wrappers like pointers and const pointers, -// enumerated types, and classes. - -/* - * Two lists of types are maintained: the list of global types, which includes - * only those types intended to be wrapped in the API (for instance, all of - * the classes). The second list is the complete list of all types, which - * probably does not need to be traversed--this includes *all* types known to - * the interrogate database, including simple types and pointers and const - * pointers to classes. These types are necessary to fully define all of the - * function parameters, but need not themselves be wrapped. - */ - -EXPCL_INTERROGATEDB int interrogate_number_of_global_types(); -EXPCL_INTERROGATEDB TypeIndex interrogate_get_global_type(int n); -EXPCL_INTERROGATEDB int interrogate_number_of_types(); -EXPCL_INTERROGATEDB TypeIndex interrogate_get_type(int n); -EXPCL_INTERROGATEDB TypeIndex interrogate_get_type_by_name(const char *type_name); -EXPCL_INTERROGATEDB TypeIndex interrogate_get_type_by_scoped_name(const char *type_name); -EXPCL_INTERROGATEDB TypeIndex interrogate_get_type_by_true_name(const char *type_name); -EXPCL_INTERROGATEDB bool interrogate_type_is_global(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_deprecated(TypeIndex type); -EXPCL_INTERROGATEDB const char *interrogate_type_name(TypeIndex type); -EXPCL_INTERROGATEDB const char *interrogate_type_scoped_name(TypeIndex type); -EXPCL_INTERROGATEDB const char *interrogate_type_true_name(TypeIndex type); - -// A given type might be a nested type, meaning it is entirely defined within -// (and scoped within) some different C++ class. In this case, the -// type_name() will return the local name of the type as seen within the -// class, while the scoped_name() will return the fully-qualified name of the -// type, and is_nested() and outer_class() can be used to determine the class -// it is nested within. -EXPCL_INTERROGATEDB bool interrogate_type_is_nested(TypeIndex type); -EXPCL_INTERROGATEDB TypeIndex interrogate_type_outer_class(TypeIndex type); - -EXPCL_INTERROGATEDB bool interrogate_type_has_comment(TypeIndex type); -EXPCL_INTERROGATEDB const char *interrogate_type_comment(TypeIndex type); - -// This returns the module name reported for the type, if available. -EXPCL_INTERROGATEDB bool interrogate_type_has_module_name(TypeIndex type); -EXPCL_INTERROGATEDB const char *interrogate_type_module_name(TypeIndex type); - -// This returns the library name reported for the type, if available. -EXPCL_INTERROGATEDB bool interrogate_type_has_library_name(TypeIndex type); -EXPCL_INTERROGATEDB const char *interrogate_type_library_name(TypeIndex type); - - -// If interrogate_type_is_atomic() returns true, the type is one of the basic -// C types enumerated in AtomicToken, above. The type may then be further -// modified by one or more of unsigned, signed, long, longlong, or short. -// However, it will not be a pointer. -EXPCL_INTERROGATEDB bool interrogate_type_is_atomic(TypeIndex type); -EXPCL_INTERROGATEDB AtomicToken interrogate_type_atomic_token(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_unsigned(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_signed(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_long(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_longlong(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_short(TypeIndex type); - -// If interrogate_type_is_wrapped() returns true, this is a composite type -// "wrapped" around some simpler type, for instance a pointer to a class. The -// type will be either a pointer or a const wrapper--it cannot be a -// combination of these. (When combinations are required, they use multiple -// wrappers. A const char pointer, for example, is represented as a pointer -// wrapper around a const wrapper around an atomic char.) -EXPCL_INTERROGATEDB bool interrogate_type_is_wrapped(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_pointer(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_const(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_typedef(TypeIndex type); -EXPCL_INTERROGATEDB TypeIndex interrogate_type_wrapped_type(TypeIndex type); - -// If interrogate_type_is_array() returns true, this is an array type. -EXPCL_INTERROGATEDB bool interrogate_type_is_array(TypeIndex type); -EXPCL_INTERROGATEDB int interrogate_type_array_size(TypeIndex type); - -// If interrogate_type_is_enum() returns true, this is an enumerated type, -// which means it may take any one of a number of named integer values. -EXPCL_INTERROGATEDB bool interrogate_type_is_enum(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_scoped_enum(TypeIndex type); -EXPCL_INTERROGATEDB int interrogate_type_number_of_enum_values(TypeIndex type); -EXPCL_INTERROGATEDB const char *interrogate_type_enum_value_name(TypeIndex type, int n); -EXPCL_INTERROGATEDB const char *interrogate_type_enum_value_scoped_name(TypeIndex type, int n); -EXPCL_INTERROGATEDB const char *interrogate_type_enum_value_comment(TypeIndex type, int n); -EXPCL_INTERROGATEDB int interrogate_type_enum_value(TypeIndex type, int n); - -// If none of the above is true, the type is some extension type. It may be a -// struct, class, or union (and the distinction between these three is not -// likely to be important to the scripting language). In any case, it may -// contain zero or more constructors, zero or one destructor, zero or more -// member functions, and zero or more data members; all of the remaining type -// functions may apply. -EXPCL_INTERROGATEDB bool interrogate_type_is_struct(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_class(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_is_union(TypeIndex type); - -// If is_fully_defined() returns false, this classstruct was a forward -// reference, and we really don't know anything about it. (In this case, it -// will appear to have no methods or members.) -EXPCL_INTERROGATEDB bool interrogate_type_is_fully_defined(TypeIndex type); - -// If is_unpublished() returns false, the classstruct is unknown because it -// was not marked to be published (or, in promiscuous mode, it is a protected -// or private nested class). -EXPCL_INTERROGATEDB bool interrogate_type_is_unpublished(TypeIndex type); - -/* - * Otherwise, especially if the type is a struct or class, we may have a - * number of member functions, including zero or more constructors and zero or - * one destructor. A constructor function may be called to allocate a new - * instance of the type; its return value will be a pointer to the new - * instance. The destructor may be called to destroy the instance; however, - * it usually should not be explicitly called by the user, since the proper - * support of the interrogate_caller_manages_return_value() interface, above, - * will ensure that the appropriate destructors are called when they should - * be. - */ - -/* - * In certain circumstances, the destructor might be inherited from a parent - * or ancestor class. This happens when the destructor wrapper from the - * ancestor class is an acceptable substitute for this destructor; this is - * only possible in the case of a virtual C++ destructor. In this case, the - * destructor returned here will be the same function index as the one - * returned by the ancestor class, and - * interrogate_type_destructor_is_inherited() will return true for this class. - */ -EXPCL_INTERROGATEDB int interrogate_type_number_of_constructors(TypeIndex type); -EXPCL_INTERROGATEDB FunctionIndex interrogate_type_get_constructor(TypeIndex type, int n); -EXPCL_INTERROGATEDB bool interrogate_type_has_destructor(TypeIndex type); -EXPCL_INTERROGATEDB bool interrogate_type_destructor_is_inherited(TypeIndex type); -EXPCL_INTERROGATEDB FunctionIndex interrogate_type_get_destructor(TypeIndex type); - -// This is the set of exposed data elements in the struct or class. -EXPCL_INTERROGATEDB int interrogate_type_number_of_elements(TypeIndex type); -EXPCL_INTERROGATEDB ElementIndex interrogate_type_get_element(TypeIndex type, int n); - -// This is the set of exposed member functions in the struct or class. -EXPCL_INTERROGATEDB int interrogate_type_number_of_methods(TypeIndex type); -EXPCL_INTERROGATEDB FunctionIndex interrogate_type_get_method(TypeIndex type, int n); - -// This is the set of MAKE_SEQ wrappers in the struct or class. -EXPCL_INTERROGATEDB int interrogate_type_number_of_make_seqs(TypeIndex type); -EXPCL_INTERROGATEDB MakeSeqIndex interrogate_type_get_make_seq(TypeIndex type, int n); - -// A C++ class may also define a number of explicit cast operators, which -// define how to convert an object of this type to an object of some other -// type (the type can be inferred by the return type of the cast function). -// This is not related to upcast and downcast, defined below. -EXPCL_INTERROGATEDB int interrogate_type_number_of_casts(TypeIndex type); -EXPCL_INTERROGATEDB FunctionIndex interrogate_type_get_cast(TypeIndex type, int n); - -// A C++ class may inherit from zero or more base classes. This defines the -// list of base classes for this particular type. -EXPCL_INTERROGATEDB int interrogate_type_number_of_derivations(TypeIndex type); -EXPCL_INTERROGATEDB TypeIndex interrogate_type_get_derivation(TypeIndex type, int n); -EXPCL_INTERROGATEDB bool interrogate_type_is_final(TypeIndex type); - -// For each base class, we might need to define an explicit upcast or downcast -// operation to convert the pointer to the derived class to an appropriate -// pointer to its base class (upcast) or vice-versa (downcast). This is -// particularly true in the presence of multiple inheritance or virtual -// inheritance, in which case you cannot simply use the same pointer as either -// type. - -// If interrogate_type_derivation_has_upcast() returns true for a particular -// typederivation combination, you must use the indicated upcast function to -// convert pointers of this type to pointers of the base type before calling -// any of the inherited methods from the base class. If this returns false, -// you may simply use the same pointer as either a derived class pointer or a -// base class pointer without any extra step. -EXPCL_INTERROGATEDB bool interrogate_type_derivation_has_upcast(TypeIndex type, int n); -EXPCL_INTERROGATEDB FunctionIndex interrogate_type_get_upcast(TypeIndex type, int n); - -/* - * Although it is always possible to upcast a pointer to a base class, it is - * not always possible to downcast from a base class to the derived class - * (particularly in the presence of virtual inheritance). If - * interrogate_type_derivation_downcast_is_impossible() returns true, forget - * it. Otherwise, downcasting works the same way as upcasting. (Of course, - * it is the caller's responsibility to guarantee that the pointer actually - * represents an object of the type being downcast to.) - */ -EXPCL_INTERROGATEDB bool interrogate_type_derivation_downcast_is_impossible(TypeIndex type, int n); -EXPCL_INTERROGATEDB bool interrogate_type_derivation_has_downcast(TypeIndex type, int n); -EXPCL_INTERROGATEDB FunctionIndex interrogate_type_get_downcast(TypeIndex type, int n); - -// A C++ class may also define any number of nested types--classes or enums -// defined within the scope of this class. -EXPCL_INTERROGATEDB int interrogate_type_number_of_nested_types(TypeIndex type); -EXPCL_INTERROGATEDB TypeIndex interrogate_type_get_nested_type(TypeIndex type, int n); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/dtool/src/interrogatedb/interrogate_request.cxx b/dtool/src/interrogatedb/interrogate_request.cxx deleted file mode 100644 index 3e02a9eecb..0000000000 --- a/dtool/src/interrogatedb/interrogate_request.cxx +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogate_request.cxx - * @author drose - * @date 2000-08-01 - */ - -#include "interrogate_request.h" -#include "interrogateDatabase.h" - -#include // for strdup - -void -interrogate_request_database(const char *database_filename) { - InterrogateModuleDef *def = new InterrogateModuleDef; - memset(def, 0, sizeof(InterrogateModuleDef)); -#ifdef _WIN32 - def->database_filename = _strdup(database_filename); -#else - def->database_filename = strdup(database_filename); -#endif - - // Don't think of this as a leak; think of it as a one-time database - // allocation. - InterrogateDatabase::get_ptr()->request_module(def); -} - -void -interrogate_request_module(InterrogateModuleDef *def) { - InterrogateDatabase::get_ptr()->request_module(def); -} diff --git a/dtool/src/interrogatedb/p3interrogatedb_composite1.cxx b/dtool/src/interrogatedb/p3interrogatedb_composite1.cxx deleted file mode 100644 index 4e54cee5a9..0000000000 --- a/dtool/src/interrogatedb/p3interrogatedb_composite1.cxx +++ /dev/null @@ -1,7 +0,0 @@ -#include "config_interrogatedb.cxx" -#include "indexRemapper.cxx" -#include "interrogateComponent.cxx" -#include "interrogateDatabase.cxx" -#include "interrogateElement.cxx" -#include "interrogateFunction.cxx" -#include "interrogateFunctionWrapper.cxx" diff --git a/dtool/src/interrogatedb/p3interrogatedb_composite2.cxx b/dtool/src/interrogatedb/p3interrogatedb_composite2.cxx deleted file mode 100644 index 41453e5f3e..0000000000 --- a/dtool/src/interrogatedb/p3interrogatedb_composite2.cxx +++ /dev/null @@ -1,6 +0,0 @@ -#include "interrogateMakeSeq.cxx" -#include "interrogateManifest.cxx" -#include "interrogateType.cxx" -#include "interrogate_datafile.cxx" -#include "interrogate_interface.cxx" -#include "interrogate_request.cxx" diff --git a/dtool/src/interrogatedb/py_compat.cxx b/dtool/src/interrogatedb/py_compat.cxx deleted file mode 100644 index 722bc8300b..0000000000 --- a/dtool/src/interrogatedb/py_compat.cxx +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file py_compat.cxx - * @author rdb - * @date 2017-12-03 - */ - -#include "py_compat.h" -#include "py_panda.h" - -#ifdef HAVE_PYTHON - -#if PY_MAJOR_VERSION < 3 -/** - * Given a long or int, returns a size_t, or raises an OverflowError if it is - * out of range. - */ -size_t PyLongOrInt_AsSize_t(PyObject *vv) { - if (PyInt_Check(vv)) { - long value = PyInt_AS_LONG(vv); - if (value < 0) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to size_t"); - return (size_t)-1; - } - return (size_t)value; - } - - if (!PyLong_Check(vv)) { - Dtool_Raise_TypeError("a long or int was expected"); - return (size_t)-1; - } - - size_t bytes; - int one = 1; - int res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes, - SIZEOF_SIZE_T, (int)*(unsigned char*)&one, 0); - - if (res < 0) { - return (size_t)res; - } else { - return bytes; - } -} -#endif - -#endif // HAVE_PYTHON diff --git a/dtool/src/interrogatedb/py_compat.h b/dtool/src/interrogatedb/py_compat.h index 4b67fba763..70c8b43e91 100644 --- a/dtool/src/interrogatedb/py_compat.h +++ b/dtool/src/interrogatedb/py_compat.h @@ -65,7 +65,7 @@ typedef int Py_ssize_t; /* Python 2.6 */ -#ifndef Py_TYPE +#if PY_VERSION_HEX < 0x02060000 # define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) #endif @@ -189,6 +189,20 @@ INLINE PyObject *_PyObject_FastCall(PyObject *func, PyObject **args, Py_ssize_t } while (0) #endif +#if PY_VERSION_HEX < 0x03070000 +INLINE PyObject *PyImport_GetModule(PyObject *name) { + PyObject *modules = PyImport_GetModuleDict(); + if (modules != nullptr) { + PyObject *module = PyDict_GetItem(modules, name); + if (module != nullptr) { + Py_INCREF(module); + return module; + } + } + return nullptr; +} +#endif + /* Python 3.8 */ #if PY_VERSION_HEX < 0x03080000 INLINE PyObject *_PyLong_Rshift(PyObject *a, size_t shiftby) { @@ -207,8 +221,12 @@ INLINE PyObject *_PyLong_Lshift(PyObject *a, size_t shiftby) { /* Python 3.9 */ +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE) +# define Py_IS_TYPE(ob, type) (Py_TYPE((PyObject *)ob) == type) +#endif + #ifndef PyCFunction_CheckExact -# define PyCFunction_CheckExact(op) (Py_TYPE(op) == &PyCFunction_Type) +# define PyCFunction_CheckExact(op) (Py_IS_TYPE(op, &PyCFunction_Type)) #endif #if PY_VERSION_HEX < 0x03090000 @@ -279,6 +297,77 @@ INLINE bool PyLong_IsNonNegative(PyObject *value) { } #endif +/* Python 3.13 */ + +#if PY_VERSION_HEX < 0x030D00A1 +# define PyLong_AsInt(x) (_PyLong_AsInt(x)) +#endif + +#if PY_VERSION_HEX < 0x030D00A1 +ALWAYS_INLINE int +PyModule_Add(PyObject *mod, const char *name, PyObject *value) { + int res = PyModule_AddObjectRef(mod, name, value); + Py_XDECREF(value); + return res; +} +#endif + +#if PY_VERSION_HEX < 0x030D00A1 +INLINE int +PyDict_GetItemRef(PyObject *mp, PyObject *key, PyObject **result) { +#if PY_MAJOR_VERSION >= 3 + PyObject *item = PyDict_GetItemWithError(mp, key); +#else + PyObject *item = _PyDict_GetItemWithError(mp, key); +#endif + if (item != nullptr) { + *result = Py_NewRef(item); + return 1; + } + *result = nullptr; + return PyErr_Occurred() ? -1 : 0; +} + +INLINE int +PyDict_GetItemStringRef(PyObject *mp, const char *key, PyObject **result) { + PyObject *item = nullptr; +#if PY_MAJOR_VERSION >= 3 + PyObject *key_obj = PyUnicode_FromString(key); + item = key_obj ? PyDict_GetItemWithError(mp, key_obj) : nullptr; +#else + PyObject *key_obj = PyString_FromString(key); + item = key_obj ? _PyDict_GetItemWithError(mp, key_obj) : nullptr; +#endif + Py_DECREF(key_obj); + if (item != nullptr) { + *result = Py_NewRef(item); + return 1; + } + *result = nullptr; + return PyErr_Occurred() ? -1 : 0; +} +#endif + +#if PY_VERSION_HEX >= 0x03050200 && PY_VERSION_HEX < 0x030D00A1 +# define PyThreadState_GetUnchecked() (_PyThreadState_UncheckedGet()) +#endif + +#if PY_VERSION_HEX < 0x030D00A2 +# define PyList_Extend(list, iterable) (PyList_SetSlice((list), PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, (iterable))) +# define PyList_Clear(list) (PyList_SetSlice((list), 0, PY_SSIZE_T_MAX, nullptr)) +#endif + +#if PY_VERSION_HEX < 0x030D00A4 +# define PyList_GetItemRef(op, index) (Py_XNewRef(PyList_GetItem((op), (index)))) +#endif + +#if PY_VERSION_HEX < 0x030D00B3 +# define Py_BEGIN_CRITICAL_SECTION(op) { +# define Py_END_CRITICAL_SECTION() } +# define Py_BEGIN_CRITICAL_SECTION2(a, b) { +# define Py_END_CRITICAL_SECTION2() } +#endif + /* Other Python implementations */ #endif // HAVE_PYTHON diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx deleted file mode 100644 index b691fbef48..0000000000 --- a/dtool/src/interrogatedb/py_panda.cxx +++ /dev/null @@ -1,918 +0,0 @@ -/** - * @file py_panda.cxx - * @author drose - * @date 2005-07-04 - */ - -#include "py_panda.h" -#include "config_interrogatedb.h" -#include "executionEnvironment.h" - -#ifdef HAVE_PYTHON - -#define _STRINGIFY_VERSION(a, b) (#a "." #b) -#define STRINGIFY_VERSION(a, b) _STRINGIFY_VERSION(a, b) - -using std::string; - -/** - - */ -void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer) { - if (DtoolInstance_Check(self)) { - *answer = DtoolInstance_UPCAST(self, *classdef); - } else { - *answer = nullptr; - } -} - -/** - * This is a support function for the Python bindings: it extracts the - * underlying C++ pointer of the given type for a given Python object. If it - * was of the wrong type, raises an AttributeError. - */ -bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer) { - if (self == nullptr || !DtoolInstance_Check(self) || DtoolInstance_VOID_PTR(self) == nullptr) { - Dtool_Raise_TypeError("C++ object is not yet constructed, or already destructed."); - return false; - } - - *answer = DtoolInstance_UPCAST(self, classdef); - return true; -} - -/** - * The same thing as Dtool_Call_ExtractThisPointer, except that it performs - * the additional check that the pointer is a non-const pointer. This is - * called by function wrappers for functions of which all overloads are non- - * const, and saves a bit of code. - * - * The extra method_name argument is used in formatting the error message. - */ -bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef, - void **answer, const char *method_name) { - - if (self == nullptr || !DtoolInstance_Check(self) || DtoolInstance_VOID_PTR(self) == nullptr) { - Dtool_Raise_TypeError("C++ object is not yet constructed, or already destructed."); - return false; - } - - if (DtoolInstance_IS_CONST(self)) { - // All overloads of this function are non-const. - PyErr_Format(PyExc_TypeError, - "Cannot call %s() on a const object.", - method_name); - return false; - } - - *answer = DtoolInstance_UPCAST(self, classdef); - return true; -} - -/** - * Extracts the C++ pointer for an object, given its Python wrapper object, - * for passing as the parameter to a C++ function. - * - * self is the Python wrapper object in question. - * - * classdef is the Python class wrapper for the C++ class in which the this - * pointer should be returned. (This may require an upcast operation, if self - * is not already an instance of classdef.) - * - * param and function_name are used for error reporting only, and describe the - * particular function and parameter index for this parameter. - * - * const_ok is true if the function is declared const and can therefore be - * called with either a const or non-const "this" pointer, or false if the - * function is declared non-const, and can therefore be called with only a - * non-const "this" pointer. - * - * The return value is the C++ pointer that was extracted, or NULL if there - * was a problem (in which case the Python exception state will have been - * set). - */ -void * -DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, - int param, const string &function_name, bool const_ok, - bool report_errors) { - // if (PyErr_Occurred()) { return nullptr; } - if (self == nullptr) { - if (report_errors) { - return Dtool_Raise_TypeError("self is nullptr"); - } - return nullptr; - } - - if (DtoolInstance_Check(self)) { - void *result = DtoolInstance_UPCAST(self, *classdef); - - if (result != nullptr) { - if (const_ok || !DtoolInstance_IS_CONST(self)) { - return result; - } - - if (report_errors) { - return PyErr_Format(PyExc_TypeError, - "%s() argument %d may not be const", - function_name.c_str(), param); - } - return nullptr; - } - } - - if (report_errors) { - return Dtool_Raise_ArgTypeError(self, param, function_name.c_str(), classdef->_PyType.tp_name); - } - - return nullptr; -} - -/** - * This is similar to a PyErr_Occurred() check, except that it also checks - * Notify to see if an assertion has occurred. If that is the case, then it - * raises an AssertionError. - * - * Returns true if there is an active exception, false otherwise. - * - * In the NDEBUG case, this is simply a #define to PyErr_Occurred(). - */ -bool _Dtool_CheckErrorOccurred() { - if (PyErr_Occurred()) { - return true; - } - if (Notify::ptr()->has_assert_failed()) { - Dtool_Raise_AssertionError(); - return true; - } - return false; -} - -/** - * Raises an AssertionError containing the last thrown assert message, and - * clears the assertion flag. Returns NULL. - */ -PyObject *Dtool_Raise_AssertionError() { - Notify *notify = Notify::ptr(); -#if PY_MAJOR_VERSION >= 3 - PyObject *message = PyUnicode_FromString(notify->get_assert_error_message().c_str()); -#else - PyObject *message = PyString_FromString(notify->get_assert_error_message().c_str()); -#endif - PyErr_SetObject(PyExc_AssertionError, message); - notify->clear_assert_failed(); - return nullptr; -} - -/** - * Raises a TypeError with the given message, and returns NULL. - */ -PyObject *Dtool_Raise_TypeError(const char *message) { - PyErr_SetString(PyExc_TypeError, message); - return nullptr; -} - -/** - * Raises a TypeError of the form: function_name() argument n must be type, - * not type for a given object passed to a function. - * - * Always returns NULL so that it can be conveniently used as a return - * expression for wrapper functions that return a PyObject pointer. - */ -PyObject *Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name) { -#if PY_MAJOR_VERSION >= 3 - PyObject *message = PyUnicode_FromFormat( -#else - PyObject *message = PyString_FromFormat( -#endif - "%s() argument %d must be %s, not %s", - function_name, param, type_name, - Py_TYPE(obj)->tp_name); - - PyErr_SetObject(PyExc_TypeError, message); - return nullptr; -} - -/** - * Raises an AttributeError of the form: 'type' has no attribute 'attr' - * - * Always returns NULL so that it can be conveniently used as a return - * expression for wrapper functions that return a PyObject pointer. - */ -PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute) { -#if PY_MAJOR_VERSION >= 3 - PyObject *message = PyUnicode_FromFormat( -#else - PyObject *message = PyString_FromFormat( -#endif - "'%.100s' object has no attribute '%.200s'", - Py_TYPE(obj)->tp_name, attribute); - - PyErr_SetObject(PyExc_AttributeError, message); - return nullptr; -} - -/** - * Raises a TypeError of the form: Arguments must match: - * - * However, in release builds, this instead is defined to a function that just - * prints out a generic message, to help reduce the amount of strings in the - * compiled library. - * - * If there is already an exception set, does nothing. - * - * Always returns NULL so that it can be conveniently used as a return - * expression for wrapper functions that return a PyObject pointer. - */ -PyObject *_Dtool_Raise_BadArgumentsError(const char *message) { - if (!PyErr_Occurred()) { - return PyErr_Format(PyExc_TypeError, "Arguments must match:\n%s", message); - } - return nullptr; -} - -/** - * Overload that prints a generic message instead. - */ -PyObject *_Dtool_Raise_BadArgumentsError() { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "arguments do not match any function overload"); - } - return nullptr; -} - -/** - * Overload that returns -1 instead of nullptr. - */ -int _Dtool_Raise_BadArgumentsError_Int(const char *message) { - if (!PyErr_Occurred()) { - PyErr_Format(PyExc_TypeError, "Arguments must match:\n%s", message); - } - return -1; -} - -/** - * Overload that returns -1 instead of nullptr and prints a generic message. - */ -int _Dtool_Raise_BadArgumentsError_Int() { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "arguments do not match any function overload"); - } - return -1; -} - -/** - * Convenience method that checks for exceptions, and if one occurred, returns - * NULL, otherwise Py_None. - */ -PyObject *_Dtool_Return_None() { - if (UNLIKELY(PyErr_Occurred())) { - return nullptr; - } -#ifndef NDEBUG - if (UNLIKELY(Notify::ptr()->has_assert_failed())) { - return Dtool_Raise_AssertionError(); - } -#endif - return Py_NewRef(Py_None); -} - -/** - * Convenience method that checks for exceptions, and if one occurred, returns - * NULL, otherwise the given boolean value as a PyObject *. - */ -PyObject *Dtool_Return_Bool(bool value) { - if (UNLIKELY(PyErr_Occurred())) { - return nullptr; - } -#ifndef NDEBUG - if (UNLIKELY(Notify::ptr()->has_assert_failed())) { - return Dtool_Raise_AssertionError(); - } -#endif - return Py_NewRef(value ? Py_True : Py_False); -} - -/** - * Convenience method that checks for exceptions, and if one occurred, returns - * NULL, otherwise the given return value. Its reference count is not - * increased. - */ -PyObject *_Dtool_Return(PyObject *value) { - if (UNLIKELY(PyErr_Occurred())) { - return nullptr; - } -#ifndef NDEBUG - if (UNLIKELY(Notify::ptr()->has_assert_failed())) { - return Dtool_Raise_AssertionError(); - } -#endif - return value; -} - -#if PY_VERSION_HEX < 0x03040000 -/** - * This function converts an int value to the appropriate enum instance. - */ -static PyObject *Dtool_EnumType_New(PyTypeObject *subtype, PyObject *args, PyObject *kwds) { - PyObject *arg; - if (!Dtool_ExtractArg(&arg, args, kwds, "value")) { - return PyErr_Format(PyExc_TypeError, - "%s() missing 1 required argument: 'value'", - subtype->tp_name); - } - - if (Py_TYPE(arg) == subtype) { - return Py_NewRef(arg); - } - - PyObject *value2member = PyDict_GetItemString(subtype->tp_dict, "_value2member_map_"); - nassertr_always(value2member != nullptr, nullptr); - - PyObject *member = PyDict_GetItem(value2member, arg); - if (member != nullptr) { - return Py_NewRef(member); - } - - PyObject *repr = PyObject_Repr(arg); - PyErr_Format(PyExc_ValueError, "%s is not a valid %s", -#if PY_MAJOR_VERSION >= 3 - PyUnicode_AS_STRING(repr), -#else - PyString_AS_STRING(repr), -#endif - subtype->tp_name); - Py_DECREF(repr); - return nullptr; -} - -static PyObject *Dtool_EnumType_Str(PyObject *self) { - PyObject *name = PyObject_GetAttrString(self, "name"); -#if PY_MAJOR_VERSION >= 3 - PyObject *repr = PyUnicode_FromFormat("%s.%s", Py_TYPE(self)->tp_name, PyString_AS_STRING(name)); -#else - PyObject *repr = PyString_FromFormat("%s.%s", Py_TYPE(self)->tp_name, PyString_AS_STRING(name)); -#endif - Py_DECREF(name); - return repr; -} - -static PyObject *Dtool_EnumType_Repr(PyObject *self) { - PyObject *name = PyObject_GetAttrString(self, "name"); - PyObject *value = PyObject_GetAttrString(self, "value"); -#if PY_MAJOR_VERSION >= 3 - PyObject *repr = PyUnicode_FromFormat("<%s.%s: %ld>", Py_TYPE(self)->tp_name, PyString_AS_STRING(name), PyLongOrInt_AS_LONG(value)); -#else - PyObject *repr = PyString_FromFormat("<%s.%s: %ld>", Py_TYPE(self)->tp_name, PyString_AS_STRING(name), PyLongOrInt_AS_LONG(value)); -#endif - Py_DECREF(name); - Py_DECREF(value); - return repr; -} -#endif - -/** - * Creates a Python 3.4-style enum type. Steals reference to 'names', which - * should be a tuple of (name, value) pairs. - */ -PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names, const char *module) { - static PyObject *enum_class = nullptr; -#if PY_VERSION_HEX >= 0x03040000 - static PyObject *enum_meta = nullptr; - static PyObject *enum_create = nullptr; - if (enum_meta == nullptr) { - PyObject *enum_module = PyImport_ImportModule("enum"); - nassertr_always(enum_module != nullptr, nullptr); - - enum_class = PyObject_GetAttrString(enum_module, "Enum"); - enum_meta = PyObject_GetAttrString(enum_module, "EnumMeta"); - enum_create = PyObject_GetAttrString(enum_meta, "_create_"); - nassertr(enum_meta != nullptr, nullptr); - } - - PyObject *result = PyObject_CallFunction(enum_create, (char *)"OsN", enum_class, name, names); - nassertr(result != nullptr, nullptr); -#else - static PyObject *name_str; - static PyObject *name_sunder_str; - static PyObject *value_str; - static PyObject *value_sunder_str; - static PyObject *value2member_map_sunder_str; - // Emulate something vaguely like the enum module. - if (enum_class == nullptr) { -#if PY_MAJOR_VERSION >= 3 - name_str = PyUnicode_InternFromString("name"); - value_str = PyUnicode_InternFromString("value"); - name_sunder_str = PyUnicode_InternFromString("_name_"); - value_sunder_str = PyUnicode_InternFromString("_value_"); - value2member_map_sunder_str = PyUnicode_InternFromString("_value2member_map_"); -#else - name_str = PyString_InternFromString("name"); - value_str = PyString_InternFromString("value"); - name_sunder_str = PyString_InternFromString("_name_"); - value_sunder_str = PyString_InternFromString("_value_"); - value2member_map_sunder_str = PyString_InternFromString("_value2member_map_"); -#endif - PyObject *name_value_tuple = PyTuple_New(4); - PyTuple_SET_ITEM(name_value_tuple, 0, Py_NewRef(name_str)); - PyTuple_SET_ITEM(name_value_tuple, 1, Py_NewRef(value_str)); - PyTuple_SET_ITEM(name_value_tuple, 2, name_sunder_str); - PyTuple_SET_ITEM(name_value_tuple, 3, value_sunder_str); - - PyObject *slots_dict = PyDict_New(); - PyDict_SetItemString(slots_dict, "__slots__", name_value_tuple); - Py_DECREF(name_value_tuple); - - enum_class = PyObject_CallFunction((PyObject *)&PyType_Type, (char *)"s()N", "Enum", slots_dict); - nassertr(enum_class != nullptr, nullptr); - } - - // Create a subclass of this generic Enum class we just created. - PyObject *value2member = PyDict_New(); - PyObject *dict = PyDict_New(); - PyDict_SetItem(dict, value2member_map_sunder_str, value2member); - PyObject *result = PyObject_CallFunction((PyObject *)&PyType_Type, (char *)"s(O)N", name, enum_class, dict); - nassertr(result != nullptr, nullptr); - - ((PyTypeObject *)result)->tp_new = Dtool_EnumType_New; - ((PyTypeObject *)result)->tp_str = Dtool_EnumType_Str; - ((PyTypeObject *)result)->tp_repr = Dtool_EnumType_Repr; - - PyObject *empty_tuple = PyTuple_New(0); - - // Copy the names as instances of the above to the class dict, and create a - // reverse mapping in the _value2member_map_ dict. - Py_ssize_t size = PyTuple_GET_SIZE(names); - for (Py_ssize_t i = 0; i < size; ++i) { - PyObject *item = PyTuple_GET_ITEM(names, i); - PyObject *name = PyTuple_GET_ITEM(item, 0); - PyObject *value = PyTuple_GET_ITEM(item, 1); - PyObject *member = PyType_GenericNew((PyTypeObject *)result, empty_tuple, nullptr); - PyObject_SetAttr(member, name_str, name); - PyObject_SetAttr(member, name_sunder_str, name); - PyObject_SetAttr(member, value_str, value); - PyObject_SetAttr(member, value_sunder_str, value); - PyObject_SetAttr(result, name, member); - PyDict_SetItem(value2member, value, member); - Py_DECREF(member); - } - Py_DECREF(names); - Py_DECREF(value2member); - Py_DECREF(empty_tuple); -#endif - - if (module != nullptr) { - PyObject *modstr = PyUnicode_FromString(module); - PyObject_SetAttrString(result, "__module__", modstr); - Py_DECREF(modstr); - } - nassertr(PyType_Check(result), nullptr); - return (PyTypeObject *)result; -} - -/** - - */ -PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &known_class_type, bool memory_rules, bool is_const, int type_index) { - // We can't do the NULL check here like in DTool_CreatePyInstance, since the - // caller will have to get the type index to pass to this function to begin - // with. That code probably would have crashed by now if it was really NULL - // for whatever reason. - nassertr(local_this_in != nullptr, nullptr); - - // IF the class is possibly a run time typed object - if (type_index > 0) { - // get best fit class... - Dtool_PyInstDef *self = (Dtool_PyInstDef *)TypeHandle::from_index(type_index).wrap_python(local_this_in, &known_class_type._PyType); - if (self != nullptr) { - self->_memory_rules = memory_rules; - self->_is_const = is_const; - return (PyObject *)self; - } - } - - // if we get this far .. just wrap the thing in the known type ?? better - // than aborting...I guess.... - Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&known_class_type._PyType, 0); - if (self != nullptr) { - self->_signature = PY_PANDA_SIGNATURE; - self->_My_Type = &known_class_type; - self->_ptr_to_object = local_this_in; - self->_memory_rules = memory_rules; - self->_is_const = is_const; - } - return (PyObject *)self; -} - -// DTool_CreatePyInstance .. wrapper function to finalize the existance of a -// general dtool py instance.. -PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_classdef, bool memory_rules, bool is_const) { - if (local_this == nullptr) { - // This is actually a very common case, so let's allow this, but return - // Py_None consistently. This eliminates code in the wrappers. - return Py_NewRef(Py_None); - } - - Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&in_classdef._PyType, 0); - if (self != nullptr) { - self->_signature = PY_PANDA_SIGNATURE; - self->_My_Type = &in_classdef; - self->_ptr_to_object = local_this; - self->_memory_rules = memory_rules; - self->_is_const = is_const; - self->_My_Type = &in_classdef; - } - return (PyObject *)self; -} - -/** - * Returns a borrowed reference to the global type dictionary. - */ -Dtool_TypeMap *Dtool_GetGlobalTypeMap() { - PyObject *capsule = PySys_GetObject((char *)"_interrogate_types"); - if (capsule != nullptr) { - return (Dtool_TypeMap *)PyCapsule_GetPointer(capsule, nullptr); - } else { - Dtool_TypeMap *type_map = new Dtool_TypeMap; - capsule = PyCapsule_New((void *)type_map, nullptr, nullptr); - PySys_SetObject((char *)"_interrogate_types", capsule); - Py_DECREF(capsule); - return type_map; - } -} - -/** - * - */ -void DtoolProxy_Init(DtoolProxy *proxy, PyObject *self, - Dtool_PyTypedObject &classdef, - TypeRegistry::PythonWrapFunc *wrap_func) { - if (proxy == nullptr) { - // Out of memory, the generated code will handle this. - return; - } - - proxy->_self = Py_NewRef(self); - PyTypeObject *cls = Py_TYPE(self); - if (cls != &classdef._PyType) { - TypeRegistry *registry = TypeRegistry::ptr(); - TypeHandle handle = registry->register_dynamic_type(cls->tp_name); - registry->record_derivation(handle, classdef._type); - //TODO unregister type when it is unloaded? weak callback? - PyTypeObject *cls_ref = (PyTypeObject *)Py_NewRef((PyObject *)cls); - registry->record_python_type(handle, cls_ref, wrap_func); - proxy->_type = handle; - } else { - proxy->_type = classdef._type; - } -} - -#define PY_MAJOR_VERSION_STR #PY_MAJOR_VERSION "." #PY_MINOR_VERSION - -#if PY_MAJOR_VERSION >= 3 -PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], PyModuleDef *module_def) { -#else -PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], const char *modulename) { -#endif - // Check the version so we can print a helpful error if it doesn't match. - string version = Py_GetVersion(); - size_t version_len = version.find('.', 2); - if (version_len != string::npos) { - version.resize(version_len); - } - - if (version != STRINGIFY_VERSION(PY_MAJOR_VERSION, PY_MINOR_VERSION)) { - // Raise a helpful error message. We can safely do this because the - // signature and behavior for PyErr_SetString has remained consistent. - std::ostringstream errs; - errs << "this module was compiled for Python " - << PY_MAJOR_VERSION << "." << PY_MINOR_VERSION << ", which is " - << "incompatible with Python " << version; - string error = errs.str(); - PyErr_SetString(PyExc_ImportError, error.c_str()); - return nullptr; - } - - Dtool_TypeMap *type_map = Dtool_GetGlobalTypeMap(); - - // the module level function inits.... - MethodDefmap functions; - for (size_t i = 0; defs[i] != nullptr; i++) { - const LibraryDef &def = *defs[i]; - - // Accumulate method definitions. - for (PyMethodDef *meth = def._methods; meth->ml_name != nullptr; meth++) { - if (functions.find(meth->ml_name) == functions.end()) { - functions[meth->ml_name] = meth; - } - } - - // Define exported types. - const Dtool_TypeDef *types = def._types; - if (types != nullptr) { - while (types->name != nullptr) { - (*type_map)[std::string(types->name)] = types->type; - ++types; - } - } - } - - // Resolve external types, in a second pass. - for (size_t i = 0; defs[i] != nullptr; i++) { - const LibraryDef &def = *defs[i]; - - Dtool_TypeDef *types = def._external_types; - if (types != nullptr) { - while (types->name != nullptr) { - auto it = type_map->find(std::string(types->name)); - if (it != type_map->end()) { - types->type = it->second; - } else { - return PyErr_Format(PyExc_NameError, "name '%s' is not defined", types->name); - } - ++types; - } - } - } - - PyMethodDef *newdef = new PyMethodDef[functions.size() + 1]; - MethodDefmap::iterator mi; - int offset = 0; - for (mi = functions.begin(); mi != functions.end(); mi++, offset++) { - newdef[offset] = *mi->second; - } - newdef[offset].ml_doc = nullptr; - newdef[offset].ml_name = nullptr; - newdef[offset].ml_meth = nullptr; - newdef[offset].ml_flags = 0; - -#if PY_MAJOR_VERSION >= 3 - module_def->m_methods = newdef; - PyObject *module = PyModule_Create(module_def); -#else - PyObject *module = Py_InitModule((char *)modulename, newdef); -#endif - - if (module == nullptr) { -#if PY_MAJOR_VERSION >= 3 - return Dtool_Raise_TypeError("PyModule_Create returned NULL"); -#else - return Dtool_Raise_TypeError("Py_InitModule returned NULL"); -#endif - } - - // MAIN_DIR needs to be set very early; this seems like a convenient place - // to do that. Perhaps we'll find a better place for this in the future. - static bool initialized_main_dir = false; - if (!initialized_main_dir) { - if (interrogatedb_cat.is_debug()) { - // Good opportunity to print this out once, at startup. - interrogatedb_cat.debug() - << "Python " << version << "\n"; - } - - if (!ExecutionEnvironment::has_environment_variable("MAIN_DIR")) { - // Grab the __main__ module. - PyObject *main_module = PyImport_ImportModule("__main__"); - if (main_module == NULL) { - interrogatedb_cat.warning() << "Unable to import __main__\n"; - } - - // Extract the __file__ attribute, if present. - Filename main_dir; - PyObject *file_attr = nullptr; - if (main_module != nullptr) { - file_attr = PyObject_GetAttrString(main_module, "__file__"); - } - if (file_attr == nullptr) { - // Must be running in the interactive interpreter. Use the CWD. - main_dir = ExecutionEnvironment::get_cwd(); - } else { -#if PY_MAJOR_VERSION >= 3 - Py_ssize_t length; - wchar_t *buffer = PyUnicode_AsWideCharString(file_attr, &length); - if (buffer != nullptr) { - main_dir = Filename::from_os_specific_w(std::wstring(buffer, length)); - main_dir.make_absolute(); - main_dir = main_dir.get_dirname(); - PyMem_Free(buffer); - } -#else - char *buffer; - Py_ssize_t length; - if (PyString_AsStringAndSize(file_attr, &buffer, &length) != -1) { - main_dir = Filename::from_os_specific(std::string(buffer, length)); - main_dir.make_absolute(); - main_dir = main_dir.get_dirname(); - } -#endif - else { - interrogatedb_cat.warning() << "Invalid string for __main__.__file__\n"; - } - } - ExecutionEnvironment::shadow_environment_variable("MAIN_DIR", main_dir.to_os_specific()); - PyErr_Clear(); - } - initialized_main_dir = true; - - // Also, while we are at it, initialize the thread swap hook. -#if defined(HAVE_THREADS) && defined(SIMPLE_THREADS) - global_thread_state_swap = PyThreadState_Swap; -#endif - } - - PyModule_AddIntConstant(module, "Dtool_PyNativeInterface", 1); - return module; -} - -// HACK.... Be careful Dtool_BorrowThisReference This function can be used to -// grab the "THIS" pointer from an object and use it Required to support -// historical inheritance in the form of "is this instance of".. -PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args) { - PyObject *from_in = nullptr; - PyObject *to_in = nullptr; - if (PyArg_UnpackTuple(args, "Dtool_BorrowThisReference", 2, 2, &to_in, &from_in)) { - - if (DtoolInstance_Check(from_in) && DtoolInstance_Check(to_in)) { - Dtool_PyInstDef *from = (Dtool_PyInstDef *) from_in; - Dtool_PyInstDef *to = (Dtool_PyInstDef *) to_in; - - // if (PyObject_TypeCheck(to_in, Py_TYPE(from_in))) { - if (from->_My_Type == to->_My_Type) { - to->_memory_rules = false; - to->_is_const = from->_is_const; - to->_ptr_to_object = from->_ptr_to_object; - - return Py_NewRef(Py_None); - } - - return PyErr_Format(PyExc_TypeError, "types %s and %s do not match", - Py_TYPE(from)->tp_name, Py_TYPE(to)->tp_name); - } else { - return Dtool_Raise_TypeError("One of these does not appear to be DTOOL Instance ??"); - } - } - return nullptr; -} - -// We do expose a dictionay for dtool classes .. this should be removed at -// some point.. -EXPCL_PYPANDA PyObject * -Dtool_AddToDictionary(PyObject *self1, PyObject *args) { - PyObject *self; - PyObject *subject; - PyObject *key; - if (PyArg_ParseTuple(args, "OSO", &self, &key, &subject)) { - PyObject *dict = ((PyTypeObject *)self)->tp_dict; - if (dict == nullptr || !PyDict_Check(dict)) { - return Dtool_Raise_TypeError("No dictionary On Object"); - } else { - PyDict_SetItem(dict, key, subject); - } - } - if (PyErr_Occurred()) { - return nullptr; - } - return Py_NewRef(Py_None); -} - -/** - * This is a support function for a synthesized __copy__() method from a C++ - * make_copy() method. - */ -PyObject *copy_from_make_copy(PyObject *self, PyObject *noargs) { - PyObject *callable = PyObject_GetAttrString(self, "make_copy"); - if (callable == nullptr) { - return nullptr; - } - PyObject *result = PyObject_CallNoArgs(callable); - Py_DECREF(callable); - return result; -} - -/** - * This is a support function for a synthesized __copy__() method from a C++ - * copy constructor. - */ -PyObject *copy_from_copy_constructor(PyObject *self, PyObject *noargs) { - PyObject *callable = (PyObject *)Py_TYPE(self); - return PyObject_CallOneArg(callable, self); -} - -/** - * This is a support function for a synthesized __deepcopy__() method for any - * class that has a __copy__() method. The sythethic method simply invokes - * __copy__(). - */ -PyObject *map_deepcopy_to_copy(PyObject *self, PyObject *args) { - PyObject *callable = PyObject_GetAttrString(self, "__copy__"); - if (callable == nullptr) { - return nullptr; - } - PyObject *result = PyObject_CallNoArgs(callable); - Py_DECREF(callable); - return result; -} - -/** - * A more efficient version of PyArg_ParseTupleAndKeywords for the special - * case where there is only a single PyObject argument. - */ -bool Dtool_ExtractArg(PyObject **result, PyObject *args, PyObject *kwds, - const char *keyword) { - - if (PyTuple_GET_SIZE(args) == 1) { - if (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0) { - *result = PyTuple_GET_ITEM(args, 0); - return true; - } - } - else if (!keyword || !keyword[0]) { - return false; - } - else if (PyTuple_GET_SIZE(args) == 0) { - PyObject *key; - Py_ssize_t ppos = 0; - if (kwds != nullptr && PyDict_GET_SIZE(kwds) == 1 && - PyDict_Next(kwds, &ppos, &key, result)) { - // We got the item, we just need to make sure that it had the right key. -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_CheckExact(key) && PyUnicode_CompareWithASCIIString(key, keyword) == 0; -#else - return PyString_CheckExact(key) && strcmp(PyString_AS_STRING(key), keyword) == 0; -#endif - } - } - - return false; -} - -/** - * Variant of Dtool_ExtractArg that does not accept a keyword argument. - */ -bool Dtool_ExtractArg(PyObject **result, PyObject *args, PyObject *kwds) { - if (PyTuple_GET_SIZE(args) == 1 && - (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0)) { - *result = PyTuple_GET_ITEM(args, 0); - return true; - } - return false; -} - -/** - * A more efficient version of PyArg_ParseTupleAndKeywords for the special - * case where there is only a single optional PyObject argument. - * - * Returns true if valid (including if there were 0 items), false if there was - * an error, such as an invalid number of parameters. - */ -bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, PyObject *kwds, - const char *keyword) { - - if (PyTuple_GET_SIZE(args) == 1) { - if (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0) { - *result = PyTuple_GET_ITEM(args, 0); - return true; - } - } - else if (!keyword || !keyword[0]) { - return (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0); - } - else if (PyTuple_GET_SIZE(args) == 0) { - if (kwds != nullptr && PyDict_GET_SIZE(kwds) == 1) { - PyObject *key; - Py_ssize_t ppos = 0; - if (!PyDict_Next(kwds, &ppos, &key, result)) { - return true; - } - - // We got the item, we just need to make sure that it had the right key. -#if PY_VERSION_HEX >= 0x03060000 - return PyUnicode_CheckExact(key) && _PyUnicode_EqualToASCIIString(key, keyword); -#elif PY_MAJOR_VERSION >= 3 - return PyUnicode_CheckExact(key) && PyUnicode_CompareWithASCIIString(key, keyword) == 0; -#else - return PyString_CheckExact(key) && strcmp(PyString_AS_STRING(key), keyword) == 0; -#endif - } else { - return true; - } - } - - return false; -} - -/** - * Variant of Dtool_ExtractOptionalArg that does not accept a keyword argument. - */ -bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, PyObject *kwds) { - if (kwds != nullptr && PyDict_GET_SIZE(kwds) != 0) { - return false; - } - if (PyTuple_GET_SIZE(args) == 1) { - *result = PyTuple_GET_ITEM(args, 0); - return true; - } - return (PyTuple_GET_SIZE(args) == 0); -} - -#endif // HAVE_PYTHON diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index ca79501601..d57af784f7 100644 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -16,6 +16,7 @@ #include "pnotify.h" #include "vector_uchar.h" #include "register_type.h" +#include "interrogate_request.h" #if defined(HAVE_PYTHON) && !defined(CPPPARSER) @@ -181,7 +182,14 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\ // forward declared of typed object. We rely on the fact that typed objects // are uniquly defined by an integer. +#if PY_VERSION_HEX >= 0x030d0000 +class Dtool_TypeMap : public std::map { +public: + PyMutex _lock { 0 }; +}; +#else typedef std::map Dtool_TypeMap; +#endif EXPCL_PYPANDA Dtool_TypeMap *Dtool_GetGlobalTypeMap(); @@ -338,6 +346,7 @@ struct LibraryDef { PyMethodDef *const _methods; const Dtool_TypeDef *const _types; Dtool_TypeDef *const _external_types; + const InterrogateModuleDef *const _module_def; }; #if PY_MAJOR_VERSION >= 3 diff --git a/dtool/src/interrogatedb/py_wrappers.cxx b/dtool/src/interrogatedb/py_wrappers.cxx deleted file mode 100644 index f0be01a3fb..0000000000 --- a/dtool/src/interrogatedb/py_wrappers.cxx +++ /dev/null @@ -1,1778 +0,0 @@ -/** - * @file py_wrappers.cxx - * @author rdb - * @date 2017-11-26 - */ - -#include "py_wrappers.h" - -#ifdef HAVE_PYTHON - -#if PY_VERSION_HEX >= 0x03040000 -#define _COLLECTIONS_ABC "_collections_abc" -#elif PY_VERSION_HEX >= 0x03030000 -#define _COLLECTIONS_ABC "collections.abc" -#else -#define _COLLECTIONS_ABC "_abcoll" -#endif - -static void _register_collection(PyTypeObject *type, const char *abc) { - PyObject *sys_modules = PyImport_GetModuleDict(); - if (sys_modules != nullptr) { - PyObject *module = PyDict_GetItemString(sys_modules, _COLLECTIONS_ABC); - if (module != nullptr) { - PyObject *dict = PyModule_GetDict(module); - if (module != nullptr) { -#if PY_MAJOR_VERSION >= 3 - static PyObject *register_str = PyUnicode_InternFromString("register"); -#else - static PyObject *register_str = PyString_InternFromString("register"); -#endif - PyObject *sequence = PyDict_GetItemString(dict, abc); - if (sequence != nullptr) { - if (PyObject_CallMethodOneArg(sequence, register_str, (PyObject *)type) == nullptr) { - PyErr_Print(); - } - } - } - } - } -} - -/** - * These classes are returned from properties that require a subscript - * interface, ie. something.children[i] = 3. - */ -static void Dtool_WrapperBase_dealloc(PyObject *self) { - Dtool_WrapperBase *wrap = (Dtool_WrapperBase *)self; - nassertv(wrap); - Py_XDECREF(wrap->_self); - Py_TYPE(self)->tp_free(self); -} - -static PyObject *Dtool_WrapperBase_repr(PyObject *self) { - Dtool_WrapperBase *wrap = (Dtool_WrapperBase *)self; - nassertr(wrap, nullptr); - - PyObject *repr = PyObject_Repr(wrap->_self); - PyObject *result; -#if PY_MAJOR_VERSION >= 3 - result = PyUnicode_FromFormat("<%s[] of %s>", wrap->_name, PyUnicode_AsUTF8(repr)); -#else - result = PyString_FromFormat("<%s[] of %s>", wrap->_name, PyString_AS_STRING(repr)); -#endif - Py_DECREF(repr); - return result; -} - -static PyObject *Dtool_SequenceWrapper_repr(PyObject *self) { - Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self; - nassertr(wrap, nullptr); - - Py_ssize_t len = -1; - if (wrap->_len_func != nullptr) { - len = wrap->_len_func(wrap->_base._self); - } - - if (len < 0) { - PyErr_Clear(); - return Dtool_WrapperBase_repr(self); - } - - PyObject *repr = PyObject_Repr(wrap->_base._self); - PyObject *result; -#if PY_MAJOR_VERSION >= 3 - result = PyUnicode_FromFormat("<%s[%zd] of %s>", wrap->_base._name, len, PyUnicode_AsUTF8(repr)); -#else - result = PyString_FromFormat("<%s[%zd] of %s>", wrap->_base._name, len, PyString_AS_STRING(repr)); -#endif - Py_DECREF(repr); - return result; -} - -static Py_ssize_t Dtool_SequenceWrapper_length(PyObject *self) { - Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self; - nassertr(wrap, -1); - if (wrap->_len_func != nullptr) { - return wrap->_len_func(wrap->_base._self); - } else { - Dtool_Raise_TypeError("property does not support len()"); - return -1; - } -} - -static PyObject *Dtool_SequenceWrapper_getitem(PyObject *self, Py_ssize_t index) { - Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self; - nassertr(wrap, nullptr); - nassertr(wrap->_getitem_func, nullptr); - return wrap->_getitem_func(wrap->_base._self, index); -} - -/** - * Implementation of (x in property) - */ -static int Dtool_SequenceWrapper_contains(PyObject *self, PyObject *value) { - Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self; - nassertr(wrap, -1); - nassertr(wrap->_len_func, -1); - nassertr(wrap->_getitem_func, -1); - - Py_ssize_t length = wrap->_len_func(wrap->_base._self); - - // Iterate through the items, invoking the equality function for each, until - // we have found the matching one. - for (Py_ssize_t index = 0; index < length; ++index) { - PyObject *item = wrap->_getitem_func(wrap->_base._self, index); - if (item != nullptr) { - int cmp = PyObject_RichCompareBool(item, value, Py_EQ); - if (cmp > 0) { - return 1; - } - if (cmp < 0) { - return -1; - } - } else { - return -1; - } - } - return 0; -} - -/** - * Implementation of property.index(x) which returns the index of the first - * occurrence of x in the sequence, or raises a ValueError if it isn't found. - */ -static PyObject *Dtool_SequenceWrapper_index(PyObject *self, PyObject *value) { - Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self; - nassertr(wrap, nullptr); - nassertr(wrap->_len_func, nullptr); - nassertr(wrap->_getitem_func, nullptr); - - Py_ssize_t length = wrap->_len_func(wrap->_base._self); - - // Iterate through the items, invoking the equality function for each, until - // we have found the right one. - for (Py_ssize_t index = 0; index < length; ++index) { - PyObject *item = wrap->_getitem_func(wrap->_base._self, index); - if (item != nullptr) { - int cmp = PyObject_RichCompareBool(item, value, Py_EQ); - if (cmp > 0) { - return Dtool_WrapValue(index); - } - if (cmp < 0) { - return nullptr; - } - } else { - return nullptr; - } - } - // Not found, raise ValueError. - return PyErr_Format(PyExc_ValueError, "%s.index() did not find value", wrap->_base._name); -} - -/** - * Implementation of property.count(x) which returns the number of occurrences - * of x in the sequence. - */ -static PyObject *Dtool_SequenceWrapper_count(PyObject *self, PyObject *value) { - Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self; - nassertr(wrap, nullptr); - Py_ssize_t index = 0; - if (wrap->_len_func != nullptr) { - index = wrap->_len_func(wrap->_base._self); - } else { - return Dtool_Raise_TypeError("property does not support count()"); - } - // Iterate through the items, invoking the == operator for each. - long count = 0; - nassertr(wrap->_getitem_func, nullptr); - while (index > 0) { - --index; - PyObject *item = wrap->_getitem_func(wrap->_base._self, index); - if (item == nullptr) { - return nullptr; - } - int cmp = PyObject_RichCompareBool(item, value, Py_EQ); - if (cmp > 0) { - ++count; - } - if (cmp < 0) { - return nullptr; - } - } -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong(count); -#else - return PyInt_FromLong(count); -#endif -} - -/** - * Implementation of `property[i] = x` - */ -static int Dtool_MutableSequenceWrapper_setitem(PyObject *self, Py_ssize_t index, PyObject *value) { - Dtool_MutableSequenceWrapper *wrap = (Dtool_MutableSequenceWrapper *)self; - nassertr(wrap, -1); - if (wrap->_setitem_func != nullptr) { - return wrap->_setitem_func(wrap->_base._self, index, value); - } else { - Dtool_Raise_TypeError("property does not support item assignment"); - return -1; - } -} - -/** - * Implementation of property.clear() which removes all elements in the - * sequence, starting with the last. - */ -static PyObject *Dtool_MutableSequenceWrapper_clear(PyObject *self, PyObject *) { - Dtool_MutableSequenceWrapper *wrap = (Dtool_MutableSequenceWrapper *)self; - nassertr(wrap, nullptr); - Py_ssize_t index = 0; - if (wrap->_len_func != nullptr && wrap->_setitem_func != nullptr) { - index = wrap->_len_func(wrap->_base._self); - } else { - return Dtool_Raise_TypeError("property does not support clear()"); - } - - // Iterate through the items, invoking the delete function for each. We do - // this in reverse order, which may be more efficient. - while (index > 0) { - --index; - if (wrap->_setitem_func(wrap->_base._self, index, nullptr) != 0) { - return nullptr; - } - } - return Py_NewRef(Py_None); -} - -/** - * Implementation of property.remove(x) which removes the first occurrence of - * x in the sequence, or raises a ValueError if it isn't found. - */ -static PyObject *Dtool_MutableSequenceWrapper_remove(PyObject *self, PyObject *value) { - Dtool_MutableSequenceWrapper *wrap = (Dtool_MutableSequenceWrapper *)self; - nassertr(wrap, nullptr); - Py_ssize_t length = 0; - if (wrap->_len_func != nullptr && wrap->_setitem_func != nullptr) { - length = wrap->_len_func(wrap->_base._self); - } else { - return Dtool_Raise_TypeError("property does not support remove()"); - } - - // Iterate through the items, invoking the equality function for each, until - // we have found the right one. - nassertr(wrap->_getitem_func, nullptr); - for (Py_ssize_t index = 0; index < length; ++index) { - PyObject *item = wrap->_getitem_func(wrap->_base._self, index); - if (item != nullptr) { - int cmp = PyObject_RichCompareBool(item, value, Py_EQ); - if (cmp > 0) { - if (wrap->_setitem_func(wrap->_base._self, index, nullptr) == 0) { - return Py_NewRef(Py_None); - } else { - return nullptr; - } - } - if (cmp < 0) { - return nullptr; - } - } else { - return nullptr; - } - } - // Not found, raise ValueError. - return PyErr_Format(PyExc_ValueError, "%s.remove() did not find value", wrap->_base._name); -} - -/** - * Implementation of property.pop([i=-1]) which returns and removes the - * element at the indicated index in the sequence. If no index is provided, - * it removes from the end of the list. - */ -static PyObject *Dtool_MutableSequenceWrapper_pop(PyObject *self, PyObject *args) { - Dtool_MutableSequenceWrapper *wrap = (Dtool_MutableSequenceWrapper *)self; - nassertr(wrap, nullptr); - if (wrap->_getitem_func == nullptr || wrap->_setitem_func == nullptr || - wrap->_len_func == nullptr) { - return Dtool_Raise_TypeError("property does not support pop()"); - } - - Py_ssize_t length = wrap->_len_func(wrap->_base._self); - Py_ssize_t index; - switch (PyTuple_GET_SIZE(args)) { - case 0: - index = length - 1; - break; - case 1: - index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(args, 0), PyExc_IndexError); - if (index == -1 && PyErr_Occurred()) { - return nullptr; - } - if (index < 0) { - index += length; - } - break; - default: - return Dtool_Raise_TypeError("pop([i=-1]) takes 0 or 1 arguments"); - } - - if (length <= 0) { - return PyErr_Format(PyExc_IndexError, "%s.pop() from empty sequence", wrap->_base._name); - } - - // Index error will be caught by getitem_func. - PyObject *value = wrap->_getitem_func(wrap->_base._self, index); - if (value != nullptr) { - if (wrap->_setitem_func(wrap->_base._self, index, nullptr) != 0) { - return nullptr; - } - return value; - } - return nullptr; -} - -/** - * Implementation of property.append(x) which is an alias for - * property.insert(len(property), x). - */ -static PyObject *Dtool_MutableSequenceWrapper_append(PyObject *self, PyObject *arg) { - Dtool_MutableSequenceWrapper *wrap = (Dtool_MutableSequenceWrapper *)self; - nassertr(wrap, nullptr); - if (wrap->_insert_func == nullptr) { - return Dtool_Raise_TypeError("property does not support append()"); - } - return wrap->_insert_func(wrap->_base._self, (size_t)-1, arg); -} - -/** - * Implementation of property.insert(i, x) which inserts the given item at the - * given position. - */ -static PyObject *Dtool_MutableSequenceWrapper_insert(PyObject *self, PyObject *args) { - Dtool_MutableSequenceWrapper *wrap = (Dtool_MutableSequenceWrapper *)self; - nassertr(wrap, nullptr); - if (wrap->_insert_func == nullptr) { - return Dtool_Raise_TypeError("property does not support insert()"); - } - if (PyTuple_GET_SIZE(args) != 2) { - return Dtool_Raise_TypeError("insert() takes exactly 2 arguments"); - } - Py_ssize_t index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(args, 0), PyExc_IndexError); - if (index == -1 && PyErr_Occurred()) { - return nullptr; - } - if (index < 0) { - if (wrap->_len_func != nullptr) { - index += wrap->_len_func(wrap->_base._self); - } else { - return PyErr_Format(PyExc_TypeError, "%s.insert() does not support negative indices", wrap->_base._name); - } - } - return wrap->_insert_func(wrap->_base._self, (size_t)std::max(index, (Py_ssize_t)0), PyTuple_GET_ITEM(args, 1)); -} - -/** - * Implementation of property.extend(seq) which is equivalent to: - * @code - * for x in seq: - * property.append(seq) - * @endcode - */ -static PyObject *Dtool_MutableSequenceWrapper_extend(PyObject *self, PyObject *arg) { - Dtool_MutableSequenceWrapper *wrap = (Dtool_MutableSequenceWrapper *)self; - nassertr(wrap, nullptr); - if (wrap->_insert_func == nullptr) { - return Dtool_Raise_TypeError("property does not support extend()"); - } - PyObject *iter = PyObject_GetIter(arg); - if (iter == nullptr) { - return nullptr; - } - PyObject *next = PyIter_Next(iter); - PyObject *retval = nullptr; - while (next != nullptr) { - retval = wrap->_insert_func(wrap->_base._self, (size_t)-1, next); - Py_DECREF(next); - if (retval == nullptr) { - Py_DECREF(iter); - return nullptr; - } - Py_DECREF(retval); - next = PyIter_Next(iter); - } - - Py_DECREF(iter); - return Py_NewRef(Py_None); -} - -/** - * Implementation of `x in mapping`. - */ -static int Dtool_MappingWrapper_contains(PyObject *self, PyObject *key) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, -1); - nassertr(wrap->_getitem_func, -1); - PyObject *value = wrap->_getitem_func(wrap->_base._self, key); - if (value != nullptr) { - Py_DECREF(value); - return 1; - } else if (PyErr_ExceptionMatches(PyExc_KeyError) || - PyErr_ExceptionMatches(PyExc_TypeError)) { - PyErr_Clear(); - return 0; - } else { - return -1; - } -} - -static PyObject *Dtool_MappingWrapper_getitem(PyObject *self, PyObject *key) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - nassertr(wrap->_getitem_func, nullptr); - return wrap->_getitem_func(wrap->_base._self, key); -} - -/** - * Implementation of iter(property) that returns an iterable over all the - * keys. - */ -static PyObject *Dtool_MappingWrapper_iter(PyObject *self) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - - if (wrap->_keys._len_func == nullptr || wrap->_keys._getitem_func == nullptr) { - return PyErr_Format(PyExc_TypeError, "%s is not iterable", wrap->_base._name); - } - - Dtool_SequenceWrapper *keys = Dtool_NewSequenceWrapper(wrap->_base._self, wrap->_base._name); - if (keys != nullptr) { - keys->_len_func = wrap->_keys._len_func; - keys->_getitem_func = wrap->_keys._getitem_func; - return PySeqIter_New((PyObject *)keys); - } else { - return nullptr; - } -} - -/** - * Implementation of property.get(key[,def=None]) which returns the value with - * the given key in the mapping, or the given default value (which defaults to - * None) if the key isn't found in the mapping. - */ -static PyObject *Dtool_MappingWrapper_get(PyObject *self, PyObject *args) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - nassertr(wrap->_getitem_func, nullptr); - Py_ssize_t size = PyTuple_GET_SIZE(args); - if (size != 1 && size != 2) { - return PyErr_Format(PyExc_TypeError, "%s.get() takes 1 or 2 arguments", wrap->_base._name); - } - PyObject *defvalue = Py_None; - if (size >= 2) { - defvalue = PyTuple_GET_ITEM(args, 1); - } - PyObject *key = PyTuple_GET_ITEM(args, 0); - PyObject *value = wrap->_getitem_func(wrap->_base._self, key); - if (value != nullptr) { - return value; - } else if (PyErr_ExceptionMatches(PyExc_KeyError)) { - PyErr_Clear(); - return Py_NewRef(defvalue); - } else { - return nullptr; - } -} - -/** - * This is returned by mapping.keys(). - */ -static PyObject *Dtool_MappingWrapper_Keys_repr(PyObject *self) { - Dtool_WrapperBase *wrap = (Dtool_WrapperBase *)self; - nassertr(wrap, nullptr); - - PyObject *repr = PyObject_Repr(wrap->_self); - PyObject *result; -#if PY_MAJOR_VERSION >= 3 - result = PyUnicode_FromFormat("<%s.keys() of %s>", wrap->_name, PyUnicode_AsUTF8(repr)); -#else - result = PyString_FromFormat("<%s.keys() of %s>", wrap->_name, PyString_AS_STRING(repr)); -#endif - Py_DECREF(repr); - return result; -} - -/** - * Implementation of property.keys(...) that returns a view of all the keys. - */ -static PyObject *Dtool_MappingWrapper_keys(PyObject *self, PyObject *) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - - if (wrap->_keys._len_func == nullptr || wrap->_keys._getitem_func == nullptr) { - return Dtool_Raise_TypeError("property does not support keys()"); - } - - Dtool_MappingWrapper *keys = (Dtool_MappingWrapper *)PyObject_MALLOC(sizeof(Dtool_MappingWrapper)); - if (keys == nullptr) { - return PyErr_NoMemory(); - } - - static PySequenceMethods seq_methods = { - Dtool_SequenceWrapper_length, - nullptr, // sq_concat - nullptr, // sq_repeat - Dtool_SequenceWrapper_getitem, - nullptr, // sq_slice - nullptr, // sq_ass_item - nullptr, // sq_ass_slice - Dtool_SequenceWrapper_contains, - nullptr, // sq_inplace_concat - nullptr, // sq_inplace_repeat - }; - - static PyTypeObject wrapper_type = { - PyVarObject_HEAD_INIT(nullptr, 0) - "sequence wrapper", - sizeof(Dtool_SequenceWrapper), - 0, // tp_itemsize - Dtool_WrapperBase_dealloc, - 0, // tp_vectorcall_offset - nullptr, // tp_getattr - nullptr, // tp_setattr - nullptr, // tp_compare - Dtool_MappingWrapper_Keys_repr, - nullptr, // tp_as_number - &seq_methods, - nullptr, // tp_as_mapping - nullptr, // tp_hash - nullptr, // tp_call - nullptr, // tp_str - PyObject_GenericGetAttr, - PyObject_GenericSetAttr, - nullptr, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, - nullptr, // tp_doc - nullptr, // tp_traverse - nullptr, // tp_clear - nullptr, // tp_richcompare - 0, // tp_weaklistoffset - PySeqIter_New, - nullptr, // tp_iternext - nullptr, // tp_methods - nullptr, // tp_members - nullptr, // tp_getset - nullptr, // tp_base - nullptr, // tp_dict - nullptr, // tp_descr_get - nullptr, // tp_descr_set - 0, // tp_dictoffset - nullptr, // tp_init - PyType_GenericAlloc, - nullptr, // tp_new - PyObject_Del, - nullptr, // tp_is_gc - nullptr, // tp_bases - nullptr, // tp_mro - nullptr, // tp_cache - nullptr, // tp_subclasses - nullptr, // tp_weaklist - nullptr, // tp_del - 0, // tp_version_tag, -#if PY_VERSION_HEX >= 0x03040000 - nullptr, // tp_finalize -#endif -#if PY_VERSION_HEX >= 0x03080000 - nullptr, // tp_vectorcall -#endif - }; - - static bool registered = false; - if (!registered) { - registered = true; - - if (PyType_Ready(&wrapper_type) < 0) { - return nullptr; - } - - // If the collections.abc module is loaded, register this as a subclass. - _register_collection((PyTypeObject *)&wrapper_type, "MappingView"); - } - - (void)PyObject_INIT(keys, &wrapper_type); - keys->_base._self = Py_XNewRef(wrap->_base._self); - keys->_base._name = wrap->_base._name; - keys->_keys._len_func = wrap->_keys._len_func; - keys->_keys._getitem_func = wrap->_keys._getitem_func; - keys->_getitem_func = wrap->_getitem_func; - keys->_setitem_func = nullptr; - return (PyObject *)keys; -} - -/** - * This is returned by mapping.values(). - */ -static PyObject *Dtool_MappingWrapper_Values_repr(PyObject *self) { - Dtool_WrapperBase *wrap = (Dtool_WrapperBase *)self; - nassertr(wrap, nullptr); - - PyObject *repr = PyObject_Repr(wrap->_self); - PyObject *result; -#if PY_MAJOR_VERSION >= 3 - result = PyUnicode_FromFormat("<%s.values() of %s>", wrap->_name, PyUnicode_AsUTF8(repr)); -#else - result = PyString_FromFormat("<%s.values() of %s>", wrap->_name, PyString_AS_STRING(repr)); -#endif - Py_DECREF(repr); - return result; -} - -static PyObject *Dtool_MappingWrapper_Values_getitem(PyObject *self, Py_ssize_t index) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - nassertr(wrap->_keys._getitem_func, nullptr); - - PyObject *key = wrap->_keys._getitem_func(wrap->_base._self, index); - if (key != nullptr) { - PyObject *value = wrap->_getitem_func(wrap->_base._self, key); - Py_DECREF(key); - return value; - } - return nullptr; -} - -/** - * Implementation of property.values(...) that returns a view of the values. - */ -static PyObject *Dtool_MappingWrapper_values(PyObject *self, PyObject *) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - nassertr(wrap->_getitem_func, nullptr); - - if (wrap->_keys._len_func == nullptr || wrap->_keys._getitem_func == nullptr) { - return Dtool_Raise_TypeError("property does not support values()"); - } - - Dtool_MappingWrapper *values = (Dtool_MappingWrapper *)PyObject_MALLOC(sizeof(Dtool_MappingWrapper)); - if (values == nullptr) { - return PyErr_NoMemory(); - } - - static PySequenceMethods seq_methods = { - Dtool_SequenceWrapper_length, - nullptr, // sq_concat - nullptr, // sq_repeat - Dtool_MappingWrapper_Values_getitem, - nullptr, // sq_slice - nullptr, // sq_ass_item - nullptr, // sq_ass_slice - Dtool_MappingWrapper_contains, - nullptr, // sq_inplace_concat - nullptr, // sq_inplace_repeat - }; - - static PyTypeObject wrapper_type = { - PyVarObject_HEAD_INIT(nullptr, 0) - "sequence wrapper", - sizeof(Dtool_MappingWrapper), - 0, // tp_itemsize - Dtool_WrapperBase_dealloc, - 0, // tp_vectorcall_offset - nullptr, // tp_getattr - nullptr, // tp_setattr - nullptr, // tp_compare - Dtool_MappingWrapper_Values_repr, - nullptr, // tp_as_number - &seq_methods, - nullptr, // tp_as_mapping - nullptr, // tp_hash - nullptr, // tp_call - nullptr, // tp_str - PyObject_GenericGetAttr, - PyObject_GenericSetAttr, - nullptr, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, - nullptr, // tp_doc - nullptr, // tp_traverse - nullptr, // tp_clear - nullptr, // tp_richcompare - 0, // tp_weaklistoffset - PySeqIter_New, - nullptr, // tp_iternext - nullptr, // tp_methods - nullptr, // tp_members - nullptr, // tp_getset - nullptr, // tp_base - nullptr, // tp_dict - nullptr, // tp_descr_get - nullptr, // tp_descr_set - 0, // tp_dictoffset - nullptr, // tp_init - PyType_GenericAlloc, - nullptr, // tp_new - PyObject_Del, - nullptr, // tp_is_gc - nullptr, // tp_bases - nullptr, // tp_mro - nullptr, // tp_cache - nullptr, // tp_subclasses - nullptr, // tp_weaklist - nullptr, // tp_del - 0, // tp_version_tag, -#if PY_VERSION_HEX >= 0x03040000 - nullptr, // tp_finalize -#endif -#if PY_VERSION_HEX >= 0x03080000 - nullptr, // tp_vectorcall -#endif - }; - - static bool registered = false; - if (!registered) { - registered = true; - - if (PyType_Ready(&wrapper_type) < 0) { - return nullptr; - } - - // If the collections.abc module is loaded, register this as a subclass. - _register_collection((PyTypeObject *)&wrapper_type, "ValuesView"); - } - - (void)PyObject_INIT(values, &wrapper_type); - values->_base._self = Py_XNewRef(wrap->_base._self); - values->_base._name = wrap->_base._name; - values->_keys._len_func = wrap->_keys._len_func; - values->_keys._getitem_func = wrap->_keys._getitem_func; - values->_getitem_func = wrap->_getitem_func; - values->_setitem_func = nullptr; - return (PyObject *)values; -} - -/** - * This is returned by mapping.items(). - */ -static PyObject *Dtool_MappingWrapper_Items_repr(PyObject *self) { - Dtool_WrapperBase *wrap = (Dtool_WrapperBase *)self; - nassertr(wrap, nullptr); - - PyObject *repr = PyObject_Repr(wrap->_self); - PyObject *result; -#if PY_MAJOR_VERSION >= 3 - result = PyUnicode_FromFormat("<%s.items() of %s>", wrap->_name, PyUnicode_AsUTF8(repr)); -#else - result = PyString_FromFormat("<%s.items() of %s>", wrap->_name, PyString_AS_STRING(repr)); -#endif - Py_DECREF(repr); - return result; -} - -static PyObject *Dtool_MappingWrapper_Items_getitem(PyObject *self, Py_ssize_t index) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - nassertr(wrap->_keys._getitem_func, nullptr); - - PyObject *key = wrap->_keys._getitem_func(wrap->_base._self, index); - if (key != nullptr) { - PyObject *value = wrap->_getitem_func(wrap->_base._self, key); - if (value != nullptr) { - // PyTuple_SET_ITEM steals the reference. - PyObject *item = PyTuple_New(2); - PyTuple_SET_ITEM(item, 0, key); - PyTuple_SET_ITEM(item, 1, value); - return item; - } else { - Py_DECREF(key); - } - } - return nullptr; -} - -/** - * Implementation of property.items(...) that returns an iterable yielding a - * `(key, value)` tuple for every item. - */ -static PyObject *Dtool_MappingWrapper_items(PyObject *self, PyObject *) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - nassertr(wrap->_getitem_func, nullptr); - - if (wrap->_keys._len_func == nullptr || wrap->_keys._getitem_func == nullptr) { - return Dtool_Raise_TypeError("property does not support items()"); - } - - Dtool_MappingWrapper *items = (Dtool_MappingWrapper *)PyObject_MALLOC(sizeof(Dtool_MappingWrapper)); - if (items == nullptr) { - return PyErr_NoMemory(); - } - - static PySequenceMethods seq_methods = { - Dtool_SequenceWrapper_length, - nullptr, // sq_concat - nullptr, // sq_repeat - Dtool_MappingWrapper_Items_getitem, - nullptr, // sq_slice - nullptr, // sq_ass_item - nullptr, // sq_ass_slice - Dtool_MappingWrapper_contains, - nullptr, // sq_inplace_concat - nullptr, // sq_inplace_repeat - }; - - static PyTypeObject wrapper_type = { - PyVarObject_HEAD_INIT(nullptr, 0) - "sequence wrapper", - sizeof(Dtool_MappingWrapper), - 0, // tp_itemsize - Dtool_WrapperBase_dealloc, - 0, // tp_vectorcall_offset - nullptr, // tp_getattr - nullptr, // tp_setattr - nullptr, // tp_compare - Dtool_MappingWrapper_Items_repr, - nullptr, // tp_as_number - &seq_methods, - nullptr, // tp_as_mapping - nullptr, // tp_hash - nullptr, // tp_call - nullptr, // tp_str - PyObject_GenericGetAttr, - PyObject_GenericSetAttr, - nullptr, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, - nullptr, // tp_doc - nullptr, // tp_traverse - nullptr, // tp_clear - nullptr, // tp_richcompare - 0, // tp_weaklistoffset - PySeqIter_New, - nullptr, // tp_iternext - nullptr, // tp_methods - nullptr, // tp_members - nullptr, // tp_getset - nullptr, // tp_base - nullptr, // tp_dict - nullptr, // tp_descr_get - nullptr, // tp_descr_set - 0, // tp_dictoffset - nullptr, // tp_init - PyType_GenericAlloc, - nullptr, // tp_new - PyObject_Del, - nullptr, // tp_is_gc - nullptr, // tp_bases - nullptr, // tp_mro - nullptr, // tp_cache - nullptr, // tp_subclasses - nullptr, // tp_weaklist - nullptr, // tp_del - 0, // tp_version_tag, -#if PY_VERSION_HEX >= 0x03040000 - nullptr, // tp_finalize -#endif -#if PY_VERSION_HEX >= 0x03080000 - nullptr, // tp_vectorcall -#endif - }; - - static bool registered = false; - if (!registered) { - registered = true; - - if (PyType_Ready(&wrapper_type) < 0) { - return nullptr; - } - - // If the collections.abc module is loaded, register this as a subclass. - _register_collection((PyTypeObject *)&wrapper_type, "MappingView"); - } - - (void)PyObject_INIT(items, &wrapper_type); - items->_base._self = Py_XNewRef(wrap->_base._self); - items->_base._name = wrap->_base._name; - items->_keys._len_func = wrap->_keys._len_func; - items->_keys._getitem_func = wrap->_keys._getitem_func; - items->_getitem_func = wrap->_getitem_func; - items->_setitem_func = nullptr; - return (PyObject *)items; -} - -/** - * Implementation of `property[key] = value` - */ -static int Dtool_MutableMappingWrapper_setitem(PyObject *self, PyObject *key, PyObject *value) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap->_setitem_func != nullptr, -1); - return wrap->_setitem_func(wrap->_base._self, key, value); -} - -/** - * Implementation of property.pop(key[,def=None]) which is the same as get() - * except that it also removes the element from the mapping. - */ -static PyObject *Dtool_MutableMappingWrapper_pop(PyObject *self, PyObject *args) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - if (wrap->_getitem_func == nullptr || wrap->_setitem_func == nullptr) { - return Dtool_Raise_TypeError("property does not support pop()"); - } - - Py_ssize_t size = PyTuple_GET_SIZE(args); - if (size != 1 && size != 2) { - return PyErr_Format(PyExc_TypeError, "%s.pop() takes 1 or 2 arguments", wrap->_base._name); - } - PyObject *defvalue = Py_None; - if (size >= 2) { - defvalue = PyTuple_GET_ITEM(args, 1); - } - - PyObject *key = PyTuple_GET_ITEM(args, 0); - PyObject *value = wrap->_getitem_func(wrap->_base._self, key); - if (value != nullptr) { - // OK, now set unset this value. - if (wrap->_setitem_func(wrap->_base._self, key, nullptr) == 0) { - return value; - } else { - Py_DECREF(value); - return nullptr; - } - } else if (PyErr_ExceptionMatches(PyExc_KeyError)) { - PyErr_Clear(); - return Py_NewRef(defvalue); - } else { - return nullptr; - } -} - -/** - * Implementation of property.popitem() which returns and removes an arbitrary - * (key, value) pair from the mapping. Useful for destructive iteration. - */ -static PyObject *Dtool_MutableMappingWrapper_popitem(PyObject *self, PyObject *) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - if (wrap->_getitem_func == nullptr || wrap->_setitem_func == nullptr || - wrap->_keys._len_func == nullptr || wrap->_keys._getitem_func == nullptr) { - return Dtool_Raise_TypeError("property does not support popitem()"); - } - - Py_ssize_t length = wrap->_keys._len_func(wrap->_base._self); - if (length < 1) { - return PyErr_Format(PyExc_KeyError, "%s is empty", wrap->_base._name); - } - - PyObject *key = wrap->_keys._getitem_func(wrap->_base._self, length - 1); - if (key != nullptr) { - PyObject *value = wrap->_getitem_func(wrap->_base._self, key); - if (value != nullptr) { - // OK, now set unset this value. - if (wrap->_setitem_func(wrap->_base._self, key, nullptr) == 0) { - PyObject *item = PyTuple_New(2); - PyTuple_SET_ITEM(item, 0, key); - PyTuple_SET_ITEM(item, 1, value); - return item; - } - Py_DECREF(value); - } - } - return nullptr; -} - -/* - * Implementation of property.clear() which removes all elements in the - * mapping. - */ -static PyObject *Dtool_MutableMappingWrapper_clear(PyObject *self, PyObject *) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - Py_ssize_t index = 0; - if (wrap->_keys._len_func != nullptr && wrap->_keys._getitem_func != nullptr && - wrap->_setitem_func != nullptr) { - index = wrap->_keys._len_func(wrap->_base._self); - } else { - return Dtool_Raise_TypeError("property does not support clear()"); - } - - // Iterate through the items, invoking the delete function for each. We do - // this in reverse order, which may be more efficient. - while (index > 0) { - --index; - PyObject *key = wrap->_keys._getitem_func(wrap->_base._self, index); - if (key != nullptr) { - int result = wrap->_setitem_func(wrap->_base._self, key, nullptr); - Py_DECREF(key); - if (result != 0) { - return nullptr; - } - } - } - return Py_NewRef(Py_None); -} - -/** - * Implementation of property.setdefault(key[,def=None]) which is the same as - * get() except that it also writes the default value back to the mapping if - * the key was not found is missing. - */ -static PyObject *Dtool_MutableMappingWrapper_setdefault(PyObject *self, PyObject *args) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - - if (wrap->_getitem_func == nullptr || wrap->_setitem_func == nullptr) { - return Dtool_Raise_TypeError("property does not support setdefault()"); - } - - Py_ssize_t size = PyTuple_GET_SIZE(args); - if (size != 1 && size != 2) { - return PyErr_Format(PyExc_TypeError, "%s.setdefault() takes 1 or 2 arguments", wrap->_base._name); - } - PyObject *defvalue = Py_None; - if (size >= 2) { - defvalue = PyTuple_GET_ITEM(args, 1); - } - PyObject *key = PyTuple_GET_ITEM(args, 0); - PyObject *value = wrap->_getitem_func(wrap->_base._self, key); - if (value != nullptr) { - return value; - } else if (PyErr_ExceptionMatches(PyExc_KeyError)) { - PyErr_Clear(); - if (wrap->_setitem_func(wrap->_base._self, key, defvalue) == 0) { - return Py_NewRef(defvalue); - } - } - return nullptr; -} - -/** - * Implementation of property.update(...) which sets multiple values in one - * go. It accepts either a single dictionary or keyword arguments, not both. - */ -static PyObject *Dtool_MutableMappingWrapper_update(PyObject *self, PyObject *args, PyObject *kwargs) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self; - nassertr(wrap, nullptr); - - if (wrap->_getitem_func == nullptr || wrap->_setitem_func == nullptr) { - return Dtool_Raise_TypeError("property does not support update()"); - } - - // We accept either a dict argument or keyword arguments, but not both. - PyObject *dict; - switch (PyTuple_GET_SIZE(args)) { - case 0: - if (kwargs == nullptr) { - // This is legal. - return Py_NewRef(Py_None); - } - dict = kwargs; - break; - case 1: - if (PyDict_Check(PyTuple_GET_ITEM(args, 0)) && (kwargs == nullptr || Py_SIZE(kwargs) == 0)) { - dict = PyTuple_GET_ITEM(args, 0); - break; - } - // Fall through - default: - return PyErr_Format(PyExc_TypeError, "%s.update() takes either a dict argument or keyword arguments", wrap->_base._name); - } - - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next(dict, &pos, &key, &value)) { - if (wrap->_setitem_func(wrap->_base._self, key, value) != 0) { - return nullptr; - } - } - return Py_NewRef(Py_None); -} - -/** - * This variant defines only a generator interface. - */ -static PyObject *Dtool_GeneratorWrapper_iternext(PyObject *self) { - Dtool_GeneratorWrapper *wrap = (Dtool_GeneratorWrapper *)self; - nassertr(wrap, nullptr); - nassertr(wrap->_iternext_func, nullptr); - return wrap->_iternext_func(wrap->_base._self); -} - -/** - * This is a variant of the Python getset mechanism that permits static - * properties. - */ -static void -Dtool_StaticProperty_dealloc(PyDescrObject *descr) { -#if PY_VERSION_HEX >= 0x03080000 - PyObject_GC_UnTrack(descr); -#else - _PyObject_GC_UNTRACK(descr); -#endif - Py_XDECREF(descr->d_type); - Py_XDECREF(descr->d_name); -//#if PY_MAJOR_VERSION >= 3 -// Py_XDECREF(descr->d_qualname); -//#endif - PyObject_GC_Del(descr); -} - -static PyObject * -Dtool_StaticProperty_repr(PyDescrObject *descr, const char *format) { -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromFormat("", - PyUnicode_AsUTF8(descr->d_name), - descr->d_type->tp_name); -#else - return PyString_FromFormat("", - PyString_AS_STRING(descr->d_name), - descr->d_type->tp_name); -#endif -} - -static int -Dtool_StaticProperty_traverse(PyObject *self, visitproc visit, void *arg) { - PyDescrObject *descr = (PyDescrObject *)self; - Py_VISIT(descr->d_type); - return 0; -} - -static PyObject * -Dtool_StaticProperty_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) { - if (descr->d_getset->get != nullptr) { - return descr->d_getset->get(obj, descr->d_getset->closure); - } else { - return PyErr_Format(PyExc_AttributeError, - "attribute '%s' of type '%.100s' is not readable", -#if PY_MAJOR_VERSION >= 3 - PyUnicode_AsUTF8(((PyDescrObject *)descr)->d_name), -#else - PyString_AS_STRING(((PyDescrObject *)descr)->d_name), -#endif - ((PyDescrObject *)descr)->d_type->tp_name); - } -} - -static int -Dtool_StaticProperty_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) { - if (descr->d_getset->set != nullptr) { - return descr->d_getset->set(obj, value, descr->d_getset->closure); - } else { - PyErr_Format(PyExc_AttributeError, - "attribute '%s' of type '%.100s' is not writable", -#if PY_MAJOR_VERSION >= 3 - PyUnicode_AsUTF8(((PyDescrObject *)descr)->d_name), -#else - PyString_AS_STRING(((PyDescrObject *)descr)->d_name), -#endif - ((PyDescrObject *)descr)->d_type->tp_name); - return -1; - } -} - -/** - * This wraps around a property that exposes a sequence interface. - */ -Dtool_SequenceWrapper *Dtool_NewSequenceWrapper(PyObject *self, const char *name) { - Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)PyObject_MALLOC(sizeof(Dtool_SequenceWrapper)); - if (wrap == nullptr) { - return (Dtool_SequenceWrapper *)PyErr_NoMemory(); - } - - static PySequenceMethods seq_methods = { - Dtool_SequenceWrapper_length, - nullptr, // sq_concat - nullptr, // sq_repeat - Dtool_SequenceWrapper_getitem, - nullptr, // sq_slice - nullptr, // sq_ass_item - nullptr, // sq_ass_slice - Dtool_SequenceWrapper_contains, - nullptr, // sq_inplace_concat - nullptr, // sq_inplace_repeat - }; - - static PyMethodDef methods[] = { - {"index", &Dtool_SequenceWrapper_index, METH_O, nullptr}, - {"count", &Dtool_SequenceWrapper_count, METH_O, nullptr}, - {nullptr, nullptr, 0, nullptr} - }; - - static PyTypeObject wrapper_type = { - PyVarObject_HEAD_INIT(nullptr, 0) - "sequence wrapper", - sizeof(Dtool_SequenceWrapper), - 0, // tp_itemsize - Dtool_WrapperBase_dealloc, - 0, // tp_vectorcall_offset - nullptr, // tp_getattr - nullptr, // tp_setattr - nullptr, // tp_compare - Dtool_SequenceWrapper_repr, - nullptr, // tp_as_number - &seq_methods, - nullptr, // tp_as_mapping - nullptr, // tp_hash - nullptr, // tp_call - nullptr, // tp_str - PyObject_GenericGetAttr, - PyObject_GenericSetAttr, - nullptr, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, - nullptr, // tp_doc - nullptr, // tp_traverse - nullptr, // tp_clear - nullptr, // tp_richcompare - 0, // tp_weaklistoffset - PySeqIter_New, - nullptr, // tp_iternext - methods, - nullptr, // tp_members - nullptr, // tp_getset - nullptr, // tp_base - nullptr, // tp_dict - nullptr, // tp_descr_get - nullptr, // tp_descr_set - 0, // tp_dictoffset - nullptr, // tp_init - PyType_GenericAlloc, - nullptr, // tp_new - PyObject_Del, - nullptr, // tp_is_gc - nullptr, // tp_bases - nullptr, // tp_mro - nullptr, // tp_cache - nullptr, // tp_subclasses - nullptr, // tp_weaklist - nullptr, // tp_del - 0, // tp_version_tag, -#if PY_VERSION_HEX >= 0x03040000 - nullptr, // tp_finalize -#endif -#if PY_VERSION_HEX >= 0x03080000 - nullptr, // tp_vectorcall -#endif - }; - - static bool registered = false; - if (!registered) { - registered = true; - - if (PyType_Ready(&wrapper_type) < 0) { - return nullptr; - } - - // If the collections.abc module is loaded, register this as a subclass. - _register_collection((PyTypeObject *)&wrapper_type, "Sequence"); - } - - (void)PyObject_INIT(wrap, &wrapper_type); - wrap->_base._self = Py_XNewRef(self); - wrap->_base._name = name; - wrap->_len_func = nullptr; - wrap->_getitem_func = nullptr; - return wrap; -} - -/** - * This wraps around a property that exposes a mutable sequence interface. - */ -Dtool_MutableSequenceWrapper *Dtool_NewMutableSequenceWrapper(PyObject *self, const char *name) { - Dtool_MutableSequenceWrapper *wrap = (Dtool_MutableSequenceWrapper *)PyObject_MALLOC(sizeof(Dtool_MutableSequenceWrapper)); - if (wrap == nullptr) { - return (Dtool_MutableSequenceWrapper *)PyErr_NoMemory(); - } - - static PySequenceMethods seq_methods = { - Dtool_SequenceWrapper_length, - nullptr, // sq_concat - nullptr, // sq_repeat - Dtool_SequenceWrapper_getitem, - nullptr, // sq_slice - Dtool_MutableSequenceWrapper_setitem, - nullptr, // sq_ass_slice - Dtool_SequenceWrapper_contains, - Dtool_MutableSequenceWrapper_extend, - nullptr, // sq_inplace_repeat - }; - - static PyMethodDef methods[] = { - {"index", &Dtool_SequenceWrapper_index, METH_O, nullptr}, - {"count", &Dtool_SequenceWrapper_count, METH_O, nullptr}, - {"clear", &Dtool_MutableSequenceWrapper_clear, METH_NOARGS, nullptr}, - {"pop", &Dtool_MutableSequenceWrapper_pop, METH_VARARGS, nullptr}, - {"remove", &Dtool_MutableSequenceWrapper_remove, METH_O, nullptr}, - {"append", &Dtool_MutableSequenceWrapper_append, METH_O, nullptr}, - {"insert", &Dtool_MutableSequenceWrapper_insert, METH_VARARGS, nullptr}, - {"extend", &Dtool_MutableSequenceWrapper_extend, METH_O, nullptr}, - {nullptr, nullptr, 0, nullptr} - }; - - static PyTypeObject wrapper_type = { - PyVarObject_HEAD_INIT(nullptr, 0) - "sequence wrapper", - sizeof(Dtool_MutableSequenceWrapper), - 0, // tp_itemsize - Dtool_WrapperBase_dealloc, - 0, // tp_vectorcall_offset - nullptr, // tp_getattr - nullptr, // tp_setattr - nullptr, // tp_compare - Dtool_SequenceWrapper_repr, - nullptr, // tp_as_number - &seq_methods, - nullptr, // tp_as_mapping - nullptr, // tp_hash - nullptr, // tp_call - nullptr, // tp_str - PyObject_GenericGetAttr, - PyObject_GenericSetAttr, - nullptr, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, - nullptr, // tp_doc - nullptr, // tp_traverse - nullptr, // tp_clear - nullptr, // tp_richcompare - 0, // tp_weaklistoffset - PySeqIter_New, - nullptr, // tp_iternext - methods, - nullptr, // tp_members - nullptr, // tp_getset - nullptr, // tp_base - nullptr, // tp_dict - nullptr, // tp_descr_get - nullptr, // tp_descr_set - 0, // tp_dictoffset - nullptr, // tp_init - PyType_GenericAlloc, - nullptr, // tp_new - PyObject_Del, - nullptr, // tp_is_gc - nullptr, // tp_bases - nullptr, // tp_mro - nullptr, // tp_cache - nullptr, // tp_subclasses - nullptr, // tp_weaklist - nullptr, // tp_del - 0, // tp_version_tag, -#if PY_VERSION_HEX >= 0x03040000 - nullptr, // tp_finalize -#endif -#if PY_VERSION_HEX >= 0x03080000 - nullptr, // tp_vectorcall -#endif - }; - - static bool registered = false; - if (!registered) { - registered = true; - - if (PyType_Ready(&wrapper_type) < 0) { - return nullptr; - } - - // If the collections.abc module is loaded, register this as a subclass. - _register_collection((PyTypeObject *)&wrapper_type, "MutableSequence"); - } - - (void)PyObject_INIT(wrap, &wrapper_type); - wrap->_base._self = Py_XNewRef(self); - wrap->_base._name = name; - wrap->_len_func = nullptr; - wrap->_getitem_func = nullptr; - wrap->_setitem_func = nullptr; - wrap->_insert_func = nullptr; - return wrap; -} - -/** - * This wraps around a mapping interface, with getitem function. - */ -Dtool_MappingWrapper *Dtool_NewMappingWrapper(PyObject *self, const char *name) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)PyObject_MALLOC(sizeof(Dtool_MappingWrapper)); - if (wrap == nullptr) { - return (Dtool_MappingWrapper *)PyErr_NoMemory(); - } - - static PySequenceMethods seq_methods = { - Dtool_SequenceWrapper_length, - nullptr, // sq_concat - nullptr, // sq_repeat - nullptr, // sq_item - nullptr, // sq_slice - nullptr, // sq_ass_item - nullptr, // sq_ass_slice - Dtool_MappingWrapper_contains, - nullptr, // sq_inplace_concat - nullptr, // sq_inplace_repeat - }; - - static PyMappingMethods map_methods = { - Dtool_SequenceWrapper_length, - Dtool_MappingWrapper_getitem, - nullptr, // mp_ass_subscript - }; - - static PyMethodDef methods[] = { - {"get", &Dtool_MappingWrapper_get, METH_VARARGS, nullptr}, - {"keys", &Dtool_MappingWrapper_keys, METH_NOARGS, nullptr}, - {"values", &Dtool_MappingWrapper_values, METH_NOARGS, nullptr}, - {"items", &Dtool_MappingWrapper_items, METH_NOARGS, nullptr}, - {nullptr, nullptr, 0, nullptr} - }; - - static PyTypeObject wrapper_type = { - PyVarObject_HEAD_INIT(nullptr, 0) - "mapping wrapper", - sizeof(Dtool_MappingWrapper), - 0, // tp_itemsize - Dtool_WrapperBase_dealloc, - 0, // tp_vectorcall_offset - nullptr, // tp_getattr - nullptr, // tp_setattr - nullptr, // tp_compare - Dtool_WrapperBase_repr, - nullptr, // tp_as_number - &seq_methods, - &map_methods, - nullptr, // tp_hash - nullptr, // tp_call - nullptr, // tp_str - PyObject_GenericGetAttr, - PyObject_GenericSetAttr, - nullptr, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, - nullptr, // tp_doc - nullptr, // tp_traverse - nullptr, // tp_clear - nullptr, // tp_richcompare - 0, // tp_weaklistoffset - Dtool_MappingWrapper_iter, - nullptr, // tp_iternext - methods, - nullptr, // tp_members - nullptr, // tp_getset - nullptr, // tp_base - nullptr, // tp_dict - nullptr, // tp_descr_get - nullptr, // tp_descr_set - 0, // tp_dictoffset - nullptr, // tp_init - PyType_GenericAlloc, - nullptr, // tp_new - PyObject_Del, - nullptr, // tp_is_gc - nullptr, // tp_bases - nullptr, // tp_mro - nullptr, // tp_cache - nullptr, // tp_subclasses - nullptr, // tp_weaklist - nullptr, // tp_del - 0, // tp_version_tag, -#if PY_VERSION_HEX >= 0x03040000 - nullptr, // tp_finalize -#endif -#if PY_VERSION_HEX >= 0x03080000 - nullptr, // tp_vectorcall -#endif - }; - - static bool registered = false; - if (!registered) { - registered = true; - - if (PyType_Ready(&wrapper_type) < 0) { - return nullptr; - } - - // If the collections.abc module is loaded, register this as a subclass. - _register_collection((PyTypeObject *)&wrapper_type, "Mapping"); - } - - (void)PyObject_INIT(wrap, &wrapper_type); - wrap->_base._self = Py_XNewRef(self); - wrap->_base._name = name; - wrap->_keys._len_func = nullptr; - wrap->_keys._getitem_func = nullptr; - wrap->_getitem_func = nullptr; - wrap->_setitem_func = nullptr; - return wrap; -} - -/** - * This wraps around a mapping interface, with getitem/setitem functions. - */ -Dtool_MappingWrapper *Dtool_NewMutableMappingWrapper(PyObject *self, const char *name) { - Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)PyObject_MALLOC(sizeof(Dtool_MappingWrapper)); - if (wrap == nullptr) { - return (Dtool_MappingWrapper *)PyErr_NoMemory(); - } - - static PySequenceMethods seq_methods = { - Dtool_SequenceWrapper_length, - nullptr, // sq_concat - nullptr, // sq_repeat - nullptr, // sq_item - nullptr, // sq_slice - nullptr, // sq_ass_item - nullptr, // sq_ass_slice - Dtool_MappingWrapper_contains, - nullptr, // sq_inplace_concat - nullptr, // sq_inplace_repeat - }; - - static PyMappingMethods map_methods = { - Dtool_SequenceWrapper_length, - Dtool_MappingWrapper_getitem, - Dtool_MutableMappingWrapper_setitem, - }; - - static PyMethodDef methods[] = { - {"get", &Dtool_MappingWrapper_get, METH_VARARGS, nullptr}, - {"pop", &Dtool_MutableMappingWrapper_pop, METH_VARARGS, nullptr}, - {"popitem", &Dtool_MutableMappingWrapper_popitem, METH_NOARGS, nullptr}, - {"clear", &Dtool_MutableMappingWrapper_clear, METH_VARARGS, nullptr}, - {"setdefault", &Dtool_MutableMappingWrapper_setdefault, METH_VARARGS, nullptr}, - {"update", (PyCFunction) &Dtool_MutableMappingWrapper_update, METH_VARARGS | METH_KEYWORDS, nullptr}, - {"keys", &Dtool_MappingWrapper_keys, METH_NOARGS, nullptr}, - {"values", &Dtool_MappingWrapper_values, METH_NOARGS, nullptr}, - {"items", &Dtool_MappingWrapper_items, METH_NOARGS, nullptr}, - {nullptr, nullptr, 0, nullptr} - }; - - static PyTypeObject wrapper_type = { - PyVarObject_HEAD_INIT(nullptr, 0) - "mapping wrapper", - sizeof(Dtool_MappingWrapper), - 0, // tp_itemsize - Dtool_WrapperBase_dealloc, - 0, // tp_vectorcall_offset - nullptr, // tp_getattr - nullptr, // tp_setattr - nullptr, // tp_compare - Dtool_WrapperBase_repr, - nullptr, // tp_as_number - &seq_methods, - &map_methods, - nullptr, // tp_hash - nullptr, // tp_call - nullptr, // tp_str - PyObject_GenericGetAttr, - PyObject_GenericSetAttr, - nullptr, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, - nullptr, // tp_doc - nullptr, // tp_traverse - nullptr, // tp_clear - nullptr, // tp_richcompare - 0, // tp_weaklistoffset - Dtool_MappingWrapper_iter, - nullptr, // tp_iternext - methods, - nullptr, // tp_members - nullptr, // tp_getset - nullptr, // tp_base - nullptr, // tp_dict - nullptr, // tp_descr_get - nullptr, // tp_descr_set - 0, // tp_dictoffset - nullptr, // tp_init - PyType_GenericAlloc, - nullptr, // tp_new - PyObject_Del, - nullptr, // tp_is_gc - nullptr, // tp_bases - nullptr, // tp_mro - nullptr, // tp_cache - nullptr, // tp_subclasses - nullptr, // tp_weaklist - nullptr, // tp_del - 0, // tp_version_tag, -#if PY_VERSION_HEX >= 0x03040000 - nullptr, // tp_finalize -#endif -#if PY_VERSION_HEX >= 0x03080000 - nullptr, // tp_vectorcall -#endif - }; - - static bool registered = false; - if (!registered) { - registered = true; - - if (PyType_Ready(&wrapper_type) < 0) { - return nullptr; - } - - // If the collections.abc module is loaded, register this as a subclass. - _register_collection((PyTypeObject *)&wrapper_type, "MutableMapping"); - } - - (void)PyObject_INIT(wrap, &wrapper_type); - wrap->_base._self = Py_XNewRef(self); - wrap->_base._name = name; - wrap->_keys._len_func = nullptr; - wrap->_keys._getitem_func = nullptr; - wrap->_getitem_func = nullptr; - wrap->_setitem_func = nullptr; - return wrap; -} - -/** - * Creates a generator that invokes a given function with the given self arg. - */ -PyObject * -Dtool_NewGenerator(PyObject *self, iternextfunc gen_next) { - static PyTypeObject wrapper_type = { - PyVarObject_HEAD_INIT(nullptr, 0) - "generator wrapper", - sizeof(Dtool_GeneratorWrapper), - 0, // tp_itemsize - Dtool_WrapperBase_dealloc, - 0, // tp_vectorcall_offset - nullptr, // tp_getattr - nullptr, // tp_setattr - nullptr, // tp_compare - nullptr, // tp_repr - nullptr, // tp_as_number - nullptr, // tp_as_sequence - nullptr, // tp_as_mapping - nullptr, // tp_hash - nullptr, // tp_call - nullptr, // tp_str - PyObject_GenericGetAttr, - PyObject_GenericSetAttr, - nullptr, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, - nullptr, // tp_doc - nullptr, // tp_traverse - nullptr, // tp_clear - nullptr, // tp_richcompare - 0, // tp_weaklistoffset - PyObject_SelfIter, - Dtool_GeneratorWrapper_iternext, - nullptr, // tp_methods - nullptr, // tp_members - nullptr, // tp_getset - nullptr, // tp_base - nullptr, // tp_dict - nullptr, // tp_descr_get - nullptr, // tp_descr_set - 0, // tp_dictoffset - nullptr, // tp_init - PyType_GenericAlloc, - nullptr, // tp_new - PyObject_Del, - nullptr, // tp_is_gc - nullptr, // tp_bases - nullptr, // tp_mro - nullptr, // tp_cache - nullptr, // tp_subclasses - nullptr, // tp_weaklist - nullptr, // tp_del - 0, // tp_version_tag, -#if PY_VERSION_HEX >= 0x03040000 - nullptr, // tp_finalize -#endif -#if PY_VERSION_HEX >= 0x03080000 - nullptr, // tp_vectorcall -#endif - }; - - if (PyType_Ready(&wrapper_type) < 0) { - return nullptr; - } - - Dtool_GeneratorWrapper *gen; - gen = (Dtool_GeneratorWrapper *)PyType_GenericAlloc(&wrapper_type, 0); - if (gen != nullptr) { - gen->_base._self = Py_NewRef(self); - gen->_iternext_func = gen_next; - } - return (PyObject *)gen; -} - -/** - * This is a variant of the Python getset mechanism that permits static - * properties. - */ -PyObject * -Dtool_NewStaticProperty(PyTypeObject *type, const PyGetSetDef *getset) { - static PyTypeObject wrapper_type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "getset_descriptor", - sizeof(PyGetSetDescrObject), - 0, // tp_itemsize - (destructor)Dtool_StaticProperty_dealloc, - 0, // tp_vectorcall_offset - nullptr, // tp_getattr - nullptr, // tp_setattr - nullptr, // tp_reserved - (reprfunc)Dtool_StaticProperty_repr, - nullptr, // tp_as_number - nullptr, // tp_as_sequence - nullptr, // tp_as_mapping - nullptr, // tp_hash - nullptr, // tp_call - nullptr, // tp_str - PyObject_GenericGetAttr, - nullptr, // tp_setattro - nullptr, // tp_as_buffer - Py_TPFLAGS_DEFAULT, - nullptr, // tp_doc - Dtool_StaticProperty_traverse, - nullptr, // tp_clear - nullptr, // tp_richcompare - 0, // tp_weaklistoffset - nullptr, // tp_iter - nullptr, // tp_iternext - nullptr, // tp_methods - nullptr, // tp_members - nullptr, // tp_getset - nullptr, // tp_base - nullptr, // tp_dict - (descrgetfunc)Dtool_StaticProperty_get, - (descrsetfunc)Dtool_StaticProperty_set, - 0, // tp_dictoffset - nullptr, // tp_init - nullptr, // tp_alloc - nullptr, // tp_new - nullptr, // tp_free - nullptr, // tp_is_gc - nullptr, // tp_bases - nullptr, // tp_mro - nullptr, // tp_cache - nullptr, // tp_subclasses - nullptr, // tp_weaklist - nullptr, // tp_del - 0, // tp_version_tag, -#if PY_VERSION_HEX >= 0x03040000 - nullptr, // tp_finalize -#endif -#if PY_VERSION_HEX >= 0x03080000 - nullptr, // tp_vectorcall -#endif - }; - - if (PyType_Ready(&wrapper_type) < 0) { - return nullptr; - } - - PyGetSetDescrObject *descr; - descr = (PyGetSetDescrObject *)PyType_GenericAlloc(&wrapper_type, 0); - if (descr != nullptr) { - Py_XINCREF(type); - descr->d_getset = (PyGetSetDef *)getset; -#if PY_MAJOR_VERSION >= 3 - descr->d_common.d_type = type; - descr->d_common.d_name = PyUnicode_InternFromString(getset->name); -#if PY_VERSION_HEX >= 0x03030000 - descr->d_common.d_qualname = nullptr; -#endif -#else - descr->d_type = type; - descr->d_name = PyString_InternFromString(getset->name); -#endif - } - return (PyObject *)descr; -} - -#endif // HAVE_PYTHON diff --git a/dtool/src/parser-inc/algorithm b/dtool/src/parser-inc/algorithm index 751a8ec2cb..52d538e5f2 100644 --- a/dtool/src/parser-inc/algorithm +++ b/dtool/src/parser-inc/algorithm @@ -25,7 +25,11 @@ namespace std { constexpr const T &min(const T &a, const T &b); template constexpr const T &max(const T &a, const T &b); + + template + void sort(RandomIt first, RandomIt last); + template + void sort(RandomIt first, RandomIt last, Compare comp); } #endif - diff --git a/dtool/src/parser-inc/emscripten/heap.h b/dtool/src/parser-inc/emscripten/heap.h new file mode 100644 index 0000000000..b4047a9fb8 --- /dev/null +++ b/dtool/src/parser-inc/emscripten/heap.h @@ -0,0 +1,9 @@ + +#pragma once + +#include +#include +#include + +#define WASM_PAGE_SIZE 65536 +#define EMSCRIPTEN_PAGE_SIZE WASM_PAGE_SIZE diff --git a/makepanda/installer.nsi b/makepanda/installer.nsi index 2897314b5f..7fc47bc9dd 100644 --- a/makepanda/installer.nsi +++ b/makepanda/installer.nsi @@ -145,7 +145,6 @@ var READABLE File /nonfatal /r "${BUILT}\panda3d\direct${EXT_SUFFIX}" File /nonfatal /r "${BUILT}\panda3d\egg${EXT_SUFFIX}" File /nonfatal /r "${BUILT}\panda3d\fx${EXT_SUFFIX}" - File /nonfatal /r "${BUILT}\panda3d\interrogatedb${EXT_SUFFIX}" File /nonfatal /r "${BUILT}\panda3d\physics${EXT_SUFFIX}" File /nonfatal /r "${BUILT}\panda3d\_rplight${EXT_SUFFIX}" File /nonfatal /r "${BUILT}\panda3d\skel${EXT_SUFFIX}" @@ -383,6 +382,7 @@ SectionGroup "Python modules" SecGroupPython !insertmacro PyBindingSection 3.11-32 .cp311-win32.pyd !insertmacro PyBindingSection 3.12-32 .cp312-win32.pyd !insertmacro PyBindingSection 3.13-32 .cp313-win32.pyd + !insertmacro PyBindingSection 3.14-32 .cp314-win32.pyd !else !insertmacro PyBindingSection 3.5 .cp35-win_amd64.pyd !insertmacro PyBindingSection 3.6 .cp36-win_amd64.pyd @@ -393,6 +393,7 @@ SectionGroup "Python modules" SecGroupPython !insertmacro PyBindingSection 3.11 .cp311-win_amd64.pyd !insertmacro PyBindingSection 3.12 .cp312-win_amd64.pyd !insertmacro PyBindingSection 3.13 .cp313-win_amd64.pyd + !insertmacro PyBindingSection 3.14 .cp314-win_amd64.pyd !endif SectionGroupEnd @@ -504,6 +505,7 @@ Function .onInit !insertmacro MaybeEnablePyBindingSection 3.11-32 !insertmacro MaybeEnablePyBindingSection 3.12-32 !insertmacro MaybeEnablePyBindingSection 3.13-32 + !insertmacro MaybeEnablePyBindingSection 3.14-32 ${EndIf} !else !insertmacro MaybeEnablePyBindingSection 3.5 @@ -516,6 +518,7 @@ Function .onInit !insertmacro MaybeEnablePyBindingSection 3.11 !insertmacro MaybeEnablePyBindingSection 3.12 !insertmacro MaybeEnablePyBindingSection 3.13 + !insertmacro MaybeEnablePyBindingSection 3.14 ${EndIf} !endif @@ -541,6 +544,10 @@ Function .onInit SectionSetFlags ${SecPyBindings3.13} ${SF_RO} SectionSetInstTypes ${SecPyBindings3.13} 0 !endif + !ifdef SecPyBindings3.14 + SectionSetFlags ${SecPyBindings3.14} ${SF_RO} + SectionSetInstTypes ${SecPyBindings3.14} 0 + !endif ${EndUnless} FunctionEnd @@ -845,6 +852,7 @@ Section Uninstall !insertmacro RemovePythonPath 3.11-32 !insertmacro RemovePythonPath 3.12-32 !insertmacro RemovePythonPath 3.13-32 + !insertmacro RemovePythonPath 3.14-32 !else !insertmacro RemovePythonPath 3.5 !insertmacro RemovePythonPath 3.6 @@ -855,6 +863,7 @@ Section Uninstall !insertmacro RemovePythonPath 3.11 !insertmacro RemovePythonPath 3.12 !insertmacro RemovePythonPath 3.13 + !insertmacro RemovePythonPath 3.14 !endif SetDetailsPrint both @@ -926,6 +935,7 @@ SectionEnd !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.11-32} $(DESC_SecPyBindings3.11-32) !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.12-32} $(DESC_SecPyBindings3.12-32) !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.13-32} $(DESC_SecPyBindings3.13-32) + !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.14-32} $(DESC_SecPyBindings3.14-32) !else !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.5} $(DESC_SecPyBindings3.5) !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.6} $(DESC_SecPyBindings3.6) @@ -936,6 +946,7 @@ SectionEnd !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.11} $(DESC_SecPyBindings3.11) !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.12} $(DESC_SecPyBindings3.12) !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.13} $(DESC_SecPyBindings3.13) + !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.14} $(DESC_SecPyBindings3.14) !endif !ifdef INCLUDE_PYVER !insertmacro MUI_DESCRIPTION_TEXT ${SecPython} $(DESC_SecPython) diff --git a/makepanda/installpanda.py b/makepanda/installpanda.py index 6ac2474a50..1d8f4deef9 100644 --- a/makepanda/installpanda.py +++ b/makepanda/installpanda.py @@ -29,6 +29,9 @@ APP_INFO = ( ("pstats", "Panda3D Profiling Tool", ("pstats",), False), ) +EXCLUDE_BINARIES = ["deploy-stub", "deploy-stubw", "run_tests"] + + def WriteApplicationsFile(fname, appinfo, mimeinfo, bindir): fhandle = open(fname, "w") for app, desc, exts, multiple in appinfo: @@ -265,7 +268,7 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built", libdir=GetLibDir( oscmd(f"cp -R -P {outputdir}/lib/{base} {dest_libdir}/panda3d/{base}") for base in os.listdir(outputdir + "/bin"): - if not base.startswith("deploy-stub"): + if base not in EXCLUDE_BINARIES: oscmd(f"cp -R -P {outputdir}/bin/{base} {dest_prefix}/bin/{base}") DeleteVCS(dest_prefix + "/share/panda3d") diff --git a/makepanda/makepackage.py b/makepanda/makepackage.py index 6bfad076c6..26447c9b6d 100755 --- a/makepanda/makepackage.py +++ b/makepanda/makepackage.py @@ -125,6 +125,8 @@ MACOS_SCRIPT_POSTFIX = """\ fi """ +EXCLUDE_BINARIES = ["deploy-stub", "deploy-stubw", "run_tests"] + def MakeInstallerNSIS(version, file, title, installdir, compressor="lzma", **kwargs): outputdir = GetOutputDir() @@ -404,7 +406,7 @@ def MakeInstallerLinux(version, debversion=None, rpmversion=None, rpmrelease=1, # Add the binaries in /usr/bin explicitly to the spec file for base in os.listdir(outputdir + "/bin"): - if not base.startswith("deploy-stub"): + if base not in EXCLUDE_BINARIES: txt += "/usr/bin/%s\n" % (base) # Write out the spec file. @@ -470,7 +472,7 @@ def MakeInstallerOSX(version, python_versions=[], installdir=None, **kwargs): oscmd("install -m 0644 doc/man/*.1 dstroot/tools/usr/local/share/man/man1/") for base in os.listdir(outputdir + "/bin"): - if not base.startswith("deploy-stub"): + if base not in EXCLUDE_BINARIES: binname = ("dstroot/tools/%s/bin/" % installdir) + base # OSX needs the -R argument to copy symbolic links correctly, it doesn't have -d. How weird. oscmd("cp -R " + outputdir + "/bin/" + base + " " + binname) @@ -795,7 +797,7 @@ def MakeInstallerFreeBSD(version, python_versions=[], **kwargs): oscmd("rm -f %s/tmp/python_dep" % outputdir) if "PYTHONVERSION" in SDK: - pyver_nodot = SDK["PYTHONVERSION"][6:].rstrip('dmu').replace('.', '') + pyver_nodot = SDK["PYTHONVERSION"][6:].rstrip('dmut').replace('.', '') else: pyver_nodot = "%d%d" % (sys.version_info[:2]) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 63dbad7c7b..626fd7e909 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -158,7 +158,7 @@ def usage(problem): print(" --everything (enable every third-party lib)") print(" --directx-sdk=X (specify version of DirectX SDK to use: jun2010, aug2009)") print(" --windows-sdk=X (specify Windows SDK version, eg. 7.1, 8.1, 10 or 11. Default is 8.1)") - print(" --msvc-version=X (specify Visual C++ version, eg. 10, 11, 12, 14, 14.1, 14.2, 14.3. Default is 14)") + print(" --msvc-version=X (specify Visual C++ version, eg. 14.1, 14.2, 14.3. Default is 14.1)") print(" --use-icl (experimental setting to use an intel compiler instead of MSVC on Windows)") print("") print("The simplest way to compile panda is to just type:") @@ -269,11 +269,11 @@ def parseopts(args): break elif option == "--" + pkg.lower() + "-incdir": PkgSetCustomLocation(pkg) - IncDirectory(pkg, value) + IncDirectory(pkg, os.path.expanduser(value)) break elif option == "--" + pkg.lower() + "-libdir": PkgSetCustomLocation(pkg) - LibDirectory(pkg, value) + LibDirectory(pkg, os.path.expanduser(value)) break if (option == "--everything" or option.startswith("--use-") or option == "--nothing" or option.startswith("--no-")): @@ -311,8 +311,8 @@ def parseopts(args): if GetTarget() == 'windows': if not MSVC_VERSION: - print("No MSVC version specified. Defaulting to 14 (Visual Studio 2015).") - MSVC_VERSION = (14, 0) + print("No MSVC version specified. Defaulting to 14.1 (Visual Studio 2017).") + MSVC_VERSION = (14, 1) else: try: MSVC_VERSION = tuple(int(d) for d in MSVC_VERSION.split('.'))[:2] @@ -321,12 +321,10 @@ def parseopts(args): except: usage("Invalid setting for --msvc-version") - if MSVC_VERSION < (14, 0): + if MSVC_VERSION < (14, 1): warn_prefix = "%sERROR:%s " % (GetColor("red"), GetColor()) print("=========================================================================") - print(warn_prefix + "Support for MSVC versions before 2015 has been discontinued.") - print(warn_prefix + "For more information, or any questions, please visit:") - print(warn_prefix + " https://github.com/panda3d/panda3d/issues/288") + print(warn_prefix + "Support for MSVC versions before 2017 has been discontinued.") print("=========================================================================") sys.stdout.flush() time.sleep(1.0) @@ -425,6 +423,8 @@ elif target == 'darwin': if arch_tag == 'arm64': PLATFORM = 'macosx-11.0-' + arch_tag + elif sys.version_info >= (3, 13): + PLATFORM = 'macosx-10.13-' + arch_tag else: PLATFORM = 'macosx-10.9-' + arch_tag @@ -565,6 +565,11 @@ if GetHost() == 'windows' and GetTarget() == 'windows': else: COMPILER = "GCC" +# Ensure we've pip-installed interrogate if we need it before setting +# PYTHONHOME, etc. +if not PkgSkip("PYTHON"): + GetInterrogate() + SetupBuildEnvironment(COMPILER) ######################################################################## @@ -1023,12 +1028,14 @@ if (COMPILER=="GCC"): # Python may have been compiled with these requirements. # Is there a cleaner way to check this? LinkFlag("PYTHON", "-s USE_BZIP2=1 -s USE_SQLITE3=1") - if not PkgHasCustomLocation("PYTHON"): + if PkgHasCustomLocation("PYTHON"): + python_libdir = FindLibDirectory("PYTHON") + else: python_libdir = GetThirdpartyDir() + "python/lib" - if os.path.isfile(python_libdir + "/libmpdec.a"): - LibName("PYTHON", python_libdir + "/libmpdec.a") - if os.path.isfile(python_libdir + "/libexpat.a"): - LibName("PYTHON", python_libdir + "/libexpat.a") + + for lib in "libmpdec.a", "libexpat.a", "libHacl_Hash_SHA2.a": + if os.path.isfile(python_libdir + "/" + lib): + LibName("PYTHON", python_libdir + "/" + lib) if GetTarget() == "linux": LibName("PYTHON", "-lutil") @@ -1318,7 +1325,7 @@ def CompileCxx(obj,src,opts): if (COMPILER=="GCC"): if (src.endswith(".c")): cmd = GetCC() +' -fPIC -c -o ' + obj - else: cmd = GetCXX()+' -std=gnu++11 -ftemplate-depth-70 -fPIC -c -o ' + obj + else: cmd = GetCXX()+' -std=gnu++14 -ftemplate-depth-70 -fPIC -c -o ' + obj for (opt, dir) in INCDIRECTORIES: if (opt=="ALWAYS") or (opt in opts): cmd += ' -I' + BracketNameWithQuotes(dir) for (opt, dir) in FRAMEWORKDIRECTORIES: @@ -1730,7 +1737,7 @@ def CompileLink(dll, obj, opts): if "PYTHON" not in opts: pythonv = SDK["PYTHONVERSION"].replace('.', '') if optlevel <= 2: - cmd += ' /NOD:{}d.lib'.format(pythonv) + cmd += ' /NOD:{}_d.lib'.format(pythonv) else: cmd += ' /NOD:{}.lib'.format(pythonv) @@ -1877,6 +1884,8 @@ def CompileLink(dll, obj, opts): if tuple(OSX_ARCHS) == ('arm64',): cmd += " -mmacosx-version-min=11.0" + elif sys.version_info >= (3, 13) and 'PYTHON' in opts: + cmd += " -mmacosx-version-min=10.13" else: cmd += " -mmacosx-version-min=10.9" @@ -1902,7 +1911,6 @@ def CompileLink(dll, obj, opts): elif GetTarget() == 'emscripten': cmd += " -s WARN_ON_UNDEFINED_SYMBOLS=1" if GetOrigExt(dll) == ".exe": - cmd += " --memory-init-file 0" cmd += " -s EXIT_RUNTIME=1" else: @@ -2514,7 +2522,8 @@ def WriteConfigSettings(): dtool_config["PYTHON_FRAMEWORK"] = 'Python' dtool_config["PHAVE_MALLOC_H"] = 'UNDEF' dtool_config["PHAVE_SYS_MALLOC_H"] = '1' - dtool_config["HAVE_OPENAL_FRAMEWORK"] = '1' + if not os.path.isdir(GetThirdpartyDir() + "openal"): + dtool_config["HAVE_OPENAL_FRAMEWORK"] = '1' dtool_config["HAVE_X11"] = 'UNDEF' # We might have X11, but we don't need it. dtool_config["IS_LINUX"] = 'UNDEF' dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF' @@ -2780,7 +2789,8 @@ del_files = ['core.py', 'core.pyc', 'core.pyo', 'direct.py', 'direct.pyc', 'direct.pyo', '_direct.pyd', '_direct.so', 'dtoolconfig.pyd', 'dtoolconfig.so', - 'net.pyd', 'net.so'] + 'net.pyd', 'net.so', + 'interrogatedb.pyd', 'interrogatedb.so'] for basename in del_files: path = os.path.join(GetOutputDir(), 'panda3d', basename) @@ -3517,27 +3527,6 @@ TargetAdd('libp3dtoolconfig.dll', input='p3prc_composite2.obj') TargetAdd('libp3dtoolconfig.dll', input='libp3dtool.dll') TargetAdd('libp3dtoolconfig.dll', opts=['ADVAPI', 'OPENSSL', 'WINGDI', 'WINUSER']) -# -# DIRECTORY: dtool/src/interrogatedb/ -# - -OPTS=['DIR:dtool/src/interrogatedb', 'BUILDING:INTERROGATEDB'] -TargetAdd('p3interrogatedb_composite1.obj', opts=OPTS, input='p3interrogatedb_composite1.cxx') -TargetAdd('p3interrogatedb_composite2.obj', opts=OPTS, input='p3interrogatedb_composite2.cxx') -TargetAdd('libp3interrogatedb.dll', input='p3interrogatedb_composite1.obj') -TargetAdd('libp3interrogatedb.dll', input='p3interrogatedb_composite2.obj') -TargetAdd('libp3interrogatedb.dll', input='libp3dtool.dll') -TargetAdd('libp3interrogatedb.dll', input='libp3dtoolconfig.dll') - -# This used to be called dtoolconfig.pyd, but it just contains the interrogatedb -# stuff, so it has been renamed appropriately. -OPTS=['DIR:dtool/metalibs/dtoolconfig'] -PyTargetAdd('interrogatedb_pydtool.obj', opts=OPTS, input="pydtool.cxx") -PyTargetAdd('interrogatedb.pyd', input='interrogatedb_pydtool.obj') -PyTargetAdd('interrogatedb.pyd', input='libp3dtool.dll') -PyTargetAdd('interrogatedb.pyd', input='libp3dtoolconfig.dll') -PyTargetAdd('interrogatedb.pyd', input='libp3interrogatedb.dll') - # # DIRECTORY: dtool/src/prckeys/ # @@ -4254,7 +4243,6 @@ PyTargetAdd('core.pyd', input='p3display_ext_composite.obj') PyTargetAdd('core.pyd', input='p3collide_ext_composite.obj') PyTargetAdd('core.pyd', input='core_module.obj') -PyTargetAdd('core.pyd', input='libp3interrogatedb.dll') PyTargetAdd('core.pyd', input=COMMON_PANDA_LIBS) PyTargetAdd('core.pyd', opts=['WINSOCK2']) @@ -4294,7 +4282,6 @@ if not PkgSkip("VISION"): PyTargetAdd('vision.pyd', input='vision_module.obj') PyTargetAdd('vision.pyd', input='libp3vision_igate.obj') PyTargetAdd('vision.pyd', input='libp3vision.dll') - PyTargetAdd('vision.pyd', input='libp3interrogatedb.dll') PyTargetAdd('vision.pyd', input=COMMON_PANDA_LIBS) # @@ -4326,7 +4313,6 @@ if not PkgSkip('SKEL'): PyTargetAdd('skel.pyd', input='skel_module.obj') PyTargetAdd('skel.pyd', input='libp3skel_igate.obj') PyTargetAdd('skel.pyd', input='libpandaskel.dll') - PyTargetAdd('skel.pyd', input='libp3interrogatedb.dll') PyTargetAdd('skel.pyd', input=COMMON_PANDA_LIBS) # @@ -4363,7 +4349,6 @@ if not PkgSkip('PANDAFX'): PyTargetAdd('fx.pyd', input='fx_module.obj') PyTargetAdd('fx.pyd', input='libp3distort_igate.obj') PyTargetAdd('fx.pyd', input='libpandafx.dll') - PyTargetAdd('fx.pyd', input='libp3interrogatedb.dll') PyTargetAdd('fx.pyd', input=COMMON_PANDA_LIBS) # @@ -4389,7 +4374,6 @@ if not PkgSkip("VRPN"): PyTargetAdd('vrpn.pyd', input='vrpn_module.obj') PyTargetAdd('vrpn.pyd', input='libp3vrpn_igate.obj') PyTargetAdd('vrpn.pyd', input='libp3vrpn.dll') - PyTargetAdd('vrpn.pyd', input='libp3interrogatedb.dll') PyTargetAdd('vrpn.pyd', input=COMMON_PANDA_LIBS) # @@ -4608,7 +4592,6 @@ if not PkgSkip("EGG"): PyTargetAdd('egg.pyd', input='libp3egg_igate.obj') PyTargetAdd('egg.pyd', input='libp3egg2pg_igate.obj') PyTargetAdd('egg.pyd', input='libpandaegg.dll') - PyTargetAdd('egg.pyd', input='libp3interrogatedb.dll') PyTargetAdd('egg.pyd', input=COMMON_PANDA_LIBS) # @@ -4808,7 +4791,6 @@ if not PkgSkip("ODE"): PyTargetAdd('ode.pyd', input='libpandaode_igate.obj') PyTargetAdd('ode.pyd', input='p3ode_ext_composite.obj') PyTargetAdd('ode.pyd', input='libpandaode.dll') - PyTargetAdd('ode.pyd', input='libp3interrogatedb.dll') PyTargetAdd('ode.pyd', input=COMMON_PANDA_LIBS) PyTargetAdd('ode.pyd', opts=['WINUSER', 'ODE']) @@ -4844,7 +4826,6 @@ if not PkgSkip("BULLET"): PyTargetAdd('bullet.pyd', input='bullet_module.obj') PyTargetAdd('bullet.pyd', input='libpandabullet_igate.obj') PyTargetAdd('bullet.pyd', input='libpandabullet.dll') - PyTargetAdd('bullet.pyd', input='libp3interrogatedb.dll') PyTargetAdd('bullet.pyd', input=COMMON_PANDA_LIBS) PyTargetAdd('bullet.pyd', opts=['WINUSER', 'BULLET']) @@ -4910,7 +4891,6 @@ if not PkgSkip("PANDAPHYSICS"): if not PkgSkip("PANDAPARTICLESYSTEM"): PyTargetAdd('physics.pyd', input='libp3particlesystem_igate.obj') PyTargetAdd('physics.pyd', input='libpandaphysics.dll') - PyTargetAdd('physics.pyd', input='libp3interrogatedb.dll') PyTargetAdd('physics.pyd', input=COMMON_PANDA_LIBS) # @@ -5225,7 +5205,6 @@ if not PkgSkip("DIRECT"): PyTargetAdd('direct.pyd', input='direct_module.obj') PyTargetAdd('direct.pyd', input='libp3direct.dll') - PyTargetAdd('direct.pyd', input='libp3interrogatedb.dll') PyTargetAdd('direct.pyd', input=COMMON_PANDA_LIBS) PyTargetAdd('direct.pyd', opts=['WINUSER', 'WINGDI', 'WINSOCK2']) @@ -6098,7 +6077,6 @@ if not PkgSkip("CONTRIB"): PyTargetAdd('ai.pyd', input='ai_module.obj') PyTargetAdd('ai.pyd', input='libpandaai_igate.obj') PyTargetAdd('ai.pyd', input='libpandaai.dll') - PyTargetAdd('ai.pyd', input='libp3interrogatedb.dll') PyTargetAdd('ai.pyd', input=COMMON_PANDA_LIBS) # @@ -6119,7 +6097,6 @@ if not PkgSkip("CONTRIB") and not PkgSkip("PYTHON"): PyTargetAdd('_rplight.pyd', input='rplight_module.obj') PyTargetAdd('_rplight.pyd', input='libp3rplight_igate.obj') PyTargetAdd('_rplight.pyd', input='p3rplight_composite1.obj') - PyTargetAdd('_rplight.pyd', input='libp3interrogatedb.dll') PyTargetAdd('_rplight.pyd', input=COMMON_PANDA_LIBS) # @@ -6170,6 +6147,42 @@ if PkgSkip("PYTHON") == 0: PyTargetAdd('libdeploy-stubw.dll', input='libp3android.dll') PyTargetAdd('libdeploy-stubw.dll', opts=['DEPLOYSTUB', 'ANDROID']) +# +# Build the test runner for static builds +# +if GetLinkAllStatic(): + if GetTarget() == 'emscripten': + LinkFlag('RUN_TESTS_FLAGS', '-s NODERAWFS') + LinkFlag('RUN_TESTS_FLAGS', '-s ASSERTIONS=2') + LinkFlag('RUN_TESTS_FLAGS', '-s ALLOW_MEMORY_GROWTH') + LinkFlag('RUN_TESTS_FLAGS', '-s INITIAL_HEAP=585302016') + LinkFlag('RUN_TESTS_FLAGS', '-s STACK_SIZE=1048576') + LinkFlag('RUN_TESTS_FLAGS', '--minify 0') + + if not PkgSkip('DIRECT'): + DefSymbol('RUN_TESTS_FLAGS', 'HAVE_DIRECT') + if not PkgSkip('PANDAPHYSICS'): + DefSymbol('RUN_TESTS_FLAGS', 'HAVE_PHYSICS') + if not PkgSkip('EGG'): + DefSymbol('RUN_TESTS_FLAGS', 'HAVE_EGG') + if not PkgSkip('BULLET'): + DefSymbol('RUN_TESTS_FLAGS', 'HAVE_BULLET') + + OPTS=['DIR:tests', 'PYTHON', 'RUN_TESTS_FLAGS'] + PyTargetAdd('run_tests-main.obj', opts=OPTS, input='main.c') + PyTargetAdd('run_tests.exe', input='run_tests-main.obj') + PyTargetAdd('run_tests.exe', input='core.pyd') + if not PkgSkip('DIRECT'): + PyTargetAdd('run_tests.exe', input='direct.pyd') + if not PkgSkip('PANDAPHYSICS'): + PyTargetAdd('run_tests.exe', input='physics.pyd') + if not PkgSkip('EGG'): + PyTargetAdd('run_tests.exe', input='egg.pyd') + if not PkgSkip('BULLET'): + PyTargetAdd('run_tests.exe', input='bullet.pyd') + PyTargetAdd('run_tests.exe', input=COMMON_PANDA_LIBS) + PyTargetAdd('run_tests.exe', opts=['PYTHON', 'BULLET', 'RUN_TESTS_FLAGS']) + # # Generate the models directory and samples directory # @@ -6331,8 +6344,16 @@ finally: # Run the test suite. if RUNTESTS: - cmdstr = BracketNameWithQuotes(SDK["PYTHONEXEC"].replace('\\', '/')) - cmdstr += " -B -m pytest tests" + if GetLinkAllStatic(): + runner = FindLocation("run_tests.exe", []) + if runner.endswith(".js"): + cmdstr = "node " + BracketNameWithQuotes(runner) + else: + cmdstr = BracketNameWithQuotes(runner) + else: + cmdstr = BracketNameWithQuotes(SDK["PYTHONEXEC"].replace('\\', '/')) + cmdstr += " -B -m pytest" + cmdstr += " tests" if GetVerbose(): cmdstr += " --verbose" oscmd(cmdstr) diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index d715437472..3a4feb5b57 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -592,8 +592,8 @@ def GetInterrogateDir(): return INTERROGATE_DIR dir = os.path.join(GetOutputDir(), "tmp", "interrogate") - if not os.path.isdir(os.path.join(dir, "panda3d_interrogate-0.1.0.dist-info")): - oscmd("\"%s\" -m pip install --force-reinstall -t \"%s\" panda3d-interrogate==0.1.0" % (sys.executable, dir)) + if not os.path.isdir(os.path.join(dir, "panda3d_interrogate-0.4.0.dist-info")): + oscmd("\"%s\" -m pip install --force-reinstall --upgrade -t \"%s\" panda3d-interrogate==0.4.0" % (sys.executable, dir)) INTERROGATE_DIR = dir @@ -2126,6 +2126,14 @@ def SdkLocatePython(prefer_thirdparty_python=False): SDK["PYTHON"] = sdkdir SDK["PYTHONEXEC"] = SDK["PYTHON"] + "/python" + gil_disabled = locations.get_config_var("Py_GIL_DISABLED") + if gil_disabled and int(gil_disabled): + SDK["PYTHONEXEC"] += "%d.%dt" % sys.version_info[:2] + abiflags = "t" + DefSymbol("PYTHON", "Py_GIL_DISABLED", "1") + else: + abiflags = "" + if (GetOptimize() <= 2): SDK["PYTHONEXEC"] += "_d.exe" else: @@ -2136,11 +2144,11 @@ def SdkLocatePython(prefer_thirdparty_python=False): # Determine which version it is by checking which dll is in the directory. if (GetOptimize() <= 2): - py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9]_d.dll") + \ - glob.glob(SDK["PYTHON"] + "/python[0-9][0-9][0-9]_d.dll") + py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9]" + abiflags + "_d.dll") + \ + glob.glob(SDK["PYTHON"] + "/python[0-9][0-9][0-9]" + abiflags + "_d.dll") else: - py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9].dll") + \ - glob.glob(SDK["PYTHON"] + "/python[0-9][0-9][0-9].dll") + py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9]" + abiflags + ".dll") + \ + glob.glob(SDK["PYTHON"] + "/python[0-9][0-9][0-9]" + abiflags + ".dll") if len(py_dlls) == 0: exit("Could not find the Python dll in %s." % (SDK["PYTHON"])) @@ -2151,37 +2159,62 @@ def SdkLocatePython(prefer_thirdparty_python=False): py_dllver = py_dll.strip(".DHLNOPTY_dhlnopty") ver = py_dllver[0] + '.' + py_dllver[1:] - SDK["PYTHONVERSION"] = "python" + ver - os.environ["PYTHONHOME"] = SDK["PYTHON"] + SDK["PYTHONVERSION"] = "python" + ver + abiflags running_ver = '%d.%d' % sys.version_info[:2] if ver != running_ver: Warn("running makepanda with Python %s, but building Panda3D with Python %s." % (running_ver, ver)) elif CrossCompiling() or (prefer_thirdparty_python and os.path.isdir(os.path.join(GetThirdpartyDir(), "python"))): - tp_python = os.path.join(GetThirdpartyDir(), "python") + if PkgHasCustomLocation("PYTHON"): + incdir = FindIncDirectory("PYTHON") + libdirs = FindLibDirectories("PYTHON") + else: + tp_python = os.path.join(GetThirdpartyDir(), "python") + incdir = tp_python + "/include" + libdirs = [tp_python + "/lib"] + bindir = tp_python + "/bin" if GetTarget() == 'darwin': - py_libs = glob.glob(tp_python + "/lib/libpython[0-9].[0-9].dylib") + \ - glob.glob(tp_python + "/lib/libpython[0-9].[0-9][0-9].dylib") + suffix = abiflags + '.dylib' else: - py_libs = glob.glob(tp_python + "/lib/libpython[0-9].[0-9].so") + \ - glob.glob(tp_python + "/lib/libpython[0-9].[0-9][0-9].so") + suffix = abiflags + '.so' + + py_libs = [] + py_static_libs = [] + for libdir in libdirs: + py_libs += glob.glob(libdir + "/libpython[0-9].[0-9]" + suffix) + py_libs += glob.glob(libdir + "/libpython[0-9].[0-9][0-9]" + suffix) + py_static_libs += glob.glob(libdir + "/libpython[0-9].[0-9]" + abiflags + ".a") + py_static_libs += glob.glob(libdir + "/libpython[0-9].[0-9][0-9]" + abiflags + ".a") + + # Prefer dynamic libs over static libs + py_libs += py_static_libs if len(py_libs) == 0: - py_libs = glob.glob(tp_python + "/lib/libpython[0-9].[0-9].a") + \ - glob.glob(tp_python + "/lib/libpython[0-9].[0-9][0-9].a") + exit("Could not find the Python library in %s." % (libdirs)) + elif len(py_libs) == 1: + py_lib = os.path.basename(py_libs[0]) + py_libver = py_lib.lstrip('.abdhilnopsty').rstrip('.abdhilnopsy') + bindir = os.path.dirname(os.path.dirname(py_libs[0])) + "/bin" + else: + # Does one match our version? + gil_disabled = locations.get_config_var("Py_GIL_DISABLED") + abiflags = 't' if gil_disabled and int(gil_disabled) else '' + our_libver = locations.get_python_version() + abiflags - if len(py_libs) == 0: - exit("Could not find the Python library in %s." % (tp_python)) - elif len(py_libs) > 1: - exit("Found multiple Python libraries in %s." % (tp_python)) + for py_lib_full in py_libs: + py_lib = os.path.basename(py_lib_full) + py_libver = py_lib.lstrip('.abdhilnopsty').rstrip('.abdhilnopsy') + if py_libver == our_libver: + bindir = os.path.dirname(os.path.dirname(py_lib_full)) + "/bin" + break + else: + exit("Found multiple Python libraries in %s, none matching current version." % (libdirs)) - py_lib = os.path.basename(py_libs[0]) - py_libver = py_lib.strip('.abdhilnopsty') SDK["PYTHONVERSION"] = "python" + py_libver - SDK["PYTHONEXEC"] = tp_python + "/bin/" + SDK["PYTHONVERSION"] - SDK["PYTHON"] = tp_python + "/include/" + SDK["PYTHONVERSION"] + SDK["PYTHONEXEC"] = bindir + "/" + SDK["PYTHONVERSION"] + SDK["PYTHON"] = incdir + "/" + SDK["PYTHONVERSION"] elif GetTarget() == 'darwin' and not PkgHasCustomLocation("PYTHON"): # On macOS, search for the Python framework directory matching the @@ -2189,11 +2222,15 @@ def SdkLocatePython(prefer_thirdparty_python=False): sysroot = SDK.get("MACOSX", "") version = locations.get_python_version() - py_fwx = "{0}/System/Library/Frameworks/Python.framework/Versions/{1}".format(sysroot, version) + framework_name = "Python" + if 't' in abiflags: + framework_name += "T" + + py_fwx = "{0}/System/Library/Frameworks/{1}.framework/Versions/{2}".format(sysroot, framework_name, version) if not os.path.exists(py_fwx): # Fall back to looking on the system. - py_fwx = "/Library/Frameworks/Python.framework/Versions/" + version + py_fwx = "/Library/Frameworks/{0}.framework/Versions/{1}".format(framework_name, version) if not os.path.exists(py_fwx): # Use Brew Python. @@ -2839,6 +2876,13 @@ def FindLibDirectory(opt): if mod == opt: return os.path.abspath(dir) +def FindLibDirectories(opt): + result = [] + for mod, dir in LIBDIRECTORIES: + if mod == opt: + result.append(os.path.abspath(dir)) + return result + def FindOptDirectory(opt): # Find the common directory associated with this module # using the include and library directories as a guide @@ -3041,6 +3085,9 @@ def SetupBuildEnvironment(compiler): # If we're cross-compiling, no point in putting our output dirs on the path. if CrossCompiling(): + if GetTarget() == 'emscripten' and not PkgSkip("PYTHON"): + AddToPathEnv("PYTHONPATH", GetOutputDir()) + os.environ["PYTHONHOME"] = os.path.dirname(os.path.dirname(SDK["PYTHON"])) return # Add our output directories to the environment. @@ -3052,6 +3099,7 @@ def SetupBuildEnvironment(compiler): # extension_native_helpers.py currently expects to find libpandaexpress on sys.path. AddToPathEnv("PYTHONPATH", os.path.join(builtdir, "bin")) AddToPathEnv("PATH", os.path.join(builtdir, "plugins")) + os.environ["PYTHONHOME"] = SDK["PYTHON"] # Now for the special (DY)LD_LIBRARY_PATH on Unix-esque systems. if GetHost() != 'windows': @@ -3368,12 +3416,16 @@ def GetExtensionSuffix(): else: dllext = '' + gil_disabled = locations.get_config_var("Py_GIL_DISABLED") + suffix = 't' if gil_disabled and int(gil_disabled) else '' if GetTargetArch() == 'x64': - return dllext + '.cp%d%d-win_amd64.pyd' % (sys.version_info[:2]) + return dllext + '.cp%d%d%s-win_amd64.pyd' % (sys.version_info[0], sys.version_info[1], suffix) else: - return dllext + '.cp%d%d-win32.pyd' % (sys.version_info[:2]) + return dllext + '.cp%d%d%s-win32.pyd' % (sys.version_info[0], sys.version_info[1], suffix) elif target == 'emscripten': - return '.so' + abi = GetPythonABI() + arch = GetTargetArch() + return '.{0}-{1}-emscripten.so'.format(abi, arch) elif CrossCompiling(): return '.{0}.so'.format(GetPythonABI()) else: @@ -3386,7 +3438,14 @@ def GetPythonABI(): if soabi: return soabi - return 'cpython-%d%d' % (sys.version_info[:2]) + soabi = 'cpython-%d%d' % (sys.version_info[:2]) + + if sys.version_info >= (3, 13): + gil_disabled = locations.get_config_var("Py_GIL_DISABLED") + if gil_disabled and int(gil_disabled): + return soabi + 't' + + return soabi def CalcLocation(fn, ipath): if fn.startswith("panda3d/") and fn.endswith(".py"): @@ -3508,7 +3567,7 @@ def GetCurrentPythonVersionInfo(): return return { - "version": SDK["PYTHONVERSION"][6:].rstrip('dmu'), + "version": SDK["PYTHONVERSION"][6:].rstrip('dmut'), "soabi": GetPythonABI(), "ext_suffix": GetExtensionSuffix(), "executable": sys.executable, @@ -3663,7 +3722,7 @@ def TargetAdd(target, dummy=0, opts=[], input=[], dep=[], ipath=None, winrc=None t.inputs.append(fullinput) # Don't re-link a library or binary if just its dependency dlls have been altered. # This should work out fine in most cases, and often reduces recompilation time. - if os.path.splitext(x)[-1] not in SUFFIX_DLL: + if os.path.splitext(x)[-1] not in SUFFIX_DLL or (GetLinkAllStatic() and target.endswith(".exe")): t.deps[fullinput] = 1 (base,suffix) = os.path.splitext(x) if SUFFIX_INC.count(suffix): diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py index 32b933c4ba..bafda55f3f 100644 --- a/makepanda/makewheel.py +++ b/makepanda/makewheel.py @@ -19,13 +19,15 @@ from sysconfig import get_platform def get_abi_tag(): - soabi = get_config_var('SOABI') - if soabi and soabi.startswith('cpython-'): - return 'cp' + soabi.split('-')[1] - elif soabi: - return soabi.replace('.', '_').replace('-', '_') + ver = 'cp%d%d' % sys.version_info[:2] + if hasattr(sys, 'abiflags'): + return ver + sys.abiflags - return 'cp%d%d' % (sys.version_info[:2]) + gil_disabled = get_config_var("Py_GIL_DISABLED") + if gil_disabled and int(gil_disabled): + return ver + 't' + + return ver def is_exe_file(path): @@ -102,6 +104,7 @@ EXCLUDE_BINARIES = [ 'interrogate_module', 'test_interrogate', 'parse_file', + 'run_tests', ] WHEEL_DATA = """Wheel-Version: 1.0 @@ -497,7 +500,8 @@ class WheelFile(object): self.consider_add_dependency(target_dep, dep_path) continue - elif dep.startswith('/Library/Frameworks/Python.framework/'): + elif dep.startswith('/Library/Frameworks/Python.framework/') or \ + dep.startswith('/Library/Frameworks/PythonT.framework/'): # Add this dependency if it's in the Python directory. target_dep = os.path.dirname(target_path) + '/' + os.path.basename(dep) target_dep = self.consider_add_dependency(target_dep, dep, loader_path) @@ -639,10 +643,20 @@ def makewheel(version, output_dir, platform=None): if platform is None: # Determine the platform from the build. platform_dat = os.path.join(output_dir, 'tmp', 'platform.dat') + cmake_cache = os.path.join(output_dir, 'CMakeCache.txt') if os.path.isfile(platform_dat): + # This is written by makepanda. platform = open(platform_dat, 'r').read().strip() + elif os.path.isfile(cmake_cache): + # This variable is written to the CMake cache by Package.cmake. + for line in open(cmake_cache, 'r').readlines(): + if line.startswith('PYTHON_PLATFORM_TAG:STRING='): + platform = line[27:].strip() + break + if not platform: + raise Exception("Could not find PYTHON_PLATFORM_TAG in CMakeCache.txt, specify --platform manually.") else: - print("Could not find platform.dat in build directory") + print("Could not find platform.dat or CMakeCache.txt in build directory") platform = get_platform() if platform.startswith("linux-") and os.path.isdir("/opt/python"): # Is this manylinux? @@ -722,11 +736,16 @@ def makewheel(version, output_dir, platform=None): whl.ignore_deps.update(MANYLINUX_LIBS) # Add libpython for deployment. + suffix = '' + gil_disabled = get_config_var("Py_GIL_DISABLED") + if gil_disabled and int(gil_disabled): + suffix = 't' + if is_windows: - pylib_name = 'python{0}{1}.dll'.format(*sys.version_info) + pylib_name = 'python{0}{1}{2}.dll'.format(sys.version_info[0], sys.version_info[1], suffix) pylib_path = os.path.join(get_config_var('BINDIR'), pylib_name) elif is_macosx: - pylib_name = 'libpython{0}.{1}.dylib'.format(*sys.version_info) + pylib_name = 'libpython{0}.{1}{2}.dylib'.format(sys.version_info[0], sys.version_info[1], suffix) pylib_path = os.path.join(get_config_var('LIBDIR'), pylib_name) else: pylib_name = get_config_var('LDLIBRARY') diff --git a/makepanda/test_wheel.py b/makepanda/test_wheel.py index cfe270099e..2de54e059d 100755 --- a/makepanda/test_wheel.py +++ b/makepanda/test_wheel.py @@ -14,7 +14,7 @@ import tempfile from optparse import OptionParser -def test_wheel(wheel, verbose=False): +def test_wheel(wheel, verbose=False, ignores=[]): envdir = tempfile.mkdtemp(prefix="venv-") print("Setting up virtual environment in {0}".format(envdir)) sys.stdout.flush() @@ -61,6 +61,9 @@ def test_wheel(wheel, verbose=False): test_cmd = [python, "-m", "pytest", "tests"] if verbose: test_cmd.append("--verbose") + for ignore in ignores: + test_cmd.append("--ignore") + test_cmd.append(ignore) # Put the location of the python DLL on the path, for deploy-stub test # This is needed because venv does not install a copy of the python DLL @@ -87,6 +90,7 @@ def test_wheel(wheel, verbose=False): if __name__ == "__main__": parser = OptionParser(usage="%prog [options] file...") parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False) + parser.add_option('', '--ignore', dest = 'ignores', help = 'Ignores given test directory (may be repeated)', action = 'append', default = []) (options, args) = parser.parse_args() if not args: @@ -94,4 +98,4 @@ if __name__ == "__main__": sys.exit(1) for arg in args: - test_wheel(arg, verbose=options.verbose) + test_wheel(arg, verbose=options.verbose, ignores=options.ignores) diff --git a/panda/src/audio/config_audio.cxx b/panda/src/audio/config_audio.cxx index d483b40d75..de128896e6 100644 --- a/panda/src/audio/config_audio.cxx +++ b/panda/src/audio/config_audio.cxx @@ -75,6 +75,13 @@ ConfigVariableInt audio_preload_threshold "practical to stream multiple sound-files from disk at the same " "time - the hard drive seek time makes it stutter.")); +ConfigVariableBool audio_want_hrtf +("audio-want-hrtf", true, + PRC_DESC("This determines whether OpenAL-Soft should activate HRTF in " + "certain hardware configurations. Set it to true to cause " + "OpenAL to automatically apply HRTF processing to all output " + "audio when headphones are used for playback.")); + // Unknown ConfigVariableInt audio_min_hw_channels diff --git a/panda/src/audio/config_audio.h b/panda/src/audio/config_audio.h index deac9704be..4e5c428e92 100644 --- a/panda/src/audio/config_audio.h +++ b/panda/src/audio/config_audio.h @@ -67,6 +67,7 @@ extern EXPCL_PANDA_AUDIO ConfigVariableDouble audio_distance_factor; extern EXPCL_PANDA_AUDIO ConfigVariableDouble audio_drop_off_factor; extern EXPCL_PANDA_AUDIO ConfigVariableDouble audio_buffering_seconds; extern EXPCL_PANDA_AUDIO ConfigVariableInt audio_preload_threshold; +extern EXPCL_PANDA_AUDIO ConfigVariableBool audio_want_hrtf; #ifdef NOTIFY_DEBUG //[ // Non-release build: diff --git a/panda/src/audiotraits/openalAudioManager.cxx b/panda/src/audiotraits/openalAudioManager.cxx index 0e6e06d16a..5df2d0d880 100644 --- a/panda/src/audiotraits/openalAudioManager.cxx +++ b/panda/src/audiotraits/openalAudioManager.cxx @@ -155,7 +155,22 @@ OpenALAudioManager() { if (_device != nullptr) { // We managed to get a device open. alcGetError(_device); // clear errors - _context = alcCreateContext(_device, nullptr); + + ALCboolean is_hrtf_present = alcIsExtensionPresent(_device, "ALC_SOFT_HRTF"); + + ALCint attrs[3] = {0}; + +#ifndef HAVE_OPENAL_FRAMEWORK + if (is_hrtf_present) { + attrs[0] = ALC_HRTF_SOFT; + attrs[1] = audio_want_hrtf.get_value() ? ALC_TRUE : ALC_FALSE; + attrs[2] = 0; // end of list + } else { + attrs[0] = 0; // end of list + } +#endif // HAVE_OPENAL_FRAMEWORK + + _context = alcCreateContext(_device, attrs); alc_audio_errcheck("alcCreateContext(_device, NULL)", _device); if (_context != nullptr) { _openal_active = true; diff --git a/panda/src/audiotraits/openalAudioManager.h b/panda/src/audiotraits/openalAudioManager.h index 3970c50627..56b01afc6c 100644 --- a/panda/src/audiotraits/openalAudioManager.h +++ b/panda/src/audiotraits/openalAudioManager.h @@ -29,6 +29,7 @@ #else #include #include + #include #endif class OpenALAudioSound; diff --git a/panda/src/audiotraits/openalAudioSound.h b/panda/src/audiotraits/openalAudioSound.h index cc643ac20c..6dc30a936c 100644 --- a/panda/src/audiotraits/openalAudioSound.h +++ b/panda/src/audiotraits/openalAudioSound.h @@ -27,6 +27,7 @@ #else #include #include + #include #endif class EXPCL_OPENAL_AUDIO OpenALAudioSound final : public AudioSound { diff --git a/panda/src/bullet/bulletDebugNode.cxx b/panda/src/bullet/bulletDebugNode.cxx index 7bc26ae1c1..b3a5407146 100644 --- a/panda/src/bullet/bulletDebugNode.cxx +++ b/panda/src/bullet/bulletDebugNode.cxx @@ -248,16 +248,8 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { // Record them without any state or transform. trav->_geoms_pcollector.add_level(2); - { - CullableObject *object = - new CullableObject(std::move(debug_lines), RenderState::make_empty(), trav->get_scene()->get_cs_world_transform()); - trav->get_cull_handler()->record_object(object, trav); - } - { - CullableObject *object = - new CullableObject(std::move(debug_triangles), RenderState::make_empty(), trav->get_scene()->get_cs_world_transform()); - trav->get_cull_handler()->record_object(object, trav); - } + trav->get_cull_handler()->record_object(CullableObject(std::move(debug_lines), RenderState::make_empty(), trav->get_scene()->get_cs_world_transform()), trav); + trav->get_cull_handler()->record_object(CullableObject(std::move(debug_triangles), RenderState::make_empty(), trav->get_scene()->get_cs_world_transform()), trav); } /** diff --git a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm index 3734f37af8..5ab3d64341 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm @@ -177,7 +177,7 @@ load_display_information() { // Get processor information const NXArchInfo *ainfo = NXGetLocalArchInfo(); - _display_information->_cpu_brand_string = strdup(ainfo->description); + _display_information->_cpu_brand_string.assign(ainfo->description); // Get version of Mac OS X SInt32 major, minor, bugfix; diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index 3aae8aee63..01c7ab8f63 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -32,7 +32,6 @@ #import "cocoaPandaAppDelegate.h" #import -#import #import #import #import @@ -47,6 +46,12 @@ TypeHandle CocoaGraphicsWindow::_type_handle; #define NSAppKitVersionNumber10_14 1671 #endif +#if __MAC_OS_X_VERSION_MAX_ALLOWED < 1070 +enum { + NSFullScreenWindowMask = 1 << 14 +}; +#endif + /** * */ @@ -177,7 +182,6 @@ void CocoaGraphicsWindow:: process_events() { GraphicsWindow::process_events(); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSEvent *event = nil; while (true) { @@ -212,8 +216,6 @@ process_events() { [_window update]; } - [pool release]; - if (_context_needs_update && _gsg != nullptr) { update_context(); } @@ -728,13 +730,12 @@ set_properties_now(WindowProperties &properties) { // here. if (!properties.has_undecorated() && !_properties.get_undecorated() && [_window respondsToSelector:@selector(setStyleMask:)]) { - if (properties.get_fixed_size()) { - [_window setStyleMask:NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask ]; - } else { - [_window setStyleMask:NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | NSResizableWindowMask ]; + NSUInteger style = ([_window styleMask] & NSFullScreenWindowMask); + style |= NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask; + if (!properties.get_fixed_size()) { + style |= NSResizableWindowMask; } + [_window setStyleMask:style]; [_window makeFirstResponder:_view]; // Resize event fired by makeFirstResponder has an invalid backing scale factor // The actual size must be reset afterward @@ -749,16 +750,14 @@ set_properties_now(WindowProperties &properties) { _properties.set_undecorated(properties.get_undecorated()); if (!_properties.get_fullscreen()) { - if (properties.get_undecorated()) { - [_window setStyleMask: NSBorderlessWindowMask]; - } else if (_properties.get_fixed_size()) { - // Fixed size windows should not show the resize button. - [_window setStyleMask: NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask ]; - } else { - [_window setStyleMask: NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | NSResizableWindowMask ]; + NSUInteger style = ([_window styleMask] & NSFullScreenWindowMask); + if (!properties.get_undecorated()) { + style |= NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask; + if (!properties.get_fixed_size()) { + style |= NSResizableWindowMask; + } } + [_window setStyleMask:style]; [_window makeFirstResponder:_view]; // Resize event fired by makeFirstResponder has an invalid backing scale factor // The actual size must be reset afterward @@ -1176,10 +1175,16 @@ do_switch_fullscreen(CGDisplayModeRef mode) { } if (_window != nil) { + // Exit macOS' own fullscreen mode, since our own fullscreen mode + // doesn't work properly with it. + if ([_window styleMask] & NSFullScreenWindowMask) { + [_window toggleFullScreen:nil]; + } + // For some reason, setting the style mask makes it give up its // first-responder status. if ([_window respondsToSelector:@selector(setStyleMask:)]) { - [_window setStyleMask:NSBorderlessWindowMask]; + [_window setStyleMask:([_window styleMask] & NSFullScreenWindowMask)]; } [_window makeFirstResponder:_view]; [_window setLevel:CGShieldingWindowLevel()]; diff --git a/panda/src/cocoadisplay/cocoaPandaApp.mm b/panda/src/cocoadisplay/cocoaPandaApp.mm index 83f0b8ef42..d256102a2c 100644 --- a/panda/src/cocoadisplay/cocoaPandaApp.mm +++ b/panda/src/cocoadisplay/cocoaPandaApp.mm @@ -16,11 +16,11 @@ @implementation CocoaPandaApp - (void) sendEvent: (NSEvent *) event { - // This is a hack that allows us to receive cmd-key-up events correctly. - // Also prevent it from eating the inserthelp key. - if (([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask)) - ||([event type] == NSKeyDown && [event keyCode] == 0x72)) { - + // This is a hack that allows us to receive cmd-key-up events correctly, as + // well as key-up events during a full-screen transition. + // Also prevent it from eating the insert/help key. + if ([event type] == NSKeyUp || + ([event type] == NSKeyDown && [event keyCode] == 0x72)) { [[self keyWindow] sendEvent: event]; } else { [super sendEvent: event]; diff --git a/panda/src/collide/collisionBox.I b/panda/src/collide/collisionBox.I index 86473473cf..385152c2a1 100644 --- a/panda/src/collide/collisionBox.I +++ b/panda/src/collide/collisionBox.I @@ -21,11 +21,9 @@ CollisionBox(const LPoint3 ¢er, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) { _min = LPoint3(_center.get_x() - x, _center.get_y() - y, _center.get_z() - z); _max = LPoint3(_center.get_x() + x, _center.get_y() + y, _center.get_z() + z); - for(int v = 0; v < 8; v++) - _vertex[v] = get_point_aabb(v); - for(int p = 0; p < 6; p++) + for (int p = 0; p < 6; ++p) { _planes[p] = set_plane(p); - setup_box(); + } } /** @@ -33,14 +31,11 @@ CollisionBox(const LPoint3 ¢er, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) */ INLINE CollisionBox:: CollisionBox(const LPoint3 &min, const LPoint3 &max) : - _min(min), _max(max) + _center((min + max) / 2), _min(min), _max(max) { - _center = (_min + _max) / 2; - for(int v = 0; v < 8; v++) - _vertex[v] = get_point_aabb(v); - for(int p = 0; p < 6; p++) + for (int p = 0; p < 6; ++p) { _planes[p] = set_plane(p); - setup_box(); + } } /** @@ -60,11 +55,9 @@ CollisionBox(const CollisionBox ©) : _min(copy._min), _max(copy._max) { - for(int v = 0; v < 8; v++) - _vertex[v] = copy._vertex[v]; - for(int p = 0; p < 6; p++) + for (int p = 0; p < 6; ++p) { _planes[p] = copy._planes[p]; - setup_box(); + } } /** @@ -139,8 +132,7 @@ get_num_points() const { */ INLINE LPoint3 CollisionBox:: get_point(int n) const { - nassertr(n >= 0 && n < 8, LPoint3::zero()); - return _vertex[n]; + return get_point_aabb(n); } /** @@ -175,6 +167,8 @@ get_plane(int n) const { /** * Creates the nth face of the rectangular solid. + * + * @deprecated Same as get_plane(). */ INLINE LPlane CollisionBox:: set_plane(int n) const { @@ -183,91 +177,3 @@ set_plane(int n) const { get_point(plane_def[n][1]), get_point(plane_def[n][2])); } - - -/** - * Returns true if the 2-d v1 is to the right of v2. - */ -INLINE bool CollisionBox:: -is_right(const LVector2 &v1, const LVector2 &v2) { - return (v1[0] * v2[1] - v1[1] * v2[0]) > 1.0e-6f; -} - -/** - * Returns the linear distance of p to the line defined by f and f+v, where v - * is a normalized vector. The result is negative if p is left of the line, - * positive if it is right of the line. - */ -INLINE PN_stdfloat CollisionBox:: -dist_to_line(const LPoint2 &p, - const LPoint2 &f, const LVector2 &v) { - LVector2 v1 = (p - f); - return (v1[0] * v[1] - v1[1] * v[0]); -} - -/** - * Assuming the indicated point in 3-d space lies within the polygon's plane, - * returns the corresponding point in the polygon's 2-d definition space. - */ -INLINE LPoint2 CollisionBox:: -to_2d(const LVecBase3 &point3d, int plane) const { - LPoint3 point = LPoint3(point3d) * _to_2d_mat[plane]; - return LPoint2(point[0], point[2]); -} - -/** - * Fills the indicated matrix with the appropriate rotation transform to move - * points from the 2-d plane into the 3-d (X, 0, Z) plane. - */ -INLINE void CollisionBox:: -calc_to_3d_mat(LMatrix4 &to_3d_mat,int plane) const { - // We have to be explicit about the coordinate system--we specifically mean - // CS_zup_right, because that points the forward vector down the Y axis and - // moves the coords in (X, 0, Z). We want this effect regardless of the - // user's coordinate system of choice. - - // The up vector, on the other hand, is completely arbitrary. - - look_at(to_3d_mat, -get_plane(plane).get_normal(), - LVector3(0.0f, 0.0f, 1.0f), CS_zup_right); - to_3d_mat.set_row(3, get_plane(plane).get_point()); -} - -/** - * Extrude the indicated point in the polygon's 2-d definition space back into - * 3-d coordinates. - */ -INLINE LPoint3 CollisionBox:: -to_3d(const LVecBase2 &point2d, const LMatrix4 &to_3d_mat) { - return LPoint3(point2d[0], 0.0f, point2d[1]) * to_3d_mat; -} - -/** - * - */ -INLINE CollisionBox::PointDef:: -PointDef(const LPoint2 &p, const LVector2 &v) : _p(p), _v(v) { -} - -/** - * - */ -INLINE CollisionBox::PointDef:: -PointDef(PN_stdfloat x, PN_stdfloat y) : _p(x, y), _v(0.0f, 0.0f) { -} - -/** - * - */ -INLINE CollisionBox::PointDef:: -PointDef(const CollisionBox::PointDef ©) : _p(copy._p), _v(copy._v) { -} - -/** - * - */ -INLINE void CollisionBox::PointDef:: -operator = (const CollisionBox::PointDef ©) { - _p = copy._p; - _v = copy._v; -} diff --git a/panda/src/collide/collisionBox.cxx b/panda/src/collide/collisionBox.cxx index f4224f2d14..5058dfaf37 100644 --- a/panda/src/collide/collisionBox.cxx +++ b/panda/src/collide/collisionBox.cxx @@ -54,6 +54,102 @@ const int CollisionBox::plane_def[6][4] = { {2, 6, 4, 0}, }; +/** + * Helper function to calculate the intersection between a line segment and a + * sphere. t is filled with the first position along the line segment where + * the intersection hits. + */ +static bool +intersect_segment_sphere(double &t, + const LPoint3 &from, const LVector3 &delta, + const LPoint3 ¢er, double radius_sq) { + double A2 = dot(delta, delta) * 2; + + LVector3 fc = from - center; + double fc_d2 = dot(fc, fc); + double C = fc_d2 - radius_sq; + + if (UNLIKELY(A2 == 0.0)) { + // Degenerate case where delta is zero. This is effectively a test + // against a point (or sphere, for nonzero inflate_radius). + t = 0.0; + return C < 0.0; + } + + double B = 2.0f * dot(delta, fc); + double radical = B*B - 2.0*A2*C; + + if (radical < 0.0) { + // No real roots: no intersection with the line. + return false; + } + + t = (-B - csqrt(radical)) / A2; + return true; +} + +/** + * Helper function to calculate the intersection between a line segment and a + * capsule. t is filled with the first position along the line segment where + * the intersection hits. + * + * Code derived from a book by Christer Ericson. + */ +static bool +intersect_segment_capsule(double &t, + const LPoint3 &from_a, const LVector3 &delta_a, + const LPoint3 &from_b, const LPoint3 &to_b, + double radius_sq) { + LVector3 m = from_a - from_b; + LVector3 delta_b = to_b - from_b; + PN_stdfloat md = m.dot(delta_b); + PN_stdfloat nd = delta_a.dot(delta_b); + PN_stdfloat dd = delta_b.dot(delta_b); + if (md < 0 && md + nd < 0) { + return intersect_segment_sphere(t, from_a, delta_a, from_b, radius_sq); + } + if (md > dd && md + nd > dd) { + return intersect_segment_sphere(t, from_a, delta_a, to_b, radius_sq); + } + PN_stdfloat nn = delta_a.dot(delta_a); + PN_stdfloat mn = m.dot(delta_a); + PN_stdfloat a = dd * nn - nd * nd; + PN_stdfloat k = m.dot(m) - radius_sq; + PN_stdfloat c = dd * k - md * md; + if (IS_NEARLY_ZERO(a)) { + // Segments run parallel + if (c > 0.0f) { + return false; + } + if (md < 0.0f) { + return intersect_segment_sphere(t, from_a, delta_a, from_b, radius_sq); + } + else if (md > dd) { + return intersect_segment_sphere(t, from_a, delta_a, to_b, radius_sq); + } + else { + t = 0.0; + } + return true; + } + PN_stdfloat b = dd * mn - nd * md; + PN_stdfloat discr = b * b - a * c; + if (discr < 0.0f) { + return false; + } + t = (-b - csqrt(discr)) / a; + if (t < 0.0 || t > 1.0) { + return false; + } + if (md + t * nd < 0) { + return intersect_segment_sphere(t, from_a, delta_a, from_b, radius_sq); + } + else if (md + t * nd > dd) { + return intersect_segment_sphere(t, from_a, delta_a, to_b, radius_sq); + } + return true; +} + /** * */ @@ -62,45 +158,6 @@ make_copy() { return new CollisionBox(*this); } -/** - * Compute parameters for each of the box's sides - */ -void CollisionBox:: -setup_box() { - assert(sizeof(_points) / sizeof(_points[0]) == 6); - assert(sizeof(_points[0]) / sizeof(_points[0][0]) == 4); - for (int plane = 0; plane < 6; plane++) { - setup_points(plane); - } -} - -/** - * Computes the plane and 2d projection of points that make up this side. - */ -void CollisionBox:: -setup_points(int plane) { - PointDef *points = _points[plane]; - - // Construct a matrix that rotates the points from the (X,0,Z) plane into - // the 3-d plane. - LMatrix4 to_3d_mat; - calc_to_3d_mat(to_3d_mat, plane); - - // And the inverse matrix rotates points from 3-d space into the 2-d plane. - _to_2d_mat[plane].invert_from(to_3d_mat); - - // Now project all of the points onto the 2-d plane. - for (size_t i = 0; i < 4; ++i) { - LPoint3 point = get_point(plane_def[plane][i]) * _to_2d_mat[plane]; - points[i] = PointDef(point[0], point[2]); - } - - for (size_t i = 0; i < 4; i++) { - points[i]._v = points[(i + 1) % 4]._p - points[i]._p; - points[i]._v.normalize(); - } -} - /** * First Dispatch point for box as a FROM object */ @@ -117,13 +174,9 @@ xform(const LMatrix4 &mat) { _min = _min * mat; _max = _max * mat; _center = _center * mat; - for(int v = 0; v < 8; v++) { - _vertex[v] = _vertex[v] * mat; - } for(int p = 0; p < 6 ; p++) { _planes[p] = set_plane(p); } - setup_box(); mark_viz_stale(); mark_internal_bounds_stale(); } @@ -169,9 +222,10 @@ output(std::ostream &out) const { */ PT(BoundingVolume) CollisionBox:: compute_internal_bounds() const { - PN_stdfloat x = _vertex[0].get_x() - _center.get_x(); - PN_stdfloat y = _vertex[0].get_y() - _center.get_y(); - PN_stdfloat z = _vertex[0].get_z() - _center.get_z(); + LPoint3 vertex = get_point_aabb(0); + PN_stdfloat x = vertex.get_x() - _center.get_x(); + PN_stdfloat y = vertex.get_y() - _center.get_y(); + PN_stdfloat z = vertex.get_z() - _center.get_z(); PN_stdfloat radius = sqrt(x * x + y * y + z * z); return new BoundingSphere(_center, radius); } @@ -190,168 +244,45 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { const LMatrix4 &wrt_mat = wrt_space->get_mat(); - LPoint3 orig_center = sphere->get_center() * wrt_mat; - LPoint3 from_center = orig_center; - bool moved_from_center = false; - PN_stdfloat t = 1.0f; - LPoint3 contact_point(from_center); - PN_stdfloat actual_t = 1.0f; + LPoint3 center = wrt_mat.xform_point(sphere->get_center()); + PN_stdfloat radius_sq = wrt_mat.xform_vec(LVector3(0, 0, sphere->get_radius())).length_squared(); - LVector3 from_radius_v = - LVector3(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat; - PN_stdfloat from_radius_2 = from_radius_v.length_squared(); - PN_stdfloat from_radius = csqrt(from_radius_2); + bool had_prev = false; + LPoint3 prev_center = center; + double t = 0; - int ip; - PN_stdfloat max_dist = 0.0; - PN_stdfloat dist = 0.0; - bool intersect; - LPlane plane; - LVector3 normal; - bool fully_inside = true; + if (wrt_space != wrt_prev_space) { + prev_center = wrt_prev_space->get_mat().xform_point(sphere->get_center()); + } + LPoint3 contact_center = prev_center; - for(ip = 0, intersect = false; ip < 6 && !intersect; ip++) { - plane = get_plane(ip); - - if (wrt_prev_space != wrt_space) { - // If we have a delta between the previous position and the current - // position, we use that to determine some more properties of the - // collision. - LPoint3 b = from_center; - LPoint3 a = sphere->get_center() * wrt_prev_space->get_mat(); - LVector3 delta = b - a; - - // First, there is no collision if the "from" object is definitely - // moving in the same direction as the plane's normal. - PN_stdfloat dot = delta.dot(plane.get_normal()); - if (dot > 0.1f) { - fully_inside = false; - continue; // no intersection - } - - if (IS_NEARLY_ZERO(dot)) { - // If we're moving parallel to the plane, the sphere is tested at its - // final point. Leave it as it is. - - } else { -/* - * Otherwise, we're moving into the plane; the sphere is tested at the point - * along its path that is closest to intersecting the plane. This may be the - * actual intersection point, or it may be the starting point or the final - * point. dot is equal to the (negative) magnitude of 'delta' along the - * direction of the plane normal t = ratio of (distance from start pos to - * plane) to (distance from start pos to end pos), along axis of plane normal - */ - PN_stdfloat dist_to_p = plane.dist_to_plane(a); - t = (dist_to_p / -dot); - - // also compute the actual contact point and time of contact for - // handlers that need it - actual_t = ((dist_to_p - from_radius) / -dot); - actual_t = min((PN_stdfloat)1.0, max((PN_stdfloat)0.0, actual_t)); - contact_point = a + (actual_t * delta); - - if (t >= 1.0f) { - // Leave it where it is. - - } else if (t < 0.0f) { - from_center = a; - moved_from_center = true; - } else { - from_center = a + t * delta; - moved_from_center = true; - } - } - } - - normal = (has_effective_normal() && sphere->get_respect_effective_normal()) ? get_effective_normal() : plane.get_normal(); - -#ifndef NDEBUG - /*if (!IS_THRESHOLD_EQUAL(normal.length_squared(), 1.0f, 0.001), NULL) { - std::cout - << "polygon within " << entry.get_into_node_path() - << " has normal " << normal << " of length " << normal.length() - << "\n"; - normal.normalize(); - }*/ -#endif - - // The nearest point within the plane to our center is the intersection of - // the line (center, center - normal) with the plane. - - if (!plane.intersects_line(dist, from_center, -(plane.get_normal()))) { - // No intersection with plane? This means the plane's effective normal - // was within the plane itself. A useless polygon. - fully_inside = false; - continue; - } - - if (dist > from_radius) { - // Fully outside this plane, there can not be an intersection. + // First, just test the starting point of the sphere. + LVector3 vec = (prev_center - _min).fmin(0) + (prev_center - _max).fmax(0); + PN_stdfloat vec_lsq = vec.length_squared(); + if (vec_lsq > radius_sq) { + if (wrt_space == wrt_prev_space) { return nullptr; } - if (dist < -from_radius) { - // Fully inside this plane. - continue; + + // We must effectively do a capsule-into-box test. + LVector3 delta = center - prev_center; + if (!intersects_capsule(t, prev_center, delta, radius_sq)) { + return nullptr; } - fully_inside = false; + contact_center = prev_center + delta * t; - LPoint2 p = to_2d(from_center - dist * plane.get_normal(), ip); - PN_stdfloat edge_dist = 0.0f; + // This is used to calculate the surface normal, which must always be + // opposed to the movement direction! + vec = (contact_center - _min).fmin(0) + (contact_center - _max).fmax(0); + if ((vec[0] > 0) == (delta[0] > 0)) vec[0] = 0; + if ((vec[1] > 0) == (delta[1] > 0)) vec[1] = 0; + if ((vec[2] > 0) == (delta[2] > 0)) vec[2] = 0; - const ClipPlaneAttrib *cpa = entry.get_into_clip_planes(); - if (cpa != nullptr) { - // We have a clip plane; apply it. - Points new_points; - if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform(),ip)) { - // All points are behind the clip plane; just do the default test. - edge_dist = dist_to_polygon(p, _points[ip], 4); - } else if (new_points.empty()) { - // The polygon is completely clipped. - continue; - } else { - // Test against the clipped polygon. - edge_dist = dist_to_polygon(p, new_points.data(), new_points.size()); - } - } else { - // No clip plane is in effect. Do the default test. - edge_dist = dist_to_polygon(p, _points[ip], 4); - } - - max_dist = from_radius; - - // Now we have edge_dist, which is the distance from the sphere center to - // the nearest edge of the polygon, within the polygon's plane. - // edge_dist<0 means the point is within the polygon. - if(edge_dist < 0) { - intersect = true; - continue; - } - - if((edge_dist > 0) && - ((edge_dist * edge_dist + dist * dist) > from_radius_2)) { - // No intersection; the circle is outside the polygon. - continue; - } - - // The sphere appears to intersect the polygon. If the edge is less than - // from_radius away, the sphere may be resting on an edge of the polygon. - // Determine how far the center of the sphere must remain from the plane, - // based on its distance from the nearest edge. - - if (edge_dist >= 0.0f) { - PN_stdfloat max_dist_2 = max(from_radius_2 - edge_dist * edge_dist, (PN_stdfloat)0.0); - max_dist = csqrt(max_dist_2); - } - - if (dist > max_dist) { - // There's no intersection: the sphere is hanging off the edge. - continue; - } - intersect = true; + had_prev = true; } - if (!fully_inside && !intersect) { - return nullptr; + else if (vec_lsq == 0.0f) { + // It's completely inside. + vec = prev_center - _center; } if (collide_cat.is_debug()) { @@ -362,26 +293,44 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { PT(CollisionEntry) new_entry = new CollisionEntry(entry); - PN_stdfloat into_depth = max_dist - dist; - if (moved_from_center) { - // We have to base the depth of intersection on the sphere's final resting - // point, not the point from which we tested the intersection. - PN_stdfloat orig_dist; - plane.intersects_line(orig_dist, orig_center, -normal); - into_depth = max_dist - orig_dist; + int axis; + if (abs(vec[0]) > abs(vec[1])) { + if (abs(vec[0]) > abs(vec[2])) { + axis = 0; + } else { + axis = 2; + } + } else { + if (abs(vec[1]) > abs(vec[2])) { + axis = 1; + } else { + axis = 2; + } } - // Clamp the surface point to the box bounds. - LPoint3 surface = from_center - normal * dist; - surface = surface.fmax(_min); - surface = surface.fmin(_max); + LPoint3 surface_point = contact_center.fmax(_min).fmin(_max); + surface_point[axis] = vec[axis] > 0 ? _max[axis] : _min[axis]; - new_entry->set_surface_normal(normal); - new_entry->set_surface_point(surface); - new_entry->set_interior_point(surface - normal * into_depth); - new_entry->set_contact_pos(contact_point); - new_entry->set_contact_normal(plane.get_normal()); - new_entry->set_t(actual_t); + LVector3 normal(0, 0, 0); + normal[axis] = (vec[axis] > 0) * 2 - 1; + + LPoint3 interior_point = surface_point; + if (had_prev) { + interior_point += (center - contact_center); + } else { + LVector3 other = surface_point - contact_center; + other[axis] = 0.0f; + interior_point[axis] = center[axis] - std::copysign(std::max((PN_stdfloat)0, csqrt(radius_sq - other.length_squared())), vec[axis]); + } + + new_entry->set_interior_point(interior_point); + new_entry->set_surface_point(surface_point); + new_entry->set_surface_normal( + (has_effective_normal() && sphere->get_respect_effective_normal()) + ? get_effective_normal() : normal); + new_entry->set_contact_pos(contact_center); + new_entry->set_contact_normal(normal); + new_entry->set_t(t); return new_entry; } @@ -1088,327 +1037,61 @@ intersects_line(double &t1, double &t2, } /** - * Clips the polygon by all of the clip planes named in the clip plane - * attribute and fills new_points up with the resulting points. - * - * The return value is true if the set of points is unmodified (all points are - * behind all the clip planes), or false otherwise. + * Determine the first point of intersection of the given capsule with the box. */ bool CollisionBox:: -apply_clip_plane(CollisionBox::Points &new_points, - const ClipPlaneAttrib *cpa, - const TransformState *net_transform, int plane_no) const { - bool all_in = true; - - int num_planes = cpa->get_num_on_planes(); - bool first_plane = true; - - for (int i = 0; i < num_planes; i++) { - NodePath plane_path = cpa->get_on_plane(i); - PlaneNode *plane_node = DCAST(PlaneNode, plane_path.node()); - if ((plane_node->get_clip_effect() & PlaneNode::CE_collision) != 0) { - CPT(TransformState) new_transform = - net_transform->invert_compose(plane_path.get_net_transform()); - - LPlane plane = plane_node->get_plane() * new_transform->get_mat(); - if (first_plane) { - first_plane = false; - if (!clip_polygon(new_points, _points[plane_no], 4, plane, plane_no)) { - all_in = false; - } - } else { - Points last_points; - last_points.swap(new_points); - if (!clip_polygon(new_points, last_points.data(), last_points.size(), plane, plane_no)) { - all_in = false; - } - } - } - } - - if (!all_in) { - compute_vectors(new_points); - } - - return all_in; -} -/** - * Clips the source_points of the polygon by the indicated clipping plane, and - * modifies new_points to reflect the new set of clipped points (but does not - * compute the vectors in new_points). - * - * The return value is true if the set of points is unmodified (all points are - * behind the clip plane), or false otherwise. - */ -bool CollisionBox:: -clip_polygon(CollisionBox::Points &new_points, - const PointDef *source_points, size_t num_source_points, - const LPlane &plane, int plane_no) const { - new_points.clear(); - if (num_source_points == 0) { - return true; - } - - LPoint3 from3d; - LVector3 delta3d; - if (!plane.intersects_plane(from3d, delta3d, get_plane(plane_no))) { - // The clipping plane is parallel to the polygon. The polygon is either - // all in or all out. - if (plane.dist_to_plane(get_plane(plane_no).get_point()) < 0.0) { - // A point within the polygon is behind the clipping plane: the polygon - // is all in. - new_points.insert(new_points.end(), source_points, source_points + num_source_points); - return true; - } +intersects_capsule(double &t, const LPoint3 &from, const LVector3 &delta, + PN_stdfloat radius_sq) const { + // First, we check whether the line segment intersects with the box + // expanded by the sphere's radius. + double t2; + if (!intersects_line(t, t2, from, delta, csqrt(radius_sq)) || + t > 1.0 || t2 < 0.0) { return false; } - // Project the line of intersection into the 2-d plane. Now we have a 2-d - // clipping line. - LPoint2 from2d = to_2d(from3d,plane_no); - LVector2 delta2d = to_2d(delta3d,plane_no); + LPoint3 intersection = from + delta * t; - PN_stdfloat a = -delta2d[1]; - PN_stdfloat b = delta2d[0]; - PN_stdfloat c = from2d[0] * delta2d[1] - from2d[1] * delta2d[0]; + // The following technique is derived from a book by Christer Ericson. + int u = 0, v = 0; + if (intersection[0] < _min[0]) u |= 4; + if (intersection[1] < _min[1]) u |= 2; + if (intersection[2] < _min[2]) u |= 1; + if (intersection[0] > _max[0]) v |= 4; + if (intersection[1] > _max[1]) v |= 2; + if (intersection[2] > _max[2]) v |= 1; - // Now walk through the points. Any point on the left of our line gets - // removed, and the line segment clipped at the point of intersection. - - // We might increase the number of vertices by as many as 1, if the plane - // clips off exactly one corner. (We might also decrease the number of - // vertices, or keep them the same number.) - new_points.reserve(num_source_points + 1); - - LPoint2 last_point = source_points[num_source_points - 1]._p; - bool last_is_in = !is_right(last_point - from2d, delta2d); - bool all_in = last_is_in; - for (size_t pi = 0; pi < num_source_points; ++pi) { - const LPoint2 &this_point = source_points[pi]._p; - bool this_is_in = !is_right(this_point - from2d, delta2d); - - // There appears to be a compiler bug in gcc 4.0: we need to extract this - // comparison outside of the if statement. - bool crossed_over = (this_is_in != last_is_in); - if (crossed_over) { - // We have just crossed over the clipping line. Find the point of - // intersection. - LVector2 d = this_point - last_point; - PN_stdfloat denom = (a * d[0] + b * d[1]); - if (denom != 0.0) { - PN_stdfloat t = -(a * last_point[0] + b * last_point[1] + c) / denom; - LPoint2 p = last_point + t * d; - - new_points.push_back(PointDef(p[0], p[1])); - last_is_in = this_is_in; - } + int m = u | v; + if (m == 7) { + double tmin = DBL_MAX; + LPoint3 vertex = get_point_aabb(v); + if (intersect_segment_capsule(t, from, delta, vertex, + get_point_aabb(v ^ 4), radius_sq)) { + tmin = std::min(t, tmin); } - - if (this_is_in) { - // We are behind the clipping line. Keep the point. - new_points.push_back(PointDef(this_point[0], this_point[1])); - } else { - all_in = false; + if (intersect_segment_capsule(t, from, delta, vertex, + get_point_aabb(v ^ 2), radius_sq)) { + tmin = std::min(t, tmin); } - - last_point = this_point; - } - - return all_in; -} - -/** - * Returns the linear distance from the 2-d point to the nearest part of the - * polygon defined by the points vector. The result is negative if the point - * is within the polygon. - */ -PN_stdfloat CollisionBox:: -dist_to_polygon(const LPoint2 &p, const PointDef *points, size_t num_points) const { - // We know that that the polygon is convex and is defined with the points in - // counterclockwise order. Therefore, we simply compare the signed distance - // to each line segment; we ignore any negative values, and take the minimum - // of all the positive values. - - // If all values are negative, the point is within the polygon; we therefore - // return an arbitrary negative result. - - bool got_dist = false; - PN_stdfloat best_dist = -1.0f; - - for (size_t i = 0; i < num_points - 1; ++i) { - PN_stdfloat d = dist_to_line_segment(p, points[i]._p, points[i + 1]._p, - points[i]._v); - if (d >= 0.0f) { - if (!got_dist || d < best_dist) { - best_dist = d; - got_dist = true; - } + if (intersect_segment_capsule(t, from, delta, vertex, + get_point_aabb(v ^ 1), radius_sq)) { + tmin = std::min(t, tmin); } - } - - PN_stdfloat d = dist_to_line_segment(p, points[num_points - 1]._p, points[0]._p, - points[num_points - 1]._v); - if (d >= 0.0f) { - if (!got_dist || d < best_dist) { - best_dist = d; - //got_dist = true; - } - } - - return best_dist; -} - -/** - * Returns the linear distance of p to the line segment defined by f and t, - * where v = (t - f).normalize(). The result is negative if p is left of the - * line, positive if it is right of the line. If the result is positive, it - * is constrained by endpoints of the line segment (i.e. the result might be - * larger than it would be for a straight distance-to-line test). If the - * result is negative, we don't bother. - */ -PN_stdfloat CollisionBox:: -dist_to_line_segment(const LPoint2 &p, - const LPoint2 &f, const LPoint2 &t, - const LVector2 &v) { - LVector2 v1 = (p - f); - PN_stdfloat d = (v1[0] * v[1] - v1[1] * v[0]); - if (d < 0.0f) { - return d; - } - - // Compute the nearest point on the line. - LPoint2 q = p + LVector2(-v[1], v[0]) * d; - - // Now constrain that point to the line segment. - if (v[0] > 0.0f) { - // X+ - if (v[1] > 0.0f) { - // Y+ - if (v[0] > v[1]) { - // X-dominant. - if (q[0] < f[0]) { - return (p - f).length(); - } if (q[0] > t[0]) { - return (p - t).length(); - } else { - return d; - } - } else { - // Y-dominant. - if (q[1] < f[1]) { - return (p - f).length(); - } if (q[1] > t[1]) { - return (p - t).length(); - } else { - return d; - } - } - } else { - // Y- - if (v[0] > -v[1]) { - // X-dominant. - if (q[0] < f[0]) { - return (p - f).length(); - } if (q[0] > t[0]) { - return (p - t).length(); - } else { - return d; - } - } else { - // Y-dominant. - if (q[1] > f[1]) { - return (p - f).length(); - } if (q[1] < t[1]) { - return (p - t).length(); - } else { - return d; - } - } - } - } else { - // X- - if (v[1] > 0.0f) { - // Y+ - if (-v[0] > v[1]) { - // X-dominant. - if (q[0] > f[0]) { - return (p - f).length(); - } if (q[0] < t[0]) { - return (p - t).length(); - } else { - return d; - } - } else { - // Y-dominant. - if (q[1] < f[1]) { - return (p - f).length(); - } if (q[1] > t[1]) { - return (p - t).length(); - } else { - return d; - } - } - } else { - // Y- - if (-v[0] > -v[1]) { - // X-dominant. - if (q[0] > f[0]) { - return (p - f).length(); - } if (q[0] < t[0]) { - return (p - t).length(); - } else { - return d; - } - } else { - // Y-dominant. - if (q[1] > f[1]) { - return (p - f).length(); - } if (q[1] < t[1]) { - return (p - t).length(); - } else { - return d; - } - } - } - } -} - -/** - * Returns true if the indicated point is within the polygon's 2-d space, - * false otherwise. - */ -bool CollisionBox:: -point_is_inside(const LPoint2 &p, const CollisionBox::Points &points) const { - // We insist that the polygon be convex. This makes things a bit simpler. - // In the case of a convex polygon, defined with points in counterclockwise - // order, a point is interior to the polygon iff the point is not right of - // each of the edges. - for (int i = 0; i < (int)points.size() - 1; i++) { - if (is_right(p - points[i]._p, points[i+1]._p - points[i]._p)) { + if (tmin == DBL_MAX) { return false; } + t = tmin; } - if (is_right(p - points[points.size() - 1]._p, - points[0]._p - points[points.size() - 1]._p)) { - return false; + else if ((m & (m - 1)) != 0) { + // There's just one edge to test. + LPoint3 edge_v1 = get_point_aabb(u ^ 7); + LPoint3 edge_v2 = get_point_aabb(v); + return intersect_segment_capsule(t, from, delta, edge_v1, edge_v2, radius_sq); } return true; } -/** - * Now that the _p members of the given points array have been computed, go - * back and compute all of the _v members. - */ -void CollisionBox:: -compute_vectors(Points &points) { - size_t num_points = points.size(); - for (size_t i = 0; i < num_points; i++) { - points[i]._v = points[(i + 1) % num_points]._p - points[i]._p; - points[i]._v.normalize(); - } -} - /** * Factory method to generate a CollisionBox object */ @@ -1427,28 +1110,42 @@ write_datagram(BamWriter *manager, Datagram &me) { _center.write_datagram(me); _min.write_datagram(me); _max.write_datagram(me); - for(int i=0; i < 8; i++) { - _vertex[i].write_datagram(me); + for (int i = 0; i < 8; ++i) { + get_point_aabb(i).write_datagram(me); } - PN_stdfloat x = _vertex[0].get_x() - _center.get_x(); - PN_stdfloat y = _vertex[0].get_y() - _center.get_y(); - PN_stdfloat z = _vertex[0].get_z() - _center.get_z(); + LPoint3 vertex = get_point_aabb(0); + PN_stdfloat x = vertex.get_x() - _center.get_x(); + PN_stdfloat y = vertex.get_y() - _center.get_y(); + PN_stdfloat z = vertex.get_z() - _center.get_z(); PN_stdfloat radius = sqrt(x * x + y * y + z * z); me.add_stdfloat(radius); me.add_stdfloat(x); me.add_stdfloat(y); me.add_stdfloat(z); - for(int i=0; i < 6; i++) { + for (int i = 0; i < 6; ++i) { _planes[i].write_datagram(me); } - for(int i=0; i < 6; i++) { - _to_2d_mat[i].write_datagram(me); + LMatrix4 to_2d_mat[6]; + for (int i = 0; i < 6; ++i) { + LMatrix4 to_3d_mat; + look_at(to_3d_mat, -get_plane(i).get_normal(), + LVector3(0.0f, 0.0f, 1.0f), CS_zup_right); + to_3d_mat.set_row(3, get_plane(i).get_point()); + + to_2d_mat[i].invert_from(to_3d_mat); + to_2d_mat[i].write_datagram(me); } - for(int i=0; i < 6; i++) { + for (int i = 0; i < 6; ++i) { me.add_uint16(4); + LPoint2 points[4]; for (size_t j = 0; j < 4; j++) { - _points[i][j]._p.write_datagram(me); - _points[i][j]._v.write_datagram(me); + points[j] = (get_point(plane_def[i][j]) * to_2d_mat[i]).get_xz(); + } + for (size_t j = 0; j < 4; j++) { + LPoint2 vec = points[(i + 1) % 4] - points[i]; + vec.normalize(); + points[j].write_datagram(me); + vec.write_datagram(me); } } } @@ -1478,25 +1175,28 @@ fillin(DatagramIterator& scan, BamReader* manager) { _center.read_datagram(scan); _min.read_datagram(scan); _max.read_datagram(scan); - for(int i=0; i < 8; i++) { - _vertex[i].read_datagram(scan); + for (int i = 0; i < 8; ++i) { + LPoint3 vertex; + vertex.read_datagram(scan); } scan.get_stdfloat(); scan.get_stdfloat(); scan.get_stdfloat(); scan.get_stdfloat(); - for(int i=0; i < 6; i++) { + for (int i = 0; i < 6; ++i) { _planes[i].read_datagram(scan); } - for(int i=0; i < 6; i++) { - _to_2d_mat[i].read_datagram(scan); + for (int i = 0; i < 6; ++i) { + LMatrix4 to_2d_mat; + to_2d_mat.read_datagram(scan); } - for(int i=0; i < 6; i++) { + for (int i = 0; i < 6; ++i) { size_t size = scan.get_uint16(); - nassertv(size == 4); - for (size_t j = 0; j < size; j++) { - _points[i][j]._p.read_datagram(scan); - _points[i][j]._v.read_datagram(scan); + for (size_t j = 0; j < size; ++j) { + LPoint2 p; + LVector2 v; + p.read_datagram(scan); + v.read_datagram(scan); } } } diff --git a/panda/src/collide/collisionBox.h b/panda/src/collide/collisionBox.h index 1b2489b9fc..95588a8acf 100644 --- a/panda/src/collide/collisionBox.h +++ b/panda/src/collide/collisionBox.h @@ -49,7 +49,6 @@ public: virtual void output(std::ostream &out) const; INLINE static void flush_level(); - void setup_box(); PUBLISHED: INLINE int get_num_points() const; @@ -94,12 +93,14 @@ protected: bool intersects_line(double &t1, double &t2, const LPoint3 &from, const LVector3 &delta, PN_stdfloat inflate_size=0) const; + bool intersects_capsule(double &t, + const LPoint3 &from, const LVector3 &delta, + PN_stdfloat radius_sq) const; private: LPoint3 _center; LPoint3 _min; LPoint3 _max; - LPoint3 _vertex[8]; // Each of the Eight Vertices of the Box LPlane _planes[6]; //Points to each of the six sides of the Box static const int plane_def[6][4]; @@ -107,49 +108,6 @@ private: static PStatCollector _volume_pcollector; static PStatCollector _test_pcollector; -private: - INLINE static bool is_right(const LVector2 &v1, const LVector2 &v2); - INLINE static PN_stdfloat dist_to_line(const LPoint2 &p, - const LPoint2 &f, const LVector2 &v); - static PN_stdfloat dist_to_line_segment(const LPoint2 &p, - const LPoint2 &f, const LPoint2 &t, - const LVector2 &v); - -public: - class PointDef { - public: - PointDef() = default; - INLINE PointDef(const LPoint2 &p, const LVector2 &v); - INLINE PointDef(PN_stdfloat x, PN_stdfloat y); - INLINE PointDef(const PointDef ©); - INLINE void operator = (const PointDef ©); - - LPoint2 _p; // the point in 2-d space - LVector2 _v; // the normalized vector to the next point - }; - typedef pvector Points; - - static void compute_vectors(Points &points); - void draw_polygon(GeomNode *viz_geom_node, GeomNode *bounds_viz_geom_node, - const Points &points) const; - - bool point_is_inside(const LPoint2 &p, const Points &points) const; - PN_stdfloat dist_to_polygon(const LPoint2 &p, const PointDef *points, size_t num_points) const; - - void setup_points(int plane); - INLINE LPoint2 to_2d(const LVecBase3 &point3d, int plane) const; - INLINE void calc_to_3d_mat(LMatrix4 &to_3d_mat, int plane) const; - INLINE static LPoint3 to_3d(const LVecBase2 &point2d, const LMatrix4 &to_3d_mat); - bool clip_polygon(Points &new_points, const PointDef *source_points, - size_t num_source_points, const LPlane &plane, - int plane_no) const; - bool apply_clip_plane(Points &new_points, const ClipPlaneAttrib *cpa, - const TransformState *net_transform, int plane_no) const; - -private: - PointDef _points[6][4]; // one set of points for each of the six planes that make up the box - LMatrix4 _to_2d_mat[6]; - public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &me); diff --git a/panda/src/collide/collisionPolygon_ext.cxx b/panda/src/collide/collisionPolygon_ext.cxx index 22ada8c344..3f7d6503aa 100644 --- a/panda/src/collide/collisionPolygon_ext.cxx +++ b/panda/src/collide/collisionPolygon_ext.cxx @@ -72,6 +72,9 @@ convert_points(pvector &vec, PyObject *points) { return false; } + bool success = true; + + Py_BEGIN_CRITICAL_SECTION(seq); PyObject **items = PySequence_Fast_ITEMS(seq); Py_ssize_t len = PySequence_Fast_GET_SIZE(seq); void *ptr; @@ -90,13 +93,14 @@ convert_points(pvector &vec, PyObject *points) { } else { Dtool_Raise_TypeError("Argument must be of LPoint3 type."); - Py_DECREF(seq); - return false; + success = false; + break; } } + Py_END_CRITICAL_SECTION(); Py_DECREF(seq); - return true; + return success; } #endif diff --git a/panda/src/collide/collisionSphere.cxx b/panda/src/collide/collisionSphere.cxx index b8323faa63..8f9dcb0ccb 100644 --- a/panda/src/collide/collisionSphere.cxx +++ b/panda/src/collide/collisionSphere.cxx @@ -145,44 +145,48 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { LPoint3 contact_point(into_intersection_point); PN_stdfloat actual_t = 0.0f; - LVector3 vec = from_b - into_center; - PN_stdfloat dist2 = dot(vec, vec); - if (dist2 > (into_radius + from_radius) * (into_radius + from_radius)) { - // No intersection with the current position. Check the delta from the - // previous frame. + LPoint3 from_a = from_b; + if (entry.get_respect_prev_transform()) { CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space(); - LPoint3 from_a = sphere->get_center() * wrt_prev_space->get_mat(); + if (wrt_prev_space != wrt_space) { + from_a = sphere->get_center() * wrt_prev_space->get_mat(); + } + } - if (!from_a.almost_equal(from_b)) { - LVector3 from_direction = from_b - from_a; - if (!intersects_line(t1, t2, from_a, from_direction, from_radius)) { - // No intersection. - return nullptr; - } + if (from_a.almost_equal(from_b)) { + LVector3 vec = from_b - into_center; + PN_stdfloat dist2 = dot(vec, vec); - if (t2 < 0.0 || t1 > 1.0) { - // Both intersection points are before the start of the segment or - // after the end of the segment. - return nullptr; - } - - // doubles, not floats, to satisfy min and max templates. - actual_t = min(1.0, max(0.0, t1)); - contact_point = from_a + actual_t * (from_b - from_a); - - if (t1 < 0.0) { - // Point a is within the sphere. The first intersection point is - // point a itself. - into_intersection_point = from_a; - } else { - // Point a is outside the sphere, and point b is either inside the - // sphere or beyond it. The first intersection point is at t1. - into_intersection_point = from_a + t1 * from_direction; - } - } else { - // No delta, therefore no intersection. + if (dist2 > (into_radius + from_radius) * (into_radius + from_radius)) { + // No intersection with the current position. return nullptr; } + } else { + LVector3 from_direction = from_b - from_a; + if (!intersects_line(t1, t2, from_a, from_direction, from_radius)) { + // No intersection. + return nullptr; + } + + if (t2 < 0.0 || t1 > 1.0) { + // Both intersection points are before the start of the segment or + // after the end of the segment. + return nullptr; + } + + // doubles, not floats, to satisfy min and max templates. + actual_t = min(1.0, max(0.0, t1)); + contact_point = from_a + actual_t * (from_b - from_a); + + if (t1 < 0.0) { + // Point a is within the sphere. The first intersection point is + // point a itself. + into_intersection_point = from_a; + } else { + // Point a is outside the sphere, and point b is either inside the + // sphere or beyond it. The first intersection point is at t1. + into_intersection_point = from_a + t1 * from_direction; + } } if (collide_cat.is_debug()) { diff --git a/panda/src/collide/collisionVisualizer.cxx b/panda/src/collide/collisionVisualizer.cxx index d8e70d11df..29d713badb 100644 --- a/panda/src/collide/collisionVisualizer.cxx +++ b/panda/src/collide/collisionVisualizer.cxx @@ -207,11 +207,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { PT(Geom) geom = new Geom(point_vdata); geom->add_primitive(points); - CullableObject *object = - new CullableObject(geom, point_state, - xform_data.get_internal_transform(trav)); - - trav->get_cull_handler()->record_object(object, trav); + trav->get_cull_handler()->record_object(CullableObject( + geom, point_state, xform_data.get_internal_transform(trav)), trav); } // Draw the normal vector at the surface point. @@ -236,11 +233,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { PT(Geom) geom = new Geom(line_vdata); geom->add_primitive(lines); - CullableObject *object = - new CullableObject(geom, empty_state, - xform_data.get_internal_transform(trav)); - - trav->get_cull_handler()->record_object(object, trav); + trav->get_cull_handler()->record_object(CullableObject( + geom, empty_state, xform_data.get_internal_transform(trav)), trav); } } } diff --git a/panda/src/cull/binCullHandler.cxx b/panda/src/cull/binCullHandler.cxx index 53feb15bd4..be944a281d 100644 --- a/panda/src/cull/binCullHandler.cxx +++ b/panda/src/cull/binCullHandler.cxx @@ -19,6 +19,6 @@ * This is called as each Geom is discovered by the CullTraverser. */ void BinCullHandler:: -record_object(CullableObject *object, const CullTraverser *traverser) { - _cull_result->add_object(object, traverser); +record_object(CullableObject &&object, const CullTraverser *traverser) { + _cull_result->add_object(std::move(object), traverser); } diff --git a/panda/src/cull/binCullHandler.h b/panda/src/cull/binCullHandler.h index afe73103ed..73d88824c3 100644 --- a/panda/src/cull/binCullHandler.h +++ b/panda/src/cull/binCullHandler.h @@ -28,7 +28,7 @@ class EXPCL_PANDA_CULL BinCullHandler : public CullHandler { public: INLINE BinCullHandler(CullResult *cull_result); - virtual void record_object(CullableObject *object, + virtual void record_object(CullableObject &&object, const CullTraverser *traverser); private: diff --git a/panda/src/cull/cullBinBackToFront.cxx b/panda/src/cull/cullBinBackToFront.cxx index 99f006b405..a8fa169304 100644 --- a/panda/src/cull/cullBinBackToFront.cxx +++ b/panda/src/cull/cullBinBackToFront.cxx @@ -23,18 +23,6 @@ TypeHandle CullBinBackToFront::_type_handle; -/** - * - */ -CullBinBackToFront:: -~CullBinBackToFront() { - Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - CullableObject *object = (*oi)._object; - delete object; - } -} - /** * Factory constructor for passing to the CullBinManager. */ diff --git a/panda/src/cull/cullBinBackToFront.h b/panda/src/cull/cullBinBackToFront.h index cfef2f4267..b950bddc28 100644 --- a/panda/src/cull/cullBinBackToFront.h +++ b/panda/src/cull/cullBinBackToFront.h @@ -33,7 +33,6 @@ public: INLINE CullBinBackToFront(const std::string &name, GraphicsStateGuardianBase *gsg, const PStatCollector &draw_region_pcollector); - virtual ~CullBinBackToFront(); static CullBin *make_bin(const std::string &name, GraphicsStateGuardianBase *gsg, diff --git a/panda/src/cull/cullBinFixed.cxx b/panda/src/cull/cullBinFixed.cxx index 7d4a4150c2..9d8ff46dcb 100644 --- a/panda/src/cull/cullBinFixed.cxx +++ b/panda/src/cull/cullBinFixed.cxx @@ -23,18 +23,6 @@ TypeHandle CullBinFixed::_type_handle; -/** - * - */ -CullBinFixed:: -~CullBinFixed() { - Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - CullableObject *object = (*oi)._object; - delete object; - } -} - /** * Factory constructor for passing to the CullBinManager. */ diff --git a/panda/src/cull/cullBinFixed.h b/panda/src/cull/cullBinFixed.h index 337283e2b3..fdaece4591 100644 --- a/panda/src/cull/cullBinFixed.h +++ b/panda/src/cull/cullBinFixed.h @@ -35,7 +35,6 @@ public: INLINE CullBinFixed(const std::string &name, GraphicsStateGuardianBase *gsg, const PStatCollector &draw_region_pcollector); - virtual ~CullBinFixed(); static CullBin *make_bin(const std::string &name, GraphicsStateGuardianBase *gsg, diff --git a/panda/src/cull/cullBinFrontToBack.cxx b/panda/src/cull/cullBinFrontToBack.cxx index 8ddc16745d..146eaaab58 100644 --- a/panda/src/cull/cullBinFrontToBack.cxx +++ b/panda/src/cull/cullBinFrontToBack.cxx @@ -23,18 +23,6 @@ TypeHandle CullBinFrontToBack::_type_handle; -/** - * - */ -CullBinFrontToBack:: -~CullBinFrontToBack() { - Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - CullableObject *object = (*oi)._object; - delete object; - } -} - /** * Factory constructor for passing to the CullBinManager. */ diff --git a/panda/src/cull/cullBinFrontToBack.h b/panda/src/cull/cullBinFrontToBack.h index b9ba66c043..15c1f80ccf 100644 --- a/panda/src/cull/cullBinFrontToBack.h +++ b/panda/src/cull/cullBinFrontToBack.h @@ -34,7 +34,6 @@ public: INLINE CullBinFrontToBack(const std::string &name, GraphicsStateGuardianBase *gsg, const PStatCollector &draw_region_pcollector); - virtual ~CullBinFrontToBack(); static CullBin *make_bin(const std::string &name, GraphicsStateGuardianBase *gsg, diff --git a/panda/src/cull/cullBinStateSorted.cxx b/panda/src/cull/cullBinStateSorted.cxx index 55c0607526..3d08802a48 100644 --- a/panda/src/cull/cullBinStateSorted.cxx +++ b/panda/src/cull/cullBinStateSorted.cxx @@ -22,18 +22,6 @@ TypeHandle CullBinStateSorted::_type_handle; -/** - * - */ -CullBinStateSorted:: -~CullBinStateSorted() { - Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - CullableObject *object = (*oi)._object; - delete object; - } -} - /** * Factory constructor for passing to the CullBinManager. */ diff --git a/panda/src/cull/cullBinStateSorted.h b/panda/src/cull/cullBinStateSorted.h index f97e41fa48..2e6486e348 100644 --- a/panda/src/cull/cullBinStateSorted.h +++ b/panda/src/cull/cullBinStateSorted.h @@ -37,7 +37,6 @@ public: INLINE CullBinStateSorted(const std::string &name, GraphicsStateGuardianBase *gsg, const PStatCollector &draw_region_pcollector); - virtual ~CullBinStateSorted(); static CullBin *make_bin(const std::string &name, GraphicsStateGuardianBase *gsg, diff --git a/panda/src/cull/cullBinUnsorted.cxx b/panda/src/cull/cullBinUnsorted.cxx index c633913a03..768ce35abf 100644 --- a/panda/src/cull/cullBinUnsorted.cxx +++ b/panda/src/cull/cullBinUnsorted.cxx @@ -19,18 +19,6 @@ TypeHandle CullBinUnsorted::_type_handle; -/** - * - */ -CullBinUnsorted:: -~CullBinUnsorted() { - Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - CullableObject *object = (*oi); - delete object; - } -} - /** * Factory constructor for passing to the CullBinManager. */ diff --git a/panda/src/cull/cullBinUnsorted.h b/panda/src/cull/cullBinUnsorted.h index 2dcf60a85f..bd31ea0a38 100644 --- a/panda/src/cull/cullBinUnsorted.h +++ b/panda/src/cull/cullBinUnsorted.h @@ -29,7 +29,6 @@ public: INLINE CullBinUnsorted(const std::string &name, GraphicsStateGuardianBase *gsg, const PStatCollector &draw_region_pcollector); - ~CullBinUnsorted(); static CullBin *make_bin(const std::string &name, GraphicsStateGuardianBase *gsg, diff --git a/panda/src/cull/drawCullHandler.cxx b/panda/src/cull/drawCullHandler.cxx index 78e27a0086..ac7ebf947f 100644 --- a/panda/src/cull/drawCullHandler.cxx +++ b/panda/src/cull/drawCullHandler.cxx @@ -25,17 +25,14 @@ * This is called as each Geom is discovered by the CullTraverser. */ void DrawCullHandler:: -record_object(CullableObject *object, const CullTraverser *traverser) { +record_object(CullableObject &&object, const CullTraverser *traverser) { // Munge vertices as needed for the GSG's requirements, and the object's // current state. bool force = !_gsg->get_effective_incomplete_render(); Thread *current_thread = traverser->get_current_thread(); - if (object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state, current_thread), traverser, force)) { + if (object.munge_geom(_gsg, _gsg->get_geom_munger(object._state, current_thread), traverser, force)) { // Now we can immediately draw the object. - draw(object, _gsg, force, current_thread); + draw(&object, _gsg, force, current_thread); } - - // Dispense with the object. - delete object; } diff --git a/panda/src/cull/drawCullHandler.h b/panda/src/cull/drawCullHandler.h index 5d8b5d3e41..127f1ee849 100644 --- a/panda/src/cull/drawCullHandler.h +++ b/panda/src/cull/drawCullHandler.h @@ -31,7 +31,7 @@ class EXPCL_PANDA_CULL DrawCullHandler : public CullHandler { public: INLINE DrawCullHandler(GraphicsStateGuardianBase *gsg); - virtual void record_object(CullableObject *object, + virtual void record_object(CullableObject &&object, const CullTraverser *traverser); private: diff --git a/panda/src/display/frameBufferProperties.cxx b/panda/src/display/frameBufferProperties.cxx index c6e1e9353f..4f27007cbc 100644 --- a/panda/src/display/frameBufferProperties.cxx +++ b/panda/src/display/frameBufferProperties.cxx @@ -305,11 +305,12 @@ int FrameBufferProperties:: get_buffer_mask() const { int mask = 0; - if (_property[FBP_back_buffers] > 0) { - mask = RenderBuffer::T_front | RenderBuffer::T_back; - } else { - mask = RenderBuffer::T_front; - } + //XXX rdb: some buffers only have a front buffer, some only a back buffer + //if (_property[FBP_back_buffers] > 0) { + mask = RenderBuffer::T_front | RenderBuffer::T_back; + //} else { + // mask = RenderBuffer::T_front; + //} if (_property[FBP_depth_bits] > 0) { mask |= RenderBuffer::T_depth; } diff --git a/panda/src/display/frameBufferProperties_ext.cxx b/panda/src/display/frameBufferProperties_ext.cxx index 96ed9d3afe..423d66d748 100644 --- a/panda/src/display/frameBufferProperties_ext.cxx +++ b/panda/src/display/frameBufferProperties_ext.cxx @@ -52,13 +52,14 @@ __setstate__(PyObject *self, PyObject *props) { PyObject *key, *value; Py_ssize_t pos = 0; + Py_BEGIN_CRITICAL_SECTION(props); while (PyDict_Next(props, &pos, &key, &value)) { // Look for a writable property on the type by this name. PyObject *descr = _PyType_Lookup(type, key); if (descr != nullptr && Py_TYPE(descr)->tp_descr_set != nullptr) { if (Py_TYPE(descr)->tp_descr_set(descr, self, value) < 0) { - return; + break; } } else { PyObject *key_repr = PyObject_Repr(key); @@ -67,9 +68,10 @@ __setstate__(PyObject *self, PyObject *props) { PyUnicode_AsUTF8(key_repr) ); Py_DECREF(key_repr); - return; + break; } } + Py_END_CRITICAL_SECTION(); } #endif // HAVE_PYTHON diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 27b8c2bf28..eb346a2b7d 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -63,6 +63,13 @@ #include #endif +#ifdef __APPLE__ +extern "C" { + void *objc_autoreleasePoolPush(); + void objc_autoreleasePoolPop(void *); +}; +#endif + using std::string; PT(GraphicsEngine) GraphicsEngine::_global_ptr; @@ -2586,6 +2593,11 @@ void GraphicsEngine::WindowRenderer:: do_frame(GraphicsEngine *engine, Thread *current_thread) { LightReMutexHolder holder(_wl_lock); +#ifdef __APPLE__ + // Enclose the entire frame in an autorelease pool. + void *pool = objc_autoreleasePoolPush(); +#endif + if (!_cull.empty()) { engine->cull_to_bins(_cull, current_thread); } @@ -2599,6 +2611,10 @@ do_frame(GraphicsEngine *engine, Thread *current_thread) { engine->process_events(_window, current_thread); } +#ifdef __APPLE__ + objc_autoreleasePoolPop(pool); +#endif + // If any GSG's on the list have no more outstanding pointers, clean them // up. (We are in the draw thread for all of these GSG's.) if (any_done_gsgs()) { @@ -2630,10 +2646,18 @@ void GraphicsEngine::WindowRenderer:: do_windows(GraphicsEngine *engine, Thread *current_thread) { LightReMutexHolder holder(_wl_lock); +#ifdef __APPLE__ + void *pool = objc_autoreleasePoolPush(); +#endif + engine->process_events(_window, current_thread); engine->make_contexts(_cdraw, current_thread); engine->make_contexts(_draw, current_thread); + +#ifdef __APPLE__ + objc_autoreleasePoolPop(pool); +#endif } /** diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index b2683dcdbe..11bffeb4a4 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -2201,7 +2201,7 @@ fetch_specified_light(const NodePath &np, LVecBase4f *into) { if (!node->is_of_type(PointLight::get_class_type())) { t *= lens->get_projection_mat() * shadow_bias_mat; } - *(LMatrix4f *)&into[Shader::LA_shadow_view_matrix] = t; + *(LMatrix4f *)&into[Shader::LA_shadow_view_matrix] = LCAST(float, t); } LVecBase3 atten = light->get_attenuation(); diff --git a/panda/src/display/windowProperties_ext.cxx b/panda/src/display/windowProperties_ext.cxx index 45b32e822c..d9975750b7 100644 --- a/panda/src/display/windowProperties_ext.cxx +++ b/panda/src/display/windowProperties_ext.cxx @@ -91,13 +91,14 @@ __setstate__(PyObject *self, PyObject *props) { PyObject *key, *value; Py_ssize_t pos = 0; + Py_BEGIN_CRITICAL_SECTION(props); while (PyDict_Next(props, &pos, &key, &value)) { // Look for a writable property on the type by this name. PyObject *descr = _PyType_Lookup(type, key); if (descr != nullptr && Py_TYPE(descr)->tp_descr_set != nullptr) { if (Py_TYPE(descr)->tp_descr_set(descr, self, value) < 0) { - return; + break; } } else { PyObject *key_repr = PyObject_Repr(key); @@ -106,9 +107,10 @@ __setstate__(PyObject *self, PyObject *props) { PyUnicode_AsUTF8(key_repr) ); Py_DECREF(key_repr); - return; + break; } } + Py_END_CRITICAL_SECTION(); } #endif // HAVE_PYTHON diff --git a/panda/src/distort/projectionScreen.cxx b/panda/src/distort/projectionScreen.cxx index 63120ea290..ff77e4448c 100644 --- a/panda/src/distort/projectionScreen.cxx +++ b/panda/src/distort/projectionScreen.cxx @@ -451,9 +451,11 @@ recompute_geom_node(const WorkingNodePath &np, LMatrix4 &rel_mat, int num_geoms = node->get_num_geoms(); for (int i = 0; i < num_geoms; i++) { PT(Geom) geom = node->modify_geom(i); - distort_cat.debug() - << " " << *node << " got geom " << geom - << ", cache_ref = " << geom->get_cache_ref_count() << "\n"; + if (distort_cat.is_debug()) { + distort_cat.debug() + << " " << *node << " got geom " << geom + << ", cache_ref = " << geom->get_cache_ref_count() << "\n"; + } geom->test_ref_count_integrity(); recompute_geom(geom, rel_mat); } diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index 90bd610455..e4ba7819d7 100644 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -5261,7 +5261,7 @@ FrameBufferProperties DXGraphicsStateGuardian9:: calc_fb_properties(DWORD cformat, DWORD dformat, DWORD multisampletype, DWORD multisamplequality) { FrameBufferProperties props; - int index=0; + int index=0, isfloat=0; int r=0, g=0, b=0, a=0; switch (cformat) { case D3DFMT_R8G8B8: r=8; g=8; b=8; a=0; break; @@ -5275,10 +5275,19 @@ calc_fb_properties(DWORD cformat, DWORD dformat, case D3DFMT_A8R3G3B2: r=3; g=3; b=2; a=8; break; case D3DFMT_X4R4G4B4: r=4; g=4; b=4; a=0; break; case D3DFMT_A2B10G10R10: r=10;g=10;b=10;a=2; break; + case D3DFMT_R16F: r=16; isfloat=1; break; + case D3DFMT_G16R16F: r=16; isfloat=1; break; + case D3DFMT_A16B16G16R16F:r=16; g=16; b=16; a=16; isfloat=1; break; + case D3DFMT_R32F: r=32; isfloat=1; break; + case D3DFMT_G32R32F: r=32; isfloat=1; break; + case D3DFMT_A32B32G32R32F:r=32; g=32; b=32; a=32; isfloat=1; break; case D3DFMT_A8P8: index=8; a=8; break; case D3DFMT_P8: index=8; a=0; break; default: break; } + if (isfloat > 0) { + props.set_float_color(true); + } if (index > 0) { props.set_rgb_color(0); props.set_indexed_color(1); diff --git a/panda/src/dxgsg9/dxTextureContext9.cxx b/panda/src/dxgsg9/dxTextureContext9.cxx index e8522f4167..34782f1a4e 100644 --- a/panda/src/dxgsg9/dxTextureContext9.cxx +++ b/panda/src/dxgsg9/dxTextureContext9.cxx @@ -231,6 +231,8 @@ create_texture(DXScreenData &scrn) { case 1: if (num_alpha_bits > 0) { _d3d_format = D3DFMT_A8; + } else if (tex->get_component_type() == Texture::T_float) { + _d3d_format = D3DFMT_R32F; } else { _d3d_format = D3DFMT_L8; } @@ -242,7 +244,11 @@ create_texture(DXScreenData &scrn) { _d3d_format = D3DFMT_R8G8B8; break; case 4: - _d3d_format = D3DFMT_A8R8G8B8; + if (tex->get_component_type() == Texture::T_float) { + _d3d_format = D3DFMT_A32B32G32R32F; + } else { + _d3d_format = D3DFMT_A8R8G8B8; + } break; } @@ -499,6 +505,13 @@ create_texture(DXScreenData &scrn) { break; } + if (num_color_channels == 1) { + CHECK_FOR_FMT(R32F); + CHECK_FOR_FMT(X8R8G8B8); + CHECK_FOR_FMT(R8G8B8); + break; + } + if (!((num_color_channels == 3) || (num_color_channels == 4))) break; //bail @@ -664,22 +677,7 @@ create_texture(DXScreenData &scrn) { } } case 8: - if (needs_luminance) { - // don't bother handling those other 8bit lum fmts like 4-4, since 16 - // 8-8 is usually supported too - nassertr(num_color_channels == 1, false); - - // look for native lum fmt first - CHECK_FOR_FMT(L8); - CHECK_FOR_FMT(L8); - - CHECK_FOR_FMT(R8G8B8); - CHECK_FOR_FMT(X8R8G8B8); - - CHECK_FOR_FMT(R5G6B5); - CHECK_FOR_FMT(X1R5G5B5); - - } else if (num_alpha_bits == 8) { + if (num_alpha_bits == 8) { // look for 16bpp A8L8, else 32-bit ARGB, else 16-4444. // skip 8bit alpha only (D3DFMT_A8), because I think only voodoo @@ -690,6 +688,21 @@ create_texture(DXScreenData &scrn) { CHECK_FOR_FMT(A8L8); CHECK_FOR_FMT(A8R8G8B8); CHECK_FOR_FMT(A4R4G4B4); + } else { + if (needs_luminance) { + // don't bother handling those other 8bit lum fmts like 4-4, since 16 + // 8-8 is usually supported too + nassertr(num_color_channels == 1, false); + + // look for native lum fmt first + CHECK_FOR_FMT(L8); + } + + CHECK_FOR_FMT(R8G8B8); + CHECK_FOR_FMT(X8R8G8B8); + + CHECK_FOR_FMT(R5G6B5); + CHECK_FOR_FMT(X1R5G5B5); } break; @@ -1563,8 +1576,8 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface9 *d3d_surface, for (DWORD y = 0; y < copy_height; y++) { source_word = ((DWORD*)surface_bytes) + x_window_offset; - memcpy(dest_line, source_word, byte_pitch); - dest_line += byte_pitch; + memcpy(dest_line, source_word, copy_width * 4); + dest_line += copy_width * 4; surface_bytes += byte_pitch; } } else { @@ -1614,8 +1627,8 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface9 *d3d_surface, // 24bpp texture case (numComponents == 3) for (DWORD y = 0; y < copy_height; y++) { source_byte = surface_bytes + x_window_offset * 3 * sizeof(BYTE); - memcpy(dest_byte, source_byte, byte_pitch); - dest_byte += byte_pitch; + memcpy(dest_byte, source_byte, copy_width * 3); + dest_byte += copy_width * 3; surface_bytes += byte_pitch; } } @@ -1808,16 +1821,21 @@ fill_d3d_texture_mipmap_pixels(int mip_level, int depth_index, D3DFORMAT source_ // Preallocate temporary buffer for conversion BYTE *temp_buffer = nullptr; - if (source_format == D3DFMT_A8 || component_width != 1) { - int num_pixels = width * height; - if (source_format == D3DFMT_A8) { - num_pixels *= 2; + if (source_format == D3DFMT_A8 || (component_width != 1 && _d3d_format != D3DFMT_R32F)) { + size_t num_bytes = width * height; + if (_d3d_format == D3DFMT_A32B32G32R32F && source_format == D3DFMT_A32B32G32R32F) { + num_bytes *= 16; + } + else if (source_format == D3DFMT_A8) { + num_bytes *= 2; source_format = D3DFMT_A8L8; source_row_byte_length *= 2; - } else { - num_pixels *= num_color_channels; } - temp_buffer = new BYTE[num_pixels]; + else { + num_bytes *= num_color_channels; + } + + temp_buffer = new BYTE[num_bytes]; if (!IS_VALID_PTR(temp_buffer)) { dxgsg9_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n"; @@ -1872,9 +1890,22 @@ fill_d3d_texture_mipmap_pixels(int mip_level, int depth_index, D3DFORMAT source_ *out_pixels = ((*source_pixels) << 8) | 0xFF; } } - pixels = (BYTE *)temp_buffer; + pixels = temp_buffer; } - else if (component_width != 1) { + else if (_d3d_format == D3DFMT_A32B32G32R32F && source_format == D3DFMT_A32B32G32R32F) { + // Swap red and blue components. + float *out_pixels = (float *)temp_buffer; + const float *source_pixels = (const float *)pixels; + size_t total_components = (size_t)width * (size_t)height * 4; + for (int i = 0; i < total_components; i += 4) { + out_pixels[i] = source_pixels[i + 2]; + out_pixels[i + 1] = source_pixels[i + 1]; + out_pixels[i + 2] = source_pixels[i + 0]; + out_pixels[i + 3] = source_pixels[i + 3]; + } + pixels = temp_buffer; + } + else if (component_width != 1 && _d3d_format != D3DFMT_R32F) { // Convert from 16-bit per channel (or larger) format down to 8-bit per // channel. This throws away precision in the original image, but dx8 // doesn't support high-precision images anyway. @@ -1887,7 +1918,7 @@ fill_d3d_texture_mipmap_pixels(int mip_level, int depth_index, D3DFORMAT source_ temp_buffer[i] = *source_pixels; source_pixels += component_width; } - pixels = (BYTE *)temp_buffer; + pixels = temp_buffer; } IDirect3DSurface9 *mip_surface = nullptr; @@ -2166,6 +2197,11 @@ fill_d3d_volume_texture_pixels(DXScreenData &scrn) { image_compression = Texture::CM_off; } + if (image.is_null() && tex->has_clear_color()) { + // Make an image, filled with the texture's clear color. + image = get_texture()->make_ram_image(); + } + if (image.is_null()) { // The texture doesn't have an image to load. That's ok; it might be a // texture we've rendered to by frame buffer operations or something. @@ -2189,17 +2225,22 @@ fill_d3d_volume_texture_pixels(DXScreenData &scrn) { // Preallocate temporary buffer for conversion BYTE *temp_buffer = nullptr; - if (_d3d_format == D3DFMT_A8 || component_width != 1) { - int num_pixels = orig_width * orig_height * orig_depth; - if (_d3d_format == D3DFMT_A8) { - num_pixels *= 2; + if (_d3d_format == D3DFMT_A8 || (component_width != 1 && _d3d_format != D3DFMT_R32F)) { + size_t num_bytes = orig_width * orig_height * orig_depth; + if (_d3d_format == D3DFMT_A32B32G32R32F && source_format == D3DFMT_A32B32G32R32F) { + num_bytes *= 16; + } + else if (_d3d_format == D3DFMT_A8) { + num_bytes *= 2; source_format = D3DFMT_A8L8; source_row_byte_length *= 2; source_page_byte_length *= 2; - } else { - num_pixels *= num_color_channels; } - temp_buffer = new BYTE[num_pixels]; + else { + num_bytes *= num_color_channels; + } + + temp_buffer = new BYTE[num_bytes]; if (!IS_VALID_PTR(temp_buffer)) { dxgsg9_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n"; @@ -2270,9 +2311,22 @@ fill_d3d_volume_texture_pixels(DXScreenData &scrn) { } } - pixels = (BYTE *)temp_buffer; + pixels = temp_buffer; } - else if (component_width != 1) { + else if (_d3d_format == D3DFMT_A32B32G32R32F && source_format == D3DFMT_A32B32G32R32F) { + // Swap red and blue components. + float *out_pixels = (float *)temp_buffer; + const float *source_pixels = (const float *)pixels; + size_t total_components = (size_t)orig_width * (size_t)orig_height * (size_t)orig_depth * 4; + for (int i = 0; i < total_components; i += 4) { + out_pixels[i] = source_pixels[i + 2]; + out_pixels[i + 1] = source_pixels[i + 1]; + out_pixels[i + 2] = source_pixels[i + 0]; + out_pixels[i + 3] = source_pixels[i + 3]; + } + pixels = temp_buffer; + } + else if (component_width != 1 && _d3d_format != D3DFMT_R32F) { // Convert from 16-bit per channel (or larger) format down to 8-bit per // channel. This throws away precision in the original image, but dx8 // doesn't support high-precision images anyway. @@ -2285,7 +2339,7 @@ fill_d3d_volume_texture_pixels(DXScreenData &scrn) { temp_buffer[i] = *source_pixels; source_pixels += component_width; } - pixels = (BYTE *)temp_buffer; + pixels = temp_buffer; } // filtering may be done here if texture if targetsize != origsize @@ -2410,6 +2464,20 @@ get_bits_per_pixel(Texture::Format format, int *alphbits) { *alphbits = 32; return 128; + case Texture::F_r16: + return 16; + case Texture::F_rg16: + return 16 * 2; + case Texture::F_rgb16: + return 16 * 3; + + case Texture::F_r32: + return 32; + case Texture::F_rg32: + return 32 * 2; + case Texture::F_rgb32: + return 32 * 3; + case Texture::F_srgb: return 24; case Texture::F_srgb_alpha: diff --git a/panda/src/dxgsg9/dxgsg9base.h b/panda/src/dxgsg9/dxgsg9base.h index 1d26d98ec5..6d0939c70a 100644 --- a/panda/src/dxgsg9/dxgsg9base.h +++ b/panda/src/dxgsg9/dxgsg9base.h @@ -157,8 +157,8 @@ typedef enum { D24S8_FLAG = FLG(20), D32_FLAG = FLG(21), INTZ_FLAG = FLG(22), - W11V11U10_FLAG = FLG(23), - A2W10V10U10_FLAG = FLG(24), + R32F_FLAG = FLG(23), + A32B32G32R32F_FLAG =FLG(24), ATI1_FLAG = FLG(25), ATI2_FLAG = FLG(26), DXT1_FLAG = FLG(27), diff --git a/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx b/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx index c09916fded..d43febe03e 100644 --- a/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx +++ b/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx @@ -45,9 +45,10 @@ wdxGraphicsBuffer9(GraphicsEngine *engine, GraphicsPipe *pipe, _color_backing_store = nullptr; _depth_backing_store = nullptr; - // is this correct ??? Since the pbuffer never gets flipped, we get - // screenshots from the same buffer we draw into. - _screenshot_buffer_type = _draw_buffer_type; + // Since the pbuffer never gets flipped, we get screenshots from the same + // buffer we draw into, which is the back buffer. + _draw_buffer_type = RenderBuffer::T_back; + _screenshot_buffer_type = RenderBuffer::T_back; _shared_depth_buffer = 0; _debug = 0; @@ -414,7 +415,7 @@ rebuild_bitplanes() { _depth_backing_store->Release(); _depth_backing_store = nullptr; } - if (!_depth_backing_store) { + if (!_depth_backing_store && _saved_depth_buffer != nullptr) { hr = _dxgsg -> _d3d_device -> CreateDepthStencilSurface (bitplane_x, bitplane_y, _saved_depth_desc.Format, _saved_depth_desc.MultiSampleType, _saved_depth_desc.MultiSampleQuality, @@ -758,10 +759,19 @@ open_buffer() { dxgsg9_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL; return false; } - hr = _saved_depth_buffer -> GetDesc (&_saved_depth_desc); - if (!SUCCEEDED (hr)) { - dxgsg9_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL; - return false; + if (_saved_depth_buffer) { + hr = _saved_depth_buffer -> GetDesc (&_saved_depth_desc); + if (!SUCCEEDED (hr)) { + dxgsg9_cat.error ( ) << "GetDesc " << D3DERRORSTRING(hr) FL; + return false; + } + } else { + ZeroMemory(&_saved_depth_desc, sizeof(_saved_depth_desc)); + } + if (_fb_properties.get_alpha_bits() > 0 && + _saved_color_desc.Format == D3DFMT_X8R8G8B8) { + // Add alpha if we didn't have it and we do need it. + _saved_color_desc.Format = D3DFMT_A8R8G8B8; } _fb_properties = _dxgsg-> calc_fb_properties(_saved_color_desc.Format, diff --git a/panda/src/dxgsg9/wdxGraphicsPipe9.cxx b/panda/src/dxgsg9/wdxGraphicsPipe9.cxx index 8cb8b9782f..1e9222a637 100644 --- a/panda/src/dxgsg9/wdxGraphicsPipe9.cxx +++ b/panda/src/dxgsg9/wdxGraphicsPipe9.cxx @@ -862,8 +862,8 @@ void Init_D3DFORMAT_map() { INSERT_ELEM(D24S8); INSERT_ELEM(D32); INSERT_ELEM(INTZ); -// NOT IN DX9 INSERT_ELEM(W11V11U10); - INSERT_ELEM(A2W10V10U10); + INSERT_ELEM(R32F); + INSERT_ELEM(A32B32G32R32F); INSERT_ELEM(ATI1); INSERT_ELEM(ATI2); INSERT_ELEM(DXT1); @@ -923,7 +923,11 @@ const char *D3DFormatStr(D3DFORMAT fmt) { CASESTR(D3DFMT_VERTEXDATA); CASESTR(D3DFMT_INDEX16); CASESTR(D3DFMT_INDEX32); + CASESTR(D3DFMT_R16F); + CASESTR(D3DFMT_G16R16F); CASESTR(D3DFMT_A16B16G16R16F); + CASESTR(D3DFMT_R32F); + CASESTR(D3DFMT_G32R32F); CASESTR(D3DFMT_A32B32G32R32F); } diff --git a/panda/src/dxgsg9/wdxGraphicsWindow9.cxx b/panda/src/dxgsg9/wdxGraphicsWindow9.cxx index b1694b5613..329a5d21b3 100644 --- a/panda/src/dxgsg9/wdxGraphicsWindow9.cxx +++ b/panda/src/dxgsg9/wdxGraphicsWindow9.cxx @@ -243,6 +243,7 @@ close_window() { DXGraphicsStateGuardian9::set_cg_device(nullptr); _dxgsg->release_swap_chain(&_wcontext); + _dxgsg = nullptr; WinGraphicsWindow::close_window(); } @@ -1187,7 +1188,7 @@ reset_device_resize_window(UINT new_xsize, UINT new_ysize) { if (wdxdisplay9_cat.is_debug()) { wdxdisplay9_cat.debug() << "swapchain is " << _wcontext._swap_chain << "\n"; } - _gsg->mark_new(); + _dxgsg->mark_new(); init_resized_window(); return retval; } diff --git a/panda/src/egg/eggNode_ext.cxx b/panda/src/egg/eggNode_ext.cxx index 3056e40d6d..eee7523459 100644 --- a/panda/src/egg/eggNode_ext.cxx +++ b/panda/src/egg/eggNode_ext.cxx @@ -24,13 +24,10 @@ __reduce__() const { extern struct Dtool_PyTypedObject Dtool_EggNode; // Find the parse_egg_node function in this module. - PyObject *sys_modules = PyImport_GetModuleDict(); - nassertr_always(sys_modules != nullptr, nullptr); - PyObject *module_name = PyObject_GetAttrString((PyObject *)&Dtool_EggNode, "__module__"); nassertr_always(module_name != nullptr, nullptr); - PyObject *module = PyDict_GetItem(sys_modules, module_name); + PyObject *module = PyImport_GetModule(module_name); Py_DECREF(module_name); nassertr_always(module != nullptr, nullptr); @@ -40,6 +37,7 @@ __reduce__() const { } else { func = PyObject_GetAttrString(module, "parse_egg_node"); } + Py_DECREF(module); nassertr_always(func != nullptr, nullptr); // Get the egg syntax to pass to the parse_egg_node function. diff --git a/panda/src/event/asyncFuture_ext.cxx b/panda/src/event/asyncFuture_ext.cxx index 44163e9be6..5ec7d080cb 100644 --- a/panda/src/event/asyncFuture_ext.cxx +++ b/panda/src/event/asyncFuture_ext.cxx @@ -146,6 +146,8 @@ static PyObject *gen_next_asyncfuture(PyObject *self) { PyObject *result = get_done_result(future); if (result != nullptr) { PyErr_SetObject(PyExc_StopIteration, result); + // PyErr_SetObject increased the reference count, so we no longer need our reference. + Py_DECREF(result); } return nullptr; } @@ -173,7 +175,7 @@ set_result(PyObject *result) { else if (DtoolInstance_Check(result)) { // If this is a Python subclass of a C++ type, fall through to below, since // we don't want to lose that extra information. - if (Py_TYPE(result) == (PyTypeObject *)DtoolInstance_TYPE(result)) { + if (Py_IS_TYPE(result, Dtool_GetPyTypeObject(DtoolInstance_TYPE(result)))) { void *ptr; if ((ptr = DtoolInstance_UPCAST(result, Dtool_TypedWritableReferenceCount))) { _this->set_result((TypedWritableReferenceCount *)ptr); diff --git a/panda/src/event/pythonTask.cxx b/panda/src/event/pythonTask.cxx index 44b0984559..d2515a9312 100644 --- a/panda/src/event/pythonTask.cxx +++ b/panda/src/event/pythonTask.cxx @@ -174,9 +174,15 @@ get_args() { PyTuple_SET_ITEM(with_task, i, Py_NewRef(item)); } - this->ref(); - PyObject *self = DTool_CreatePyInstance(this, Dtool_PythonTask, true, false); - PyTuple_SET_ITEM(with_task, num_args, self); + // Check whether we have a Python wrapper. This is not the case if the + // object has been created by C++ and never been exposed to Python code. + if (__self__ == nullptr) { + // A __self__ instance does not exist, let's create one now. + this->ref(); + __self__ = DTool_CreatePyInstance(this, Dtool_PythonTask, true, false); + } + + PyTuple_SET_ITEM(with_task, num_args, Py_NewRef(__self__)); return with_task; } else { @@ -294,13 +300,13 @@ __setattr__(PyObject *self, PyObject *attr, PyObject *v) { if (!PyUnicode_Check(attr)) { PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", - attr->ob_type->tp_name); + Py_TYPE(attr)->tp_name); return -1; } PyObject *descr = _PyType_Lookup(Py_TYPE(self), attr); if (descr != nullptr) { - descrsetfunc f = descr->ob_type->tp_descr_set; + descrsetfunc f = Py_TYPE(descr)->tp_descr_set; if (f != nullptr) { return f(descr, self, v); } @@ -357,11 +363,9 @@ PyObject *PythonTask:: __getattribute__(PyObject *self, PyObject *attr) const { // We consult the instance dict first, since the user may have overridden a // method or something. - PyObject *item = PyDict_GetItem(__dict__, attr); - - if (item != nullptr) { - // PyDict_GetItem returns a borrowed reference. - return Py_NewRef(item); + PyObject *item; + if (PyDict_GetItemRef(__dict__, attr, &item) > 0) { + return item; } return PyObject_GenericGetAttr(self, attr); @@ -465,7 +469,7 @@ cancel() { #endif // Shortcut for unextended AsyncFuture. - if (Py_TYPE(_fut_waiter) == (PyTypeObject *)&Dtool_AsyncFuture) { + if (Py_IS_TYPE(_fut_waiter, Dtool_GetPyTypeObject(&Dtool_AsyncFuture))) { AsyncFuture *fut = (AsyncFuture *)DtoolInstance_VOID_PTR(_fut_waiter); if (!fut->done()) { fut->cancel(); @@ -713,7 +717,7 @@ do_python_task() { _retrieved_exception = false; if (task_cat.is_debug()) { - if (_exception != nullptr && Py_TYPE(_exception) == &PyType_Type) { + if (_exception != nullptr && Py_IS_TYPE(_exception, &PyType_Type)) { task_cat.debug() << *this << " received " << ((PyTypeObject *)_exception)->tp_name << " from coroutine.\n"; } else { @@ -858,7 +862,7 @@ do_python_task() { PyMethodDef *meth = nullptr; if (PyCFunction_Check(result)) { meth = ((PyCFunctionObject *)result)->m_ml; - } else if (Py_TYPE(result) == &PyMethodDescr_Type) { + } else if (Py_IS_TYPE(result, &PyMethodDescr_Type)) { meth = ((PyMethodDescrObject *)result)->d_method; } @@ -1004,11 +1008,16 @@ call_owner_method(const char *method_name) { void PythonTask:: call_function(PyObject *function) { if (function != Py_None) { - this->ref(); - PyObject *self = DTool_CreatePyInstance(this, Dtool_PythonTask, true, false); - PyObject *result = PyObject_CallOneArg(function, self); + // Check whether we have a Python wrapper. This is not the case if the + // object has been created by C++ and never been exposed to Python code. + if (__self__ == nullptr) { + // A __self__ instance does not exist, let's create one now. + this->ref(); + __self__ = DTool_CreatePyInstance(this, Dtool_PythonTask, true, false); + } + + PyObject *result = PyObject_CallOneArg(function, __self__); Py_XDECREF(result); - Py_DECREF(self); } } diff --git a/panda/src/express/CMakeLists.txt b/panda/src/express/CMakeLists.txt index b7e18ef397..035097afa3 100644 --- a/panda/src/express/CMakeLists.txt +++ b/panda/src/express/CMakeLists.txt @@ -148,7 +148,7 @@ set(P3EXPRESS_IGATEEXT composite_sources(p3express P3EXPRESS_SOURCES) add_component_library(p3express SYMBOL BUILDING_PANDA_EXPRESS ${P3EXPRESS_SOURCES} ${P3EXPRESS_HEADERS}) -target_link_libraries(p3express p3pandabase p3interrogatedb p3prc p3dtool +target_link_libraries(p3express p3pandabase p3dconfig p3prc p3dtool PKG::ZLIB PKG::OPENSSL) target_interrogate(p3express ALL EXTENSIONS ${P3EXPRESS_IGATEEXT}) diff --git a/panda/src/express/datagram_ext.I b/panda/src/express/datagram_ext.I index 70a71a8b44..494a76188e 100644 --- a/panda/src/express/datagram_ext.I +++ b/panda/src/express/datagram_ext.I @@ -47,7 +47,7 @@ __reduce__() const { } extern struct Dtool_PyTypedObject Dtool_Datagram; - PyObject *tp = (PyObject *)&Dtool_Datagram._PyType; + PyObject *tp = (PyObject *)Dtool_GetPyTypeObject(&Dtool_Datagram); PyObject *result = PyTuple_New(2); PyTuple_SET_ITEM(result, 0, Py_NewRef(tp)); diff --git a/panda/src/express/memoryUsage.cxx b/panda/src/express/memoryUsage.cxx index bdc785222a..21161a025b 100644 --- a/panda/src/express/memoryUsage.cxx +++ b/panda/src/express/memoryUsage.cxx @@ -16,7 +16,6 @@ #include "trueClock.h" #include "typedReferenceCount.h" #include "mutexImpl.h" -#include "interrogate_request.h" #if defined(_MSC_VER) && defined(_DEBUG) #include diff --git a/panda/src/express/pointerToArray_ext.I b/panda/src/express/pointerToArray_ext.I index 3406a67263..849f993cba 100644 --- a/panda/src/express/pointerToArray_ext.I +++ b/panda/src/express/pointerToArray_ext.I @@ -96,7 +96,7 @@ __init__(PyObject *self, PyObject *source) { // Now construct the internal list by copying the elements one-at-a-time // from Python. - PyObject *dict = DtoolInstance_TYPE(self)->_PyType.tp_dict; + PyObject *dict = Dtool_GetPyTypeObject(DtoolInstance_TYPE(self))->tp_dict; PyObject *push_back = PyDict_GetItemString(dict, "push_back"); if (push_back == nullptr) { PyErr_BadArgument(); @@ -106,12 +106,13 @@ __init__(PyObject *self, PyObject *source) { // We need to initialize the this pointer before we can call push_back. DtoolInstance_INIT_PTR(self, this->_this); + Py_BEGIN_CRITICAL_SECTION(source); Py_ssize_t size = PySequence_Size(source); this->_this->reserve(size); for (Py_ssize_t i = 0; i < size; ++i) { PyObject *item = PySequence_GetItem(source, i); if (item == nullptr) { - return; + break; } PyObject *result = PyObject_CallFunctionObjArgs(push_back, self, item, nullptr); Py_DECREF(item); @@ -121,10 +122,11 @@ __init__(PyObject *self, PyObject *source) { PyErr_Format(PyExc_TypeError, "Element %zd in sequence passed to PointerToArray " "constructor could not be added", i); - return; + break; } Py_DECREF(result); } + Py_END_CRITICAL_SECTION(); } /** diff --git a/panda/src/express/virtualFileMountRamdisk.cxx b/panda/src/express/virtualFileMountRamdisk.cxx index feda85d1f6..2d0449d41d 100644 --- a/panda/src/express/virtualFileMountRamdisk.cxx +++ b/panda/src/express/virtualFileMountRamdisk.cxx @@ -30,6 +30,7 @@ TypeHandle VirtualFileMountRamdisk::Directory::_type_handle; */ VirtualFileMountRamdisk:: VirtualFileMountRamdisk() : _root("") { + _root.local_object(); } /** @@ -477,6 +478,10 @@ PT(VirtualFileMountRamdisk::FileBase) VirtualFileMountRamdisk::Directory:: do_find_file(const string &filename) const { size_t slash = filename.find('/'); if (slash == string::npos) { + if (filename.empty()) { + return (FileBase *)this; + } + // Search for a file within the local directory. FileBase tfile(filename); tfile.local_object(); diff --git a/panda/src/express/virtualFileSystem.cxx b/panda/src/express/virtualFileSystem.cxx index 37c220f4ca..1f67b98840 100644 --- a/panda/src/express/virtualFileSystem.cxx +++ b/panda/src/express/virtualFileSystem.cxx @@ -1206,7 +1206,7 @@ scan_mount_points(vector_string &names, const Filename &path) const { mount_point[prefix.length()] == '/') { // This mount point is below the indicated path. Is it only one // directory below? - string basename = mount_point.substr(prefix.length()); + string basename = mount_point.substr(prefix.length() + 1); if (basename.find('/') == string::npos) { // No embedded slashes, so it's only one directory below. names.push_back(basename); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index c50cfddb4f..1b3326a78c 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -24,6 +24,7 @@ #include "geomTrifans.h" #include "geomLines.h" #include "geomLinestrips.h" +#include "geomPatches.h" #include "geomPoints.h" #include "geomVertexReader.h" #include "graphicsWindow.h" @@ -188,16 +189,22 @@ static const string default_vshader = "in vec4 p3d_MultiTexCoord0;\n" "out vec3 texcoord;\n" "out vec4 color;\n" + "uniform mat4 p3d_ModelViewProjectionMatrix;\n" #else "#version 100\n" "precision mediump float;\n" "attribute vec4 p3d_Vertex;\n" "attribute vec4 p3d_Color;\n" "attribute vec4 p3d_MultiTexCoord0;\n" - "varying vec3 texcoord;\n" "varying lowp vec4 color;\n" -#endif + "#ifdef GL_FRAGMENT_PRECISION_HIGH\n" + "varying highp vec3 texcoord;\n" + "uniform highp mat4 p3d_ModelViewProjectionMatrix;\n" + "#else\n" + "varying mediump vec3 texcoord;\n" "uniform mat4 p3d_ModelViewProjectionMatrix;\n" + "#endif\n" +#endif "uniform mat4 p3d_TextureMatrix;\n" "uniform vec4 p3d_ColorScale;\n" "void main(void) {\n" @@ -265,7 +272,11 @@ static const string default_fshader = #else "#version 100\n" "precision mediump float;\n" - "varying vec3 texcoord;\n" + "#ifdef GL_FRAGMENT_PRECISION_HIGH\n" + "varying highp vec3 texcoord;\n" + "#else\n" + "varying mediump vec3 texcoord;\n" + "#endif\n" "varying lowp vec4 color;\n" "uniform lowp sampler2D p3d_Texture0;\n" "uniform lowp vec4 p3d_TexAlphaOnly;\n" @@ -5707,7 +5718,7 @@ draw_patches(const GeomPrimitivePipelineReader *reader, bool force) { } #ifndef OPENGLES - _glPatchParameteri(GL_PATCH_VERTICES, reader->get_object()->get_num_vertices_per_primitive()); + _glPatchParameteri(GL_PATCH_VERTICES, ((const GeomPatches *)reader->get_object())->get_num_vertices_per_primitive()); #ifdef SUPPORT_IMMEDIATE_MODE if (_use_sender) { diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 2fa9c43cfc..f411bb9fcc 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -1839,7 +1839,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { << " is bound to image unit " << binding << "\n"; } - if (binding >= _glsl_img_inputs.size()) { + if (binding >= (GLint)_glsl_img_inputs.size()) { _glsl_img_inputs.resize(binding + 1); } diff --git a/panda/src/gobj/geomPatches.cxx b/panda/src/gobj/geomPatches.cxx index f5fe9711d0..63ee7fcd1e 100644 --- a/panda/src/gobj/geomPatches.cxx +++ b/panda/src/gobj/geomPatches.cxx @@ -71,21 +71,6 @@ get_primitive_type() const { return PT_patches; } -/** - * If the primitive type is a simple type in which all primitives have the - * same number of vertices, like patches, returns the number of vertices per - * primitive. If the primitive type is a more complex type in which different - * primitives might have different numbers of vertices, for instance a - * triangle strip, returns 0. - * - * In the case of GeomPatches, this returns the fixed number that was - * specified to the constructor. - */ -int GeomPatches:: -get_num_vertices_per_primitive() const { - return _num_vertices_per_patch; -} - /** * Calls the appropriate method on the GSG to draw the primitive. */ diff --git a/panda/src/gobj/geomPatches.h b/panda/src/gobj/geomPatches.h index 85cda81e59..92c84b58c4 100644 --- a/panda/src/gobj/geomPatches.h +++ b/panda/src/gobj/geomPatches.h @@ -32,7 +32,9 @@ public: virtual PT(GeomPrimitive) make_copy() const; virtual PrimitiveType get_primitive_type() const; - virtual int get_num_vertices_per_primitive() const; + virtual int get_num_vertices_per_primitive() const final { + return _num_vertices_per_patch; + } public: virtual bool draw(GraphicsStateGuardianBase *gsg, diff --git a/panda/src/gobj/internalName_ext.cxx b/panda/src/gobj/internalName_ext.cxx index c7a145f23c..ab8e49eec8 100644 --- a/panda/src/gobj/internalName_ext.cxx +++ b/panda/src/gobj/internalName_ext.cxx @@ -74,7 +74,7 @@ PyObject *Extension:: __reduce__() const { std::string name = _this->get_name(); return Py_BuildValue("(N(s#))", - PyObject_GetAttrString((PyObject *)&Dtool_InternalName._PyType, "make"), name.c_str(), name.size()); + PyObject_GetAttrString((PyObject *)Dtool_GetPyTypeObject(&Dtool_InternalName), "make"), name.c_str(), name.size()); } #endif // HAVE_PYTHON diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 59ddcdc61e..2afe0f0320 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -10183,13 +10183,15 @@ do_write_datagram_header(CData *cdata, BamWriter *manager, Datagram &me, bool &h << "Texture file " << cdata->_fullpath << " found as " << filename << "\n"; } - if (!has_bam_dir || !alpha_filename.make_relative_to(bam_dir, true)) { - alpha_filename.find_on_searchpath(get_model_path()); - } - if (gobj_cat.is_debug()) { - gobj_cat.debug() - << "Alpha image " << cdata->_alpha_fullpath - << " found as " << alpha_filename << "\n"; + if (!alpha_filename.empty()) { + if (!has_bam_dir || !alpha_filename.make_relative_to(bam_dir, true)) { + alpha_filename.find_on_searchpath(get_model_path()); + } + if (gobj_cat.is_debug()) { + gobj_cat.debug() + << "Alpha image " << cdata->_alpha_fullpath + << " found as " << alpha_filename << "\n"; + } } break; diff --git a/panda/src/gobj/textureCollection_ext.cxx b/panda/src/gobj/textureCollection_ext.cxx index 127bba9ac5..46e9920280 100644 --- a/panda/src/gobj/textureCollection_ext.cxx +++ b/panda/src/gobj/textureCollection_ext.cxx @@ -31,13 +31,14 @@ __init__(PyObject *self, PyObject *sequence) { return; } + Py_BEGIN_CRITICAL_SECTION(fast); Py_ssize_t size = PySequence_Fast_GET_SIZE(fast); _this->reserve(size); for (int i = 0; i < size; ++i) { PyObject *item = PySequence_Fast_GET_ITEM(fast, i); if (item == nullptr) { - return; + break; } Texture *tex; @@ -48,13 +49,12 @@ __init__(PyObject *self, PyObject *sequence) { stream << "Element " << i << " in sequence passed to TextureCollection constructor is not a Texture"; std::string str = stream.str(); PyErr_SetString(PyExc_TypeError, str.c_str()); - Py_DECREF(fast); - return; + break; } else { _this->add_texture(tex); } } - + Py_END_CRITICAL_SECTION(); Py_DECREF(fast); } diff --git a/panda/src/grutil/pipeOcclusionCullTraverser.I b/panda/src/grutil/pipeOcclusionCullTraverser.I index d5e8685afd..9d51d18504 100644 --- a/panda/src/grutil/pipeOcclusionCullTraverser.I +++ b/panda/src/grutil/pipeOcclusionCullTraverser.I @@ -42,8 +42,8 @@ get_occlusion_mask() const { * */ INLINE PipeOcclusionCullTraverser::PendingObject:: -PendingObject(CullableObject *object) : - _object(object) +PendingObject(CullableObject &&object) : + _object(std::move(object)) { } diff --git a/panda/src/grutil/pipeOcclusionCullTraverser.cxx b/panda/src/grutil/pipeOcclusionCullTraverser.cxx index 62828319b3..ab0e859cea 100644 --- a/panda/src/grutil/pipeOcclusionCullTraverser.cxx +++ b/panda/src/grutil/pipeOcclusionCullTraverser.cxx @@ -217,28 +217,19 @@ end_traverse() { _current_query = nullptr; _next_query = nullptr; - PendingObjects::iterator oi; - for (oi = _pending_objects.begin(); oi != _pending_objects.end(); ++oi) { - PendingObject &pobj = (*oi); + for (PendingObject &pobj : _pending_objects) { if (pobj._query == nullptr) { _occlusion_untested_pcollector.add_level(1); - _true_cull_handler->record_object(pobj._object, this); + _true_cull_handler->record_object(std::move(pobj._object), this); } else { int num_fragments = pobj._query->get_num_fragments(); if (num_fragments != 0) { _occlusion_passed_pcollector.add_level(1); - _true_cull_handler->record_object(pobj._object, this); + _true_cull_handler->record_object(std::move(pobj._object), this); } else { _occlusion_failed_pcollector.add_level(1); - delete pobj._object; } } - - // The CullableObject has by now either been recorded (which will - // eventually delete it) or deleted directly. -#ifndef NDEBUG - pobj._object = nullptr; -#endif // NDEBUG } _pending_objects.clear(); CullTraverser::end_traverse(); @@ -363,9 +354,9 @@ traverse_below(CullTraverserData &data) { * the end of the scene. */ void PipeOcclusionCullTraverser:: -record_object(CullableObject *object, const CullTraverser *traverser) { +record_object(CullableObject &&object, const CullTraverser *traverser) { nassertv(traverser == this); - PendingObject pobj(object); + PendingObject pobj(std::move(object)); Thread *current_thread = get_current_thread(); @@ -379,13 +370,13 @@ record_object(CullableObject *object, const CullTraverser *traverser) { // ancestor. Don't perform another one. pobj._query = _current_query; - } else if (object->_geom->get_nested_vertices(current_thread) < min_occlusion_vertices) { + } else if (pobj._object._geom->get_nested_vertices(current_thread) < min_occlusion_vertices) { // This object is too small to bother testing for occlusions. } else { // Issue an occlusion test for this object. - CPT(BoundingVolume) vol = object->_geom->get_bounds(current_thread); - CPT(TransformState) net_transform = _inv_cs_world_transform->compose(object->_internal_transform); + CPT(BoundingVolume) vol = pobj._object._geom->get_bounds(current_thread); + CPT(TransformState) net_transform = _inv_cs_world_transform->compose(pobj._object._internal_transform); CPT(TransformState) internal_transform; CPT(Geom) geom; if (get_volume_viz(vol, geom, net_transform, internal_transform)) { @@ -394,7 +385,7 @@ record_object(CullableObject *object, const CullTraverser *traverser) { } } - _pending_objects.push_back(pobj); + _pending_objects.push_back(std::move(pobj)); } /** @@ -608,14 +599,13 @@ perform_occlusion_test(const Geom *geom, const TransformState *net_transform, gsg->begin_occlusion_query(); - CullableObject *viz = - new CullableObject(geom, _solid_test_state, internal_transform); + CullableObject viz(geom, _solid_test_state, internal_transform); static ConfigVariableBool test_occlude("test-occlude", false); if (test_occlude) { - _true_cull_handler->record_object(viz, _internal_trav); + _true_cull_handler->record_object(std::move(viz), _internal_trav); } else { - _internal_cull_handler->record_object(viz, _internal_trav); + _internal_cull_handler->record_object(std::move(viz), _internal_trav); } PT(OcclusionQueryContext) query = gsg->end_occlusion_query(); @@ -654,13 +644,9 @@ show_results(int num_fragments, const Geom *geom, TransparencyAttrib::make(TransparencyAttrib::M_alpha), ColorAttrib::make_flat(color)); - CullableObject *internal_viz = - new CullableObject(geom, state, internal_transform); - _internal_cull_handler->record_object(internal_viz, _internal_trav); + _internal_cull_handler->record_object(CullableObject(geom, state, internal_transform), _internal_trav); // Also render the viz in the main scene. internal_transform = get_scene()->get_cs_world_transform()->compose(net_transform); - CullableObject *main_viz = - new CullableObject(geom, state, internal_transform); - _true_cull_handler->record_object(main_viz, this); + _true_cull_handler->record_object(CullableObject(geom, state, internal_transform), this); } diff --git a/panda/src/grutil/pipeOcclusionCullTraverser.h b/panda/src/grutil/pipeOcclusionCullTraverser.h index d41c5acff4..f193b997e6 100644 --- a/panda/src/grutil/pipeOcclusionCullTraverser.h +++ b/panda/src/grutil/pipeOcclusionCullTraverser.h @@ -39,7 +39,7 @@ class GraphicsStateGuardian; * in grutil instead, for lack of any better ideas. */ class EXPCL_PANDA_GRUTIL PipeOcclusionCullTraverser : public CullTraverser, - public CullHandler { + public CullHandler { PUBLISHED: explicit PipeOcclusionCullTraverser(GraphicsOutput *host); PipeOcclusionCullTraverser(const PipeOcclusionCullTraverser ©) = delete; @@ -59,7 +59,7 @@ protected: virtual bool is_in_view(CullTraverserData &data); virtual void traverse_below(CullTraverserData &data); - virtual void record_object(CullableObject *object, + virtual void record_object(CullableObject &&object, const CullTraverser *traverser); private: @@ -110,10 +110,10 @@ private: class PendingObject { public: - INLINE PendingObject(CullableObject *object); + INLINE PendingObject(CullableObject &&object); INLINE ~PendingObject(); - CullableObject *_object; + CullableObject _object; PT(OcclusionQueryContext) _query; }; typedef pvector PendingObjects; diff --git a/panda/src/grutil/shaderTerrainMesh.cxx b/panda/src/grutil/shaderTerrainMesh.cxx index 339db9c383..4b42a35938 100644 --- a/panda/src/grutil/shaderTerrainMesh.cxx +++ b/panda/src/grutil/shaderTerrainMesh.cxx @@ -544,8 +544,8 @@ void ShaderTerrainMesh::add_for_draw(CullTraverser *trav, CullTraverserData &dat state = state->set_attrib(current_shader_attrib, 10000); // Emit chunk - CullableObject *object = new CullableObject(_chunk_geom, std::move(state), std::move(modelview_transform)); - trav->get_cull_handler()->record_object(object, trav); + trav->get_cull_handler()->record_object(CullableObject( + _chunk_geom, std::move(state), std::move(modelview_transform)), trav); // After rendering, increment the view index ++_current_view_index; diff --git a/panda/src/iphone/ipfreeze.py b/panda/src/iphone/ipfreeze.py index 8762b95b63..a18a20b9fc 100755 --- a/panda/src/iphone/ipfreeze.py +++ b/panda/src/iphone/ipfreeze.py @@ -66,7 +66,7 @@ if __name__ == '__main__': libs = '' libs += ' -framework Foundation -framework UIKit' if link_all_static: - libs += ' -lframework -lputil -lcollide -lpgraph -lchan -ltext -lpnmimage -lpnmimagetypes -levent -leffects -lgobj -ldisplay -lmathutil -lexpress -ldgraph -ldevice -ltform -llinmath -lpstatclient -lpanda -lglstuff -lrecorder -lpgui -lchar -lpipeline -lpandabase -llerp -lgsgbase -ldownloader -lparametrics -lpgraphnodes -lcull -lgrutil -lnet -lmovies -lnativenet -laudio -linterrogatedb -ldconfig -ldtoolutil -ldtoolbase -lprc -liphonedisplay -lpandaexpress -lpanda' + libs += ' -lframework -lputil -lcollide -lpgraph -lchan -ltext -lpnmimage -lpnmimagetypes -levent -leffects -lgobj -ldisplay -lmathutil -lexpress -ldgraph -ldevice -ltform -llinmath -lpstatclient -lpanda -lglstuff -lrecorder -lpgui -lchar -lpipeline -lpandabase -llerp -lgsgbase -ldownloader -lparametrics -lpgraphnodes -lcull -lgrutil -lnet -lmovies -lnativenet -laudio -ldconfig -ldtoolutil -ldtoolbase -lprc -liphonedisplay -lpandaexpress -lpanda' libs += ' -lphysics -lparticlesystem -lpandaphysics' libs += ' -ldistort -leffects -lpandafx' libs += ' -ldirectbase -ldcparser -ldeadrec -ldistributed -lhttp -lshowbase -linterval -lmotiontrail -ldirect' diff --git a/panda/src/linmath/compose_matrix_src.cxx b/panda/src/linmath/compose_matrix_src.cxx index 180f498e84..c3bb401c89 100644 --- a/panda/src/linmath/compose_matrix_src.cxx +++ b/panda/src/linmath/compose_matrix_src.cxx @@ -327,12 +327,21 @@ unwind_yup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) { xz = normalize(xz); // Compute the rotation about the +Y (up) axis. This is yaw, or "heading". - FLOATTYPE heading = rad_2_deg(((FLOATTYPE)catan2(xz[0], xz[1]))); + FLOATTYPE heading = catan2(xz[0], xz[1]); // Unwind the heading, and continue. FLOATNAME(LMatrix3) rot_y; - rot_y.set_rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f), - CS_yup_right); + rot_y._m(0, 0) = xz[1]; + rot_y._m(0, 1) = 0; + rot_y._m(0, 2) = xz[0]; + + rot_y._m(1, 0) = 0; + rot_y._m(1, 1) = 1; + rot_y._m(1, 2) = 0; + + rot_y._m(2, 0) = -xz[0]; + rot_y._m(2, 1) = 0; + rot_y._m(2, 2) = xz[1]; x = x * rot_y; y = y * rot_y; @@ -343,12 +352,21 @@ unwind_yup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) { yz = normalize(yz); // Compute the rotation about the +X (right) axis. This is pitch. - FLOATTYPE pitch = rad_2_deg((FLOATTYPE)(-catan2(yz[0], yz[1]))); + FLOATTYPE pitch = -catan2(yz[0], yz[1]); // Unwind the pitch. FLOATNAME(LMatrix3) rot_x; - rot_x.set_rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f), - CS_yup_right); + rot_x._m(0, 0) = 1; + rot_x._m(0, 1) = 0; + rot_x._m(0, 2) = 0; + + rot_x._m(1, 0) = 0; + rot_x._m(1, 1) = yz[1]; + rot_x._m(1, 2) = yz[0]; + + rot_x._m(2, 0) = 0; + rot_x._m(2, 1) = -yz[0]; + rot_x._m(2, 2) = yz[1]; x = x * rot_x; y = y * rot_x; @@ -359,12 +377,21 @@ unwind_yup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) { xy = normalize(xy); // Compute the rotation about the +Z (back) axis. This is roll. - FLOATTYPE roll = -rad_2_deg(((FLOATTYPE)catan2(xy[1], xy[0]))); + FLOATTYPE roll = -catan2(xy[1], xy[0]); // Unwind the roll from the axes, and continue. FLOATNAME(LMatrix3) rot_z; - rot_z.set_rotate_mat_normaxis(roll, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f), - CS_yup_right); + rot_z._m(0, 0) = xy[0]; + rot_z._m(0, 1) = -xy[1]; + rot_z._m(0, 2) = 0; + + rot_z._m(1, 0) = xy[1]; + rot_z._m(1, 1) = xy[0]; + rot_z._m(1, 2) = 0; + + rot_z._m(2, 0) = 0; + rot_z._m(2, 1) = 0; + rot_z._m(2, 2) = 1; x = x * rot_z; y = y * rot_z; @@ -376,9 +403,9 @@ unwind_yup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) { mat.set_row(2, z); // Return the three rotation components. - hpr[0] = heading; - hpr[1] = pitch; - hpr[2] = roll; + hpr[0] = rad_2_deg(heading); + hpr[1] = rad_2_deg(pitch); + hpr[2] = rad_2_deg(roll); } /** @@ -402,12 +429,21 @@ unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) { xy = normalize(xy); // Compute the rotation about the +Z (up) axis. This is yaw, or "heading". - FLOATTYPE heading = -rad_2_deg(((FLOATTYPE)catan2(xy[0], xy[1]))); + FLOATTYPE heading = -catan2(xy[0], xy[1]); // Unwind the heading, and continue. FLOATNAME(LMatrix3) rot_z; - rot_z.set_rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f), - CS_zup_right); + rot_z._m(0, 0) = xy[1]; + rot_z._m(0, 1) = xy[0]; + rot_z._m(0, 2) = 0; + + rot_z._m(1, 0) = -xy[0]; + rot_z._m(1, 1) = xy[1]; + rot_z._m(1, 2) = 0; + + rot_z._m(2, 0) = 0; + rot_z._m(2, 1) = 0; + rot_z._m(2, 2) = 1; x = x * rot_z; y = y * rot_z; @@ -418,12 +454,21 @@ unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) { yz = normalize(yz); // Compute the rotation about the +X (right) axis. This is pitch. - FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)catan2(yz[1], yz[0]))); + FLOATTYPE pitch = catan2(yz[1], yz[0]); // Unwind the pitch. FLOATNAME(LMatrix3) rot_x; - rot_x.set_rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f), - CS_zup_right); + rot_x._m(0, 0) = 1; + rot_x._m(0, 1) = 0; + rot_x._m(0, 2) = 0; + + rot_x._m(1, 0) = 0; + rot_x._m(1, 1) = yz[0]; + rot_x._m(1, 2) = -yz[1]; + + rot_x._m(2, 0) = 0; + rot_x._m(2, 1) = yz[1]; + rot_x._m(2, 2) = yz[0]; x = x * rot_x; y = y * rot_x; @@ -434,12 +479,21 @@ unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) { xz = normalize(xz); // Compute the rotation about the -Y (back) axis. This is roll. - FLOATTYPE roll = -rad_2_deg(((FLOATTYPE)catan2(xz[1], xz[0]))); + FLOATTYPE roll = -catan2(xz[1], xz[0]); // Unwind the roll from the axes, and continue. FLOATNAME(LMatrix3) rot_y; - rot_y.set_rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f), - CS_zup_right); + rot_y._m(0, 0) = xz[0]; + rot_y._m(0, 1) = 0; + rot_y._m(0, 2) = -xz[1]; + + rot_y._m(1, 0) = 0; + rot_y._m(1, 1) = 1; + rot_y._m(1, 2) = 0; + + rot_y._m(2, 0) = xz[1]; + rot_y._m(2, 1) = 0; + rot_y._m(2, 2) = xz[0]; x = x * rot_y; y = y * rot_y; @@ -451,9 +505,9 @@ unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) { mat.set_row(2, z); // Return the three rotation components. - hpr[0] = heading; - hpr[1] = pitch; - hpr[2] = roll; + hpr[0] = rad_2_deg(heading); + hpr[1] = rad_2_deg(pitch); + hpr[2] = rad_2_deg(roll); } /** @@ -473,10 +527,12 @@ decompose_matrix(const FLOATNAME(LMatrix3) &mat, cs = get_default_coordinate_system(); } +#ifdef _DEBUG if (linmath_cat.is_debug()) { linmath_cat.debug() << "decomposing " << mat << " via cs " << cs << "\n"; } +#endif // Extract the rotation and scale, according to the coordinate system of // choice. @@ -534,10 +590,12 @@ decompose_matrix(const FLOATNAME(LMatrix3) &mat, return false; } +#ifdef _DEBUG if (linmath_cat.is_debug()) { linmath_cat.debug() << "after unwind, mat is " << new_mat << "\n"; } +#endif scale.set(new_mat(0, 0), new_mat(1, 1), new_mat(2, 2)); diff --git a/panda/src/linmath/dblnames.h b/panda/src/linmath/dblnames.h index a2e7363e3e..47d143713e 100644 --- a/panda/src/linmath/dblnames.h +++ b/panda/src/linmath/dblnames.h @@ -46,7 +46,8 @@ #define FLOATTYPE_REPR(v, str) do { \ double v_copy = (v); \ char *into_str = (str); \ - if ((double)(long long)v_copy == v_copy) { \ + if (v_copy < 1e16 && v_copy > -1e16 && \ + (double)(long long)v_copy == v_copy) { \ snprintf(into_str, 32, "%lld", (long long)v_copy); \ } else { \ pdtoa(v_copy, into_str); \ diff --git a/panda/src/linmath/fltnames.h b/panda/src/linmath/fltnames.h index a69d651f51..c634b97cac 100644 --- a/panda/src/linmath/fltnames.h +++ b/panda/src/linmath/fltnames.h @@ -46,8 +46,9 @@ #define FLOATTYPE_REPR(v, str) do { \ float v_copy = (v); \ char *into_str = (str); \ - if ((float)(int)v_copy == v_copy) { \ - snprintf(into_str, 32, "%d", (int)v_copy); \ + if (v_copy < 1e16f && v_copy > -1e16f && \ + (float)(long long)v_copy == v_copy) { \ + snprintf(into_str, 32, "%lld", (long long)v_copy); \ } else { \ pftoa(v_copy, into_str); \ } \ diff --git a/panda/src/linmath/lorientation_src.I b/panda/src/linmath/lorientation_src.I index 8cc56aa235..684f71118c 100644 --- a/panda/src/linmath/lorientation_src.I +++ b/panda/src/linmath/lorientation_src.I @@ -70,7 +70,7 @@ FLOATNAME(LOrientation)(const FLOATNAME(LMatrix4) &m) { */ INLINE_LINMATH FLOATNAME(LOrientation) FLOATNAME(LOrientation):: operator * (const FLOATNAME(LRotation) &other) const { - return multiply((FLOATNAME(LOrientation) &)other); + return multiply((const FLOATNAME(LOrientation) &)other); } /** @@ -80,5 +80,5 @@ operator * (const FLOATNAME(LRotation) &other) const { INLINE_LINMATH FLOATNAME(LOrientation) FLOATNAME(LOrientation):: operator * (const FLOATNAME(LQuaternion) &other) const { nassert_raise("LOrientation * LQuaternion is undefined; use LOrientation * LRotation or LQuaternion * LQuaternion"); - return multiply((FLOATNAME(LOrientation) &)other); + return multiply((const FLOATNAME(LOrientation) &)other); } diff --git a/panda/src/linmath/lvecBase2_ext_src.I b/panda/src/linmath/lvecBase2_ext_src.I index f860917257..adb8e793e9 100644 --- a/panda/src/linmath/lvecBase2_ext_src.I +++ b/panda/src/linmath/lvecBase2_ext_src.I @@ -183,7 +183,7 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) { #endif } else { PyErr_Format(PyExc_ValueError, "'%.200s' object is not iterable", - assign->ob_type->tp_name); + Py_TYPE(assign)->tp_name); } return -1; } diff --git a/panda/src/linmath/lvecBase3_ext_src.I b/panda/src/linmath/lvecBase3_ext_src.I index 67bc4b65b0..07a83a010d 100644 --- a/panda/src/linmath/lvecBase3_ext_src.I +++ b/panda/src/linmath/lvecBase3_ext_src.I @@ -187,7 +187,7 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) { #endif } else { PyErr_Format(PyExc_ValueError, "'%.200s' object is not iterable", - assign->ob_type->tp_name); + Py_TYPE(assign)->tp_name); } return -1; } diff --git a/panda/src/linmath/lvecBase4_ext_src.I b/panda/src/linmath/lvecBase4_ext_src.I index 9b396af666..40647bff42 100644 --- a/panda/src/linmath/lvecBase4_ext_src.I +++ b/panda/src/linmath/lvecBase4_ext_src.I @@ -196,7 +196,7 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) { #endif } else { PyErr_Format(PyExc_ValueError, "'%.200s' object is not iterable", - assign->ob_type->tp_name); + Py_TYPE(assign)->tp_name); } return -1; } diff --git a/panda/src/ode/odeSpace_ext.cxx b/panda/src/ode/odeSpace_ext.cxx index 4c6fb56161..27f4cbbb6a 100644 --- a/panda/src/ode/odeSpace_ext.cxx +++ b/panda/src/ode/odeSpace_ext.cxx @@ -72,7 +72,7 @@ collide(PyObject* arg, PyObject* callback) { nassertr(callback != nullptr, -1); if (!PyCallable_Check(callback)) { - PyErr_Format(PyExc_TypeError, "'%s' object is not callable", callback->ob_type->tp_name); + PyErr_Format(PyExc_TypeError, "'%s' object is not callable", Py_TYPE(callback)->tp_name); return -1; } else if (_this->get_id() == nullptr) { diff --git a/panda/src/ode/odeUtil_ext.cxx b/panda/src/ode/odeUtil_ext.cxx index e3115bfda6..545fbb6f1a 100644 --- a/panda/src/ode/odeUtil_ext.cxx +++ b/panda/src/ode/odeUtil_ext.cxx @@ -28,7 +28,7 @@ int Extension:: collide2(const OdeGeom &geom1, const OdeGeom &geom2, PyObject* arg, PyObject* callback) { nassertr(callback != nullptr, -1); if (!PyCallable_Check(callback)) { - PyErr_Format(PyExc_TypeError, "'%s' object is not callable", callback->ob_type->tp_name); + PyErr_Format(PyExc_TypeError, "'%s' object is not callable", Py_TYPE(callback)->tp_name); return -1; } else { _python_callback = Py_XNewRef(callback); diff --git a/panda/src/parametrics/ropeNode.cxx b/panda/src/parametrics/ropeNode.cxx index 5d49c2dda3..cf1e073c9b 100644 --- a/panda/src/parametrics/ropeNode.cxx +++ b/panda/src/parametrics/ropeNode.cxx @@ -329,10 +329,8 @@ render_thread(CullTraverser *trav, CullTraverserData &data, state = state->add_attrib(ColorAttrib::make_vertex()); } - CullableObject *object = - new CullableObject(geom, state, - data.get_internal_transform(trav)); - trav->get_cull_handler()->record_object(object, trav); + trav->get_cull_handler()->record_object(CullableObject( + std::move(geom), std::move(state), data.get_internal_transform(trav)), trav); } /** @@ -375,10 +373,8 @@ render_tape(CullTraverser *trav, CullTraverserData &data, state = state->add_attrib(ColorAttrib::make_vertex()); } - CullableObject *object = - new CullableObject(geom, state, - data.get_internal_transform(trav)); - trav->get_cull_handler()->record_object(object, trav); + trav->get_cull_handler()->record_object(CullableObject( + std::move(geom), std::move(state), data.get_internal_transform(trav)), trav); } /** @@ -428,10 +424,8 @@ render_billboard(CullTraverser *trav, CullTraverserData &data, state = state->add_attrib(ColorAttrib::make_vertex()); } - CullableObject *object = - new CullableObject(geom, state, - data.get_internal_transform(trav)); - trav->get_cull_handler()->record_object(object, trav); + trav->get_cull_handler()->record_object(CullableObject( + std::move(geom), std::move(state), data.get_internal_transform(trav)), trav); } /** @@ -489,10 +483,8 @@ render_tube(CullTraverser *trav, CullTraverserData &data, state = state->add_attrib(ColorAttrib::make_vertex()); } - CullableObject *object = - new CullableObject(geom, state, - data.get_internal_transform(trav)); - trav->get_cull_handler()->record_object(object, trav); + trav->get_cull_handler()->record_object(CullableObject( + std::move(geom), std::move(state), data.get_internal_transform(trav)), trav); } /** @@ -523,8 +515,16 @@ get_connected_segments(RopeNode::CurveSegments &curve_segments, LPoint3 point; result->eval_segment_point(segment, 0.0f, point); + // We need a bit more relaxed threshold to prevent breaks between + // segments, see GitHub issue #1325. +#ifdef STDFLOAT_DOUBLE + static const double threshold = 1.0e-8; +#else + static const float threshold = 1.0e-4f; +#endif + if (curve_segment == nullptr || - !point.almost_equal(last_point)) { + !point.almost_equal(last_point, threshold)) { // If the first point of this segment is different from the last point // of the previous segment, end the previous segment and begin a new // one. diff --git a/panda/src/parametrics/sheetNode.cxx b/panda/src/parametrics/sheetNode.cxx index 620a35512f..cac8409278 100644 --- a/panda/src/parametrics/sheetNode.cxx +++ b/panda/src/parametrics/sheetNode.cxx @@ -319,10 +319,8 @@ render_sheet(CullTraverser *trav, CullTraverserData &data, state = state->add_attrib(ColorAttrib::make_vertex()); } - CullableObject *object = - new CullableObject(geom, state, - data.get_internal_transform(trav)); - trav->get_cull_handler()->record_object(object, trav); + trav->get_cull_handler()->record_object(CullableObject( + std::move(geom), std::move(state), data.get_internal_transform(trav)), trav); } /** diff --git a/panda/src/pgraph/cullHandler.cxx b/panda/src/pgraph/cullHandler.cxx index b8f889706d..3350e0a6d7 100644 --- a/panda/src/pgraph/cullHandler.cxx +++ b/panda/src/pgraph/cullHandler.cxx @@ -40,10 +40,9 @@ CullHandler:: * expected to delete it later. */ void CullHandler:: -record_object(CullableObject *object, const CullTraverser *traverser) { - nout << *object->_geom << " " << *object->_internal_transform << " " - << *object->_state << "\n"; - delete object; +record_object(CullableObject &&object, const CullTraverser *traverser) { + nout << *object._geom << " " << *object._internal_transform << " " + << *object._state << "\n"; } /** diff --git a/panda/src/pgraph/cullHandler.h b/panda/src/pgraph/cullHandler.h index 9d42d6bad8..a5877d5eb9 100644 --- a/panda/src/pgraph/cullHandler.h +++ b/panda/src/pgraph/cullHandler.h @@ -30,7 +30,7 @@ public: CullHandler(); virtual ~CullHandler(); - virtual void record_object(CullableObject *object, + virtual void record_object(CullableObject &&object, const CullTraverser *traverser); virtual void end_traverse(); diff --git a/panda/src/pgraph/cullResult.I b/panda/src/pgraph/cullResult.I index 303a06dfd8..a0ea58eb3f 100644 --- a/panda/src/pgraph/cullResult.I +++ b/panda/src/pgraph/cullResult.I @@ -16,6 +16,7 @@ */ INLINE CullResult:: ~CullResult() { + delete_page(_page); } /** @@ -32,6 +33,19 @@ get_bin(int bin_index) { return make_new_bin(bin_index); } +/** + * Allocates memory for a new CullableObject that is associated with this + * CullResult. + */ +INLINE CullableObject *CullResult:: +alloc_object(CullableObject &&object) { + AllocationPage *page = _page; + if (page->_size >= page->_capacity) { + page = new_page(); + } + return new (page->_memory + sizeof(CullableObject) * (page->_size++)) CullableObject(std::move(object)); +} + /** * If the user configured flash-bin-binname, then update the object's state to * flash all the geometry in the bin. diff --git a/panda/src/pgraph/cullResult.cxx b/panda/src/pgraph/cullResult.cxx index b6b238f838..d4b1550935 100644 --- a/panda/src/pgraph/cullResult.cxx +++ b/panda/src/pgraph/cullResult.cxx @@ -61,6 +61,8 @@ CullResult(GraphicsStateGuardianBase *gsg, _gsg(gsg), _draw_region_pcollector(draw_region_pcollector) { + _page = &_first_page; + #ifdef DO_MEMORY_USAGE MemoryUsage::update_type(this, get_class_type()); #endif @@ -100,13 +102,13 @@ make_next() const { * the owner of the object pointer, and will eventually delete it. */ void CullResult:: -add_object(CullableObject *object, const CullTraverser *traverser) { +add_object(CullableObject &&object, const CullTraverser *traverser) { static const LColor flash_alpha_color(0.92, 0.96, 0.10, 1.0f); static const LColor flash_binary_color(0.21f, 0.67f, 0.24, 1.0f); static const LColor flash_multisample_color(0.78f, 0.05f, 0.81f, 1.0f); static const LColor flash_dual_color(0.92, 0.01f, 0.01f, 1.0f); - nassertv(object->_draw_callback != nullptr || object->_geom != nullptr); + nassertv(object._draw_callback != nullptr || object._geom != nullptr); bool force = !traverser->get_effective_incomplete_render(); Thread *current_thread = traverser->get_current_thread(); @@ -114,62 +116,60 @@ add_object(CullableObject *object, const CullTraverser *traverser) { // This is probably a good time to check for an auto rescale setting. const RescaleNormalAttrib *rescale; - object->_state->get_attrib_def(rescale); + object._state->get_attrib_def(rescale); if (rescale->get_mode() == RescaleNormalAttrib::M_auto) { RescaleNormalAttrib::Mode mode; - if (object->_internal_transform->has_identity_scale()) { + if (object._internal_transform->has_identity_scale()) { mode = RescaleNormalAttrib::M_none; - } else if (object->_internal_transform->has_uniform_scale()) { + } else if (object._internal_transform->has_uniform_scale()) { mode = RescaleNormalAttrib::M_rescale; } else { mode = RescaleNormalAttrib::M_normalize; } - object->_state = object->_state->compose(get_rescale_normal_state(mode)); + object._state = object._state->compose(get_rescale_normal_state(mode)); } // Check for a special wireframe setting. const RenderModeAttrib *rmode; - if (object->_state->get_attrib(rmode)) { + if (object._state->get_attrib(rmode)) { if (rmode->get_mode() == RenderModeAttrib::M_filled_wireframe) { - CullableObject *wireframe_part = new CullableObject(*object); + CullableObject wireframe_part(object); const ShaderAttrib *shader = nullptr; - object->_state->get_attrib(shader); - wireframe_part->_state = get_wireframe_overlay_state(rmode, shader); + object._state->get_attrib(shader); + wireframe_part._state = get_wireframe_overlay_state(rmode, shader); - if (wireframe_part->munge_geom - (_gsg, _gsg->get_geom_munger(wireframe_part->_state, current_thread), + if (wireframe_part.munge_geom + (_gsg, _gsg->get_geom_munger(wireframe_part._state, current_thread), traverser, force)) { int wireframe_bin_index = bin_manager->find_bin("fixed"); CullBin *bin = get_bin(wireframe_bin_index); nassertv(bin != nullptr); - check_flash_bin(wireframe_part->_state, bin_manager, wireframe_bin_index); - bin->add_object(wireframe_part, current_thread); - } else { - delete wireframe_part; + check_flash_bin(wireframe_part._state, bin_manager, wireframe_bin_index); + bin->add_object(alloc_object(std::move(wireframe_part)), current_thread); } - object->_state = object->_state->compose(get_wireframe_filled_state()); + object._state = object._state->compose(get_wireframe_filled_state()); } } // Check to see if there's a special transparency setting. const TransparencyAttrib *trans; - if (object->_state->get_attrib(trans)) { + if (object._state->get_attrib(trans)) { switch (trans->get_mode()) { case TransparencyAttrib::M_alpha: case TransparencyAttrib::M_premultiplied_alpha: // M_alpha implies an alpha-write test, so we don't waste time writing // 0-valued pixels. - object->_state = object->_state->compose(get_alpha_state()); - check_flash_transparency(object->_state, flash_alpha_color); + object._state = object._state->compose(get_alpha_state()); + check_flash_transparency(object._state, flash_alpha_color); break; case TransparencyAttrib::M_binary: // M_binary is implemented by explicitly setting the alpha test. - object->_state = object->_state->compose(get_binary_state()); - check_flash_transparency(object->_state, flash_binary_color); + object._state = object._state->compose(get_binary_state()); + check_flash_transparency(object._state, flash_binary_color); break; case TransparencyAttrib::M_multisample: @@ -177,14 +177,14 @@ add_object(CullableObject *object, const CullTraverser *traverser) { // The multisample modes are implemented using M_binary if the GSG in // use doesn't support multisample. if (!_gsg->get_supports_multisample()) { - object->_state = object->_state->compose(get_binary_state()); + object._state = object._state->compose(get_binary_state()); } - check_flash_transparency(object->_state, flash_multisample_color); + check_flash_transparency(object._state, flash_multisample_color); break; case TransparencyAttrib::M_dual: #ifndef NDEBUG - check_flash_transparency(object->_state, flash_dual_color); + check_flash_transparency(object._state, flash_dual_color); #endif if (!m_dual) { // If m_dual is configured off, it becomes M_alpha. @@ -198,7 +198,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) { // falls back to M_alpha. { const CullBinAttrib *bin_attrib; - if (!object->_state->get_attrib(bin_attrib) || + if (!object._state->get_attrib(bin_attrib) || bin_attrib->get_bin_name().empty()) { // We make a copy of the object to draw the transparent part; this // gets placed in the transparent bin. @@ -206,28 +206,25 @@ add_object(CullableObject *object, const CullTraverser *traverser) { if (m_dual_transparent) #endif { - CullableObject *transparent_part = new CullableObject(*object); + CullableObject transparent_part(object); CPT(RenderState) transparent_state = get_dual_transparent_state(); - transparent_part->_state = object->_state->compose(transparent_state); - if (transparent_part->munge_geom - (_gsg, _gsg->get_geom_munger(transparent_part->_state, current_thread), + transparent_part._state = object._state->compose(transparent_state); + if (transparent_part.munge_geom + (_gsg, _gsg->get_geom_munger(transparent_part._state, current_thread), traverser, force)) { - int transparent_bin_index = transparent_part->_state->get_bin_index(); + int transparent_bin_index = transparent_part._state->get_bin_index(); CullBin *bin = get_bin(transparent_bin_index); nassertv(bin != nullptr); - check_flash_bin(transparent_part->_state, bin_manager, transparent_bin_index); - bin->add_object(transparent_part, current_thread); - } else { - delete transparent_part; + check_flash_bin(transparent_part._state, bin_manager, transparent_bin_index); + bin->add_object(alloc_object(std::move(transparent_part)), current_thread); } } // Now we can draw the opaque part. This will end up in the opaque // bin. - object->_state = object->_state->compose(get_dual_opaque_state()); + object._state = object._state->compose(get_dual_opaque_state()); #ifndef NDEBUG if (!m_dual_opaque) { - delete object; return; } #endif @@ -242,20 +239,18 @@ add_object(CullableObject *object, const CullTraverser *traverser) { } } - int bin_index = object->_state->get_bin_index(); + int bin_index = object._state->get_bin_index(); CullBin *bin = get_bin(bin_index); nassertv(bin != nullptr); - check_flash_bin(object->_state, bin_manager, bin_index); + check_flash_bin(object._state, bin_manager, bin_index); // Munge vertices as needed for the GSG's requirements, and the object's // current state. - if (object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state, current_thread), traverser, force)) { + if (object.munge_geom(_gsg, _gsg->get_geom_munger(object._state, current_thread), traverser, force)) { // The object may or may not now be fully resident, but this may not // matter, since the GSG may have the necessary buffers already loaded. // We'll let the GSG ultimately decide whether to render it. - bin->add_object(object, current_thread); - } else { - delete object; + bin->add_object(alloc_object(std::move(object)), current_thread); } } @@ -371,6 +366,33 @@ make_new_bin(int bin_index) { return bin_ptr; } +/** + * Creates a new AllocationPage replacing the old one. + */ +CullResult::AllocationPage *CullResult:: +new_page() { + AllocationPage *page = new AllocationPage; + page->_next = _page; + _page = page; + return page; +} + +/** + * + */ +void CullResult:: +delete_page(AllocationPage *page) { + size_t size = std::exchange(page->_size, 0); + for (size_t i = 0; i < size; ++i) { + ((CullableObject *)page->_memory)[i].~CullableObject(); + } + AllocationPage *next = page->_next; + if (next != nullptr) { + delete_page(next); + delete page; + } +} + /** * Returns a RenderState containing the given rescale normal attribute. */ diff --git a/panda/src/pgraph/cullResult.h b/panda/src/pgraph/cullResult.h index 24c0df3d78..ff7cb5fd51 100644 --- a/panda/src/pgraph/cullResult.h +++ b/panda/src/pgraph/cullResult.h @@ -45,6 +45,7 @@ class EXPCL_PANDA_PGRAPH CullResult : public ReferenceCount { public: CullResult(GraphicsStateGuardianBase *gsg, const PStatCollector &draw_region_pcollector); + CullResult(const CullResult ©) = delete; INLINE ~CullResult(); PUBLISHED: @@ -52,7 +53,7 @@ PUBLISHED: INLINE CullBin *get_bin(int bin_index); - void add_object(CullableObject *object, const CullTraverser *traverser); + void add_object(CullableObject &&object, const CullTraverser *traverser); void finish_cull(SceneSetup *scene_setup, Thread *current_thread); void draw(Thread *current_thread); @@ -64,6 +65,11 @@ public: private: CullBin *make_new_bin(int bin_index); + struct AllocationPage; + AllocationPage *new_page(); + void delete_page(AllocationPage *page); + INLINE CullableObject *alloc_object(CullableObject &&object); + INLINE void check_flash_bin(CPT(RenderState) &state, CullBinManager *bin_manager, int bin_index); INLINE void check_flash_transparency(CPT(RenderState) &state, const LColor &color); @@ -88,6 +94,16 @@ private: bool _show_transparency = false; + // Arena allocator for CullableObjects. + struct AllocationPage { + AllocationPage *_next = nullptr; + static const size_t _capacity = 64; + size_t _size = 0; + alignas(CullableObject) unsigned char _memory[sizeof(CullableObject) * _capacity]; + }; + AllocationPage *_page; + AllocationPage _first_page; + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index aa1ea8eaa2..1982439e0d 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -259,15 +259,8 @@ draw_bounding_volume(const BoundingVolume *vol, if (bounds_viz != nullptr) { _geoms_pcollector.add_level(2); - CullableObject *outer_viz = - new CullableObject(bounds_viz, get_bounds_outer_viz_state(), - internal_transform); - _cull_handler->record_object(outer_viz, this); - - CullableObject *inner_viz = - new CullableObject(std::move(bounds_viz), get_bounds_inner_viz_state(), - internal_transform); - _cull_handler->record_object(inner_viz, this); + _cull_handler->record_object(CullableObject(bounds_viz, get_bounds_outer_viz_state(), internal_transform), this); + _cull_handler->record_object(CullableObject(std::move(bounds_viz), get_bounds_inner_viz_state(), internal_transform), this); } } @@ -309,11 +302,10 @@ show_bounds(CullTraverserData &data, bool tight) { if (bounds_viz != nullptr) { _geoms_pcollector.add_level(1); - CullableObject *outer_viz = - new CullableObject(std::move(bounds_viz), get_bounds_outer_viz_state(), - internal_transform); - outer_viz->_instances = data._instances; - _cull_handler->record_object(outer_viz, this); + CullableObject outer_viz(std::move(bounds_viz), get_bounds_outer_viz_state(), + internal_transform); + outer_viz._instances = data._instances; + _cull_handler->record_object(std::move(outer_viz), this); } } else if (data._instances == nullptr) { draw_bounding_volume(node->get_bounds(), internal_transform); diff --git a/panda/src/pgraph/cullableObject.h b/panda/src/pgraph/cullableObject.h index b11b464657..46fdc228c6 100644 --- a/panda/src/pgraph/cullableObject.h +++ b/panda/src/pgraph/cullableObject.h @@ -24,7 +24,6 @@ #include "geomNode.h" #include "cullTraverserData.h" #include "pStatCollector.h" -#include "deletedChain.h" #include "graphicsStateGuardianBase.h" #include "sceneSetup.h" #include "lightMutex.h" @@ -46,7 +45,10 @@ public: CPT(TransformState) internal_transform); INLINE CullableObject(const CullableObject ©); + INLINE CullableObject(CullableObject &&from) noexcept = default; + INLINE void operator = (const CullableObject ©); + INLINE CullableObject &operator = (CullableObject &&from) noexcept = default; bool munge_geom(GraphicsStateGuardianBase *gsg, GeomMunger *munger, const CullTraverser *traverser, bool force); @@ -64,8 +66,6 @@ public: bool force, Thread *current_thread); public: - ALLOC_DELETED_CHAIN(CullableObject); - void output(std::ostream &out) const; public: diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index 2b758c1cea..0443dfc208 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -538,10 +538,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { if (!geom->is_empty()) { CPT(RenderState) state = data._state->compose(geoms.get_geom_state(0)); if (!state->has_cull_callback() || state->cull_callback(trav, data)) { - CullableObject *object = - new CullableObject(std::move(geom), std::move(state), std::move(internal_transform)); - object->_instances = data._instances; - trav->get_cull_handler()->record_object(object, trav); + CullableObject object(std::move(geom), std::move(state), std::move(internal_transform)); + object._instances = data._instances; + trav->get_cull_handler()->record_object(std::move(object), trav); } } } @@ -562,10 +561,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { if (data._instances != nullptr) { // Draw each individual instance. We don't bother culling each // individual Geom for each instance; that is probably way too slow. - CullableObject *object = - new CullableObject(std::move(geom), std::move(state), internal_transform); - object->_instances = data._instances; - trav->get_cull_handler()->record_object(object, trav); + CullableObject object(std::move(geom), std::move(state), internal_transform); + object._instances = data._instances; + trav->get_cull_handler()->record_object(std::move(object), trav); continue; } @@ -588,9 +586,8 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { } } - CullableObject *object = - new CullableObject(std::move(geom), std::move(state), internal_transform); - trav->get_cull_handler()->record_object(object, trav); + trav->get_cull_handler()->record_object(CullableObject( + std::move(geom), std::move(state), internal_transform), trav); } } } diff --git a/panda/src/pgraph/nodePathCollection_ext.cxx b/panda/src/pgraph/nodePathCollection_ext.cxx index a06caf8380..de0267e589 100644 --- a/panda/src/pgraph/nodePathCollection_ext.cxx +++ b/panda/src/pgraph/nodePathCollection_ext.cxx @@ -36,13 +36,14 @@ __init__(PyObject *self, PyObject *sequence) { return; } + Py_BEGIN_CRITICAL_SECTION(fast); Py_ssize_t size = PySequence_Fast_GET_SIZE(fast); _this->reserve(size); for (int i = 0; i < size; ++i) { PyObject *item = PySequence_Fast_GET_ITEM(fast, i); if (item == nullptr) { - return; + break; } NodePath *path; @@ -52,13 +53,12 @@ __init__(PyObject *self, PyObject *sequence) { stream << "Element " << i << " in sequence passed to NodePathCollection constructor is not a NodePath"; std::string str = stream.str(); PyErr_SetString(PyExc_TypeError, str.c_str()); - Py_DECREF(fast); - return; + break; } else { _this->add_path(*path); } } - + Py_END_CRITICAL_SECTION(); Py_DECREF(fast); } @@ -75,7 +75,7 @@ __reduce__(PyObject *self) const { // object whose constructor we should call (e.g. this), and the arguments // necessary to reconstruct this object. - PyObject *this_class = (PyObject *)self->ob_type; + PyObject *this_class = (PyObject *)Py_TYPE(self); if (this_class == nullptr) { return nullptr; } diff --git a/panda/src/pgraph/nodePath_ext.cxx b/panda/src/pgraph/nodePath_ext.cxx index 23cfb172d2..e05877be53 100644 --- a/panda/src/pgraph/nodePath_ext.cxx +++ b/panda/src/pgraph/nodePath_ext.cxx @@ -56,10 +56,10 @@ __deepcopy__(PyObject *self, PyObject *memo) const { extern struct Dtool_PyTypedObject Dtool_NodePath; // Borrowed reference. - PyObject *dupe = PyDict_GetItem(memo, self); - if (dupe != nullptr) { + PyObject *dupe; + if (PyDict_GetItemRef(memo, self, &dupe) > 0) { // Already in the memo dictionary. - return Py_NewRef(dupe); + return dupe; } NodePath *np_dupe; @@ -279,19 +279,21 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) { PyObject *key, *value; Py_ssize_t pos = 0; + Py_BEGIN_CRITICAL_SECTION(kwargs); while (PyDict_Next(kwargs, &pos, &key, &value)) { char *buffer; Py_ssize_t length; buffer = (char *)PyUnicode_AsUTF8AndSize(key, &length); if (buffer == nullptr) { Dtool_Raise_TypeError("NodePath.set_shader_inputs accepts only string keywords"); - return; + break; } CPT_InternalName name(std::string(buffer, length)); ShaderInput &input = attrib->_inputs[name]; invoke_extension(&input).__init__(std::move(name), value); } + Py_END_CRITICAL_SECTION(); if (!PyErr_Occurred()) { node->set_attrib(ShaderAttrib::return_new(attrib)); diff --git a/panda/src/pgraph/occluderNode.cxx b/panda/src/pgraph/occluderNode.cxx index a1db42c3c3..408f5e28f1 100644 --- a/panda/src/pgraph/occluderNode.cxx +++ b/panda/src/pgraph/occluderNode.cxx @@ -141,17 +141,15 @@ bool OccluderNode:: cull_callback(CullTraverser *trav, CullTraverserData &data) { // Normally, an OccluderNode is invisible. But if someone shows it, we will // draw a visualization, a checkerboard-textured polygon. - CullableObject *occluder_viz = - new CullableObject(get_occluder_viz(trav, data), get_occluder_viz_state(trav, data), - data.get_internal_transform(trav)); - trav->get_cull_handler()->record_object(occluder_viz, trav); + trav->get_cull_handler()->record_object(CullableObject( + get_occluder_viz(trav, data), get_occluder_viz_state(trav, data), + data.get_internal_transform(trav)), trav); // Also get the frame. nassertr(_frame_viz != nullptr, false); - CullableObject *frame_viz = - new CullableObject(_frame_viz, get_frame_viz_state(trav, data), - data.get_internal_transform(trav)); - trav->get_cull_handler()->record_object(frame_viz, trav); + trav->get_cull_handler()->record_object(CullableObject( + _frame_viz, get_frame_viz_state(trav, data), + data.get_internal_transform(trav)), trav); // Now carry on to render our child nodes. return true; diff --git a/panda/src/pgraph/pandaNode_ext.cxx b/panda/src/pgraph/pandaNode_ext.cxx index cd7ca8b252..f1d25ed08e 100644 --- a/panda/src/pgraph/pandaNode_ext.cxx +++ b/panda/src/pgraph/pandaNode_ext.cxx @@ -47,10 +47,10 @@ __deepcopy__(PyObject *self, PyObject *memo) const { extern struct Dtool_PyTypedObject Dtool_PandaNode; // Borrowed reference. - PyObject *dupe = PyDict_GetItem(memo, self); - if (dupe != nullptr) { + PyObject *dupe; + if (PyDict_GetItemRef(memo, self, &dupe) > 0) { // Already in the memo dictionary. - return Py_NewRef(dupe); + return dupe; } PT(PandaNode) node_dupe = _this->copy_subgraph(); @@ -122,12 +122,11 @@ get_python_tag(PyObject *key) const { } PyObject *dict = ((PythonTagDataImpl *)_this->_python_tag_data.p())->_dict; - PyObject *value = PyDict_GetItem(dict, key); - if (value == nullptr) { - value = Py_None; + PyObject *value; + if (PyDict_GetItemRef(dict, key, &value) == 0) { + value = Py_NewRef(Py_None); } - // PyDict_GetItem returns a borrowed reference. - return Py_NewRef(value); + return value; } /** @@ -142,7 +141,7 @@ has_python_tag(PyObject *key) const { } PyObject *dict = ((PythonTagDataImpl *)_this->_python_tag_data.p())->_dict; - return (PyDict_GetItem(dict, key) != nullptr); + return PyDict_Contains(dict, key); } /** @@ -157,7 +156,8 @@ clear_python_tag(PyObject *key) { } PyObject *dict = do_get_python_tags(); - if (PyDict_GetItem(dict, key) != nullptr) { + Py_BEGIN_CRITICAL_SECTION(dict); + if (PyDict_Contains(dict, key)) { PyDict_DelItem(dict, key); } @@ -166,6 +166,7 @@ clear_python_tag(PyObject *key) { // unique reference to the tags, so clear the tag object. _this->_python_tag_data.clear(); } + Py_END_CRITICAL_SECTION(); } /** diff --git a/panda/src/pgraph/planeNode.cxx b/panda/src/pgraph/planeNode.cxx index dbae5ff960..4a290a2454 100644 --- a/panda/src/pgraph/planeNode.cxx +++ b/panda/src/pgraph/planeNode.cxx @@ -140,10 +140,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { // Normally, a PlaneNode is invisible. But if someone shows it, we will // draw a visualization, a nice yellow wireframe. - CullableObject *plane_viz = - new CullableObject(get_viz(trav, data), data._state, - data.get_internal_transform(trav)); - trav->get_cull_handler()->record_object(plane_viz, trav); + trav->get_cull_handler()->record_object(CullableObject( + get_viz(trav, data), data._state, data.get_internal_transform(trav)), trav); // Now carry on to render our child nodes. return true; diff --git a/panda/src/pgraph/pythonLoaderFileType.cxx b/panda/src/pgraph/pythonLoaderFileType.cxx index 9076a3535e..aa4b84cceb 100644 --- a/panda/src/pgraph/pythonLoaderFileType.cxx +++ b/panda/src/pgraph/pythonLoaderFileType.cxx @@ -89,26 +89,25 @@ init(PyObject *loader) { return false; } - PyObject *sequence = PySequence_Fast(extensions, "extensions must be a sequence"); - PyObject **items = PySequence_Fast_ITEMS(sequence); - Py_ssize_t num_items = PySequence_Fast_GET_SIZE(sequence); + PyObject *tuple = PySequence_Tuple(extensions); + Py_ssize_t num_items = PyTuple_GET_SIZE(tuple); Py_DECREF(extensions); if (num_items == 0) { PyErr_SetString(PyExc_ValueError, "extensions list may not be empty"); - Py_DECREF(sequence); + Py_DECREF(tuple); return false; } bool found_extension = false; for (Py_ssize_t i = 0; i < num_items; ++i) { - PyObject *extension = items[i]; + PyObject *extension = PyTuple_GET_ITEM(tuple, i); const char *extension_str; Py_ssize_t extension_len; extension_str = PyUnicode_AsUTF8AndSize(extension, &extension_len); if (extension_str == nullptr) { - Py_DECREF(sequence); + Py_DECREF(tuple); return false; } @@ -127,7 +126,7 @@ init(PyObject *loader) { } } } - Py_DECREF(sequence); + Py_DECREF(tuple); if (!found_extension) { PyObject *repr = PyObject_Repr(loader); diff --git a/panda/src/pgraph/renderState_ext.cxx b/panda/src/pgraph/renderState_ext.cxx index 6cfe05965e..085d79d6f9 100644 --- a/panda/src/pgraph/renderState_ext.cxx +++ b/panda/src/pgraph/renderState_ext.cxx @@ -56,7 +56,7 @@ make(PyObject *args, PyObject *kwds) { int override = 0; if (py_override != nullptr) { - override = _PyLong_AsInt(py_override); + override = PyLong_AsInt(py_override); if (override == -1 && PyErr_Occurred()) { return nullptr; } diff --git a/panda/src/pgraph/shaderAttrib_ext.cxx b/panda/src/pgraph/shaderAttrib_ext.cxx index b599d5ab25..012095935a 100644 --- a/panda/src/pgraph/shaderAttrib_ext.cxx +++ b/panda/src/pgraph/shaderAttrib_ext.cxx @@ -46,22 +46,28 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) const { PyObject *key, *value; Py_ssize_t pos = 0; + Py_BEGIN_CRITICAL_SECTION(kwargs); while (PyDict_Next(kwargs, &pos, &key, &value)) { char *buffer; Py_ssize_t length; buffer = (char *)PyUnicode_AsUTF8AndSize(key, &length); if (buffer == nullptr) { Dtool_Raise_TypeError("ShaderAttrib.set_shader_inputs accepts only string keywords"); - delete attrib; - return nullptr; + break; } CPT_InternalName name(std::string(buffer, length)); ShaderInput &input = attrib->_inputs[name]; invoke_extension(&input).__init__(std::move(name), value); } + Py_END_CRITICAL_SECTION(); - return ShaderAttrib::return_new(attrib); + if (!PyErr_Occurred()) { + return ShaderAttrib::return_new(attrib); + } else { + delete attrib; + return nullptr; + } } #endif // HAVE_PYTHON diff --git a/panda/src/pgraph/shaderInput_ext.cxx b/panda/src/pgraph/shaderInput_ext.cxx index d7496120b6..e9c83c18fc 100644 --- a/panda/src/pgraph/shaderInput_ext.cxx +++ b/panda/src/pgraph/shaderInput_ext.cxx @@ -269,12 +269,20 @@ __init__(CPT_InternalName name, PyObject *value, int priority) { } else if (PySequence_Check(value) && !PyUnicode_CheckExact(value)) { // Iterate over the sequence to make sure all have the same type. +#ifdef Py_GIL_DISABLED + PyObject *fast = PySequence_Tuple(value); +#else PyObject *fast = PySequence_Fast(value, "unknown type passed to ShaderInput"); +#endif if (fast == nullptr) { return; } +#ifdef Py_GIL_DISABLED + Py_ssize_t num_items = PyTuple_GET_SIZE(fast); +#else Py_ssize_t num_items = PySequence_Fast_GET_SIZE(fast); +#endif if (num_items <= 0) { // We can't determine the type of a list of size 0. _this->_type = ShaderInput::M_numeric; @@ -289,6 +297,9 @@ __init__(CPT_InternalName name, PyObject *value, int priority) { for (Py_ssize_t i = 0; i < num_items; ++i) { PyObject *item = items[i]; + //FIXME: if these items are not tuples, this is not thread-safe in the + // free-threaded build. Convert everything to tuples, and push to a + // vector? if (PySequence_Check(item)) { Py_ssize_t itemsize = PySequence_Size(item); if (known_itemsize >= 0 && itemsize != known_itemsize) { @@ -310,7 +321,7 @@ __init__(CPT_InternalName name, PyObject *value, int priority) { Dtool_Raise_TypeError("unknown element type in sequence passed as element of sequence passed to ShaderInput"); Py_DECREF(subitem); Py_DECREF(fast); - break; + return; } Py_DECREF(subitem); } diff --git a/panda/src/pgraphnodes/callbackNode.cxx b/panda/src/pgraphnodes/callbackNode.cxx index 2e555dfd1e..8ebb38cd15 100644 --- a/panda/src/pgraphnodes/callbackNode.cxx +++ b/panda/src/pgraphnodes/callbackNode.cxx @@ -121,11 +121,10 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { // Geoms, however. CallbackObject *cbobj = get_draw_callback(); if (cbobj != nullptr) { - CullableObject *object = - new CullableObject(nullptr, data._state, - data.get_internal_transform(trav)); - object->set_draw_callback(cbobj); - trav->get_cull_handler()->record_object(object, trav); + CullableObject object(nullptr, data._state, + data.get_internal_transform(trav)); + object.set_draw_callback(cbobj); + trav->get_cull_handler()->record_object(std::move(object), trav); } } diff --git a/panda/src/pgraphnodes/computeNode.cxx b/panda/src/pgraphnodes/computeNode.cxx index 8c757e2860..505989762d 100644 --- a/panda/src/pgraphnodes/computeNode.cxx +++ b/panda/src/pgraphnodes/computeNode.cxx @@ -82,11 +82,10 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { // OK, render this node. Rendering this node means creating a // CullableObject for the Dispatcher. We don't need to pass any Geoms, // however. - CullableObject *object = - new CullableObject(nullptr, data._state, - data.get_internal_transform(trav)); - object->set_draw_callback(_dispatcher); - trav->get_cull_handler()->record_object(object, trav); + CullableObject object(nullptr, data._state, + data.get_internal_transform(trav)); + object.set_draw_callback(_dispatcher); + trav->get_cull_handler()->record_object(std::move(object), trav); } /** diff --git a/panda/src/pgraphnodes/nodeCullCallbackData.cxx b/panda/src/pgraphnodes/nodeCullCallbackData.cxx index 5a9dbc9e0a..32faac3930 100644 --- a/panda/src/pgraphnodes/nodeCullCallbackData.cxx +++ b/panda/src/pgraphnodes/nodeCullCallbackData.cxx @@ -48,11 +48,10 @@ upcall() { // any Geoms, however. CallbackObject *cbobj = cbnode->get_draw_callback(); if (cbobj != nullptr) { - CullableObject *object = - new CullableObject(nullptr, _data._state, - _data.get_internal_transform(_trav)); - object->set_draw_callback(cbobj); - _trav->get_cull_handler()->record_object(object, _trav); + CullableObject object(nullptr, _data._state, + _data.get_internal_transform(_trav)); + object.set_draw_callback(cbobj); + _trav->get_cull_handler()->record_object(std::move(object), _trav); } } diff --git a/panda/src/pgui/pgItem.cxx b/panda/src/pgui/pgItem.cxx index 7d2e884f82..d612e889cc 100644 --- a/panda/src/pgui/pgItem.cxx +++ b/panda/src/pgui/pgItem.cxx @@ -775,9 +775,14 @@ move(const MouseWatcherParameter ¶m) { */ void PGItem:: background_press(const MouseWatcherParameter ¶m) { - for (PGItem *item : _background_focus) { + // We have to be careful, because objects may remove themselves from the set + // while we're iterating over it. + auto it = _background_focus.begin(); + while (it != _background_focus.end()) { + PGItem *item = *it++; if (!item->get_focus()) { - item->press(param, true); + PT(PGItem) item_ref(item); + item_ref->press(param, true); } } } @@ -787,9 +792,12 @@ background_press(const MouseWatcherParameter ¶m) { */ void PGItem:: background_release(const MouseWatcherParameter ¶m) { - for (PGItem *item : _background_focus) { + auto it = _background_focus.begin(); + while (it != _background_focus.end()) { + PGItem *item = *it++; if (!item->get_focus()) { - item->release(param, true); + PT(PGItem) item_ref(item); + item_ref->release(param, true); } } } @@ -799,9 +807,12 @@ background_release(const MouseWatcherParameter ¶m) { */ void PGItem:: background_keystroke(const MouseWatcherParameter ¶m) { - for (PGItem *item : _background_focus) { + auto it = _background_focus.begin(); + while (it != _background_focus.end()) { + PGItem *item = *it++; if (!item->get_focus()) { - item->keystroke(param, true); + PT(PGItem) item_ref(item); + item_ref->keystroke(param, true); } } } @@ -811,9 +822,12 @@ background_keystroke(const MouseWatcherParameter ¶m) { */ void PGItem:: background_candidate(const MouseWatcherParameter ¶m) { - for (PGItem *item : _background_focus) { + auto it = _background_focus.begin(); + while (it != _background_focus.end()) { + PGItem *item = *it++; if (!item->get_focus()) { - item->candidate(param, true); + PT(PGItem) item_ref(item); + item_ref->candidate(param, true); } } } diff --git a/panda/src/pipeline/cycleDataLockedStageReader.I b/panda/src/pipeline/cycleDataLockedStageReader.I index 6cee154bb7..4fef7c8694 100644 --- a/panda/src/pipeline/cycleDataLockedStageReader.I +++ b/panda/src/pipeline/cycleDataLockedStageReader.I @@ -184,7 +184,7 @@ CycleDataLockedStageReader(const CycleDataLockedStageReader © template INLINE CycleDataLockedStageReader:: CycleDataLockedStageReader(CycleDataLockedStageReader &&from) noexcept : - _pointer(from._cycler) + _pointer(from._pointer) { from._pointer = nullptr; } diff --git a/panda/src/pipeline/threadWin32Impl.I b/panda/src/pipeline/threadWin32Impl.I index ca236b78f0..809da14418 100644 --- a/panda/src/pipeline/threadWin32Impl.I +++ b/panda/src/pipeline/threadWin32Impl.I @@ -63,14 +63,6 @@ is_simple_threads() { return false; } -/** - * - */ -INLINE void ThreadWin32Impl:: -sleep(double seconds) { - Sleep((int)(seconds * 1000)); -} - /** * */ diff --git a/panda/src/pipeline/threadWin32Impl.cxx b/panda/src/pipeline/threadWin32Impl.cxx index c8653a4f5c..e8a10b78d5 100644 --- a/panda/src/pipeline/threadWin32Impl.cxx +++ b/panda/src/pipeline/threadWin32Impl.cxx @@ -25,6 +25,10 @@ static thread_local Thread *_current_thread = nullptr; static patomic_flag _main_thread_known = ATOMIC_FLAG_INIT; +#ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION +#define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002 +#endif + #if _WIN32_WINNT < 0x0601 // Requires Windows 7. static DWORD (__stdcall *EnableThreadProfiling)(HANDLE, DWORD, DWORD64, HANDLE *) = nullptr; @@ -78,6 +82,11 @@ ThreadWin32Impl:: } CloseHandle(_thread); + + if (_timer != nullptr) { + CloseHandle(_timer); + _timer = nullptr; + } } /** @@ -200,6 +209,27 @@ bind_thread(Thread *thread) { return thread; } + +/** + * + */ +void ThreadWin32Impl:: +sleep(double seconds) { + Thread *thread = get_current_thread(); + ThreadWin32Impl *self = &thread->_impl; + + HANDLE timer = self->_timer; + if (timer == nullptr) { + timer = CreateWaitableTimerExW(nullptr, nullptr, CREATE_WAITABLE_TIMER_MANUAL_RESET | CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); + self->_timer = timer; + } + + LARGE_INTEGER ft; + ft.QuadPart = seconds * -10000000LL; + SetWaitableTimer(timer, &ft, 0, nullptr, nullptr, 0); + WaitForSingleObject(timer, INFINITE); +} + /** * Returns the number of context switches that occurred on the current thread. * The first number is the total number of context switches reported by the OS, diff --git a/panda/src/pipeline/threadWin32Impl.h b/panda/src/pipeline/threadWin32Impl.h index 1d62320789..a5528e5588 100644 --- a/panda/src/pipeline/threadWin32Impl.h +++ b/panda/src/pipeline/threadWin32Impl.h @@ -48,7 +48,7 @@ public: INLINE static bool is_threading_supported(); INLINE static bool is_true_threads(); INLINE static bool is_simple_threads(); - INLINE static void sleep(double seconds); + static void sleep(double seconds); INLINE static void yield(); INLINE static void consider_yield(); @@ -72,6 +72,7 @@ private: bool _joinable; Status _status; HANDLE _profiling; + HANDLE _timer = nullptr; }; #include "threadWin32Impl.I" diff --git a/panda/src/pstatclient/pStatClient_ext.cxx b/panda/src/pstatclient/pStatClient_ext.cxx index 0724470cfb..f786b07dcd 100644 --- a/panda/src/pstatclient/pStatClient_ext.cxx +++ b/panda/src/pstatclient/pStatClient_ext.cxx @@ -72,11 +72,21 @@ __declspec(noinline) make_python_frame_collector(PyFrameObject *frame, PyCodeObject *code) { #if PY_VERSION_HEX >= 0x030B0000 // 3.11 // Fetch the module name out of the frame's global scope. + const char *mod_name = ""; + PyObject *py_mod_name = nullptr; PyObject *globals = PyFrame_GetGlobals(frame); - PyObject *py_mod_name = PyDict_GetItemString(globals, "__name__"); +#if PY_VERSION_HEX >= 0x030D00A1 // 3.13 + if (PyDict_GetItemStringRef(globals, "__name__", &py_mod_name) > 0) { + mod_name = PyUnicode_AsUTF8(py_mod_name); + } +#else + py_mod_name = PyDict_GetItemString(globals, "__name__"); + if (py_mod_name != nullptr) { + mod_name = PyUnicode_AsUTF8(py_mod_name); + } +#endif Py_DECREF(globals); - const char *mod_name = py_mod_name ? PyUnicode_AsUTF8(py_mod_name) : ""; const char *meth_name = PyUnicode_AsUTF8(code->co_qualname); char buffer[1024]; size_t len = snprintf(buffer, sizeof(buffer), "%s:%s", mod_name, meth_name); @@ -85,6 +95,11 @@ make_python_frame_collector(PyFrameObject *frame, PyCodeObject *code) { buffer[i] = ':'; } } + +#if PY_VERSION_HEX >= 0x030D00A1 // 3.13 + Py_XDECREF(py_mod_name); +#endif + #else // Try to figure out the type name. There's no obvious way to do this. // It's possible that the first argument passed to this function is the @@ -179,23 +194,26 @@ make_c_function_collector(PyCFunctionObject *meth) { len = (dot - cls->tp_name) + 1; } else { // If there's no module name, we need to get it from __module__. - PyObject *py_mod_name = cls->tp_dict ? PyDict_GetItemString(cls->tp_dict, "__module__") : nullptr; + PyObject *py_mod_name = nullptr; const char *mod_name = nullptr; - if (py_mod_name != nullptr) { + if (cls->tp_dict != nullptr && + PyDict_GetItemStringRef(cls->tp_dict, "__module__", &py_mod_name) > 0) { if (PyUnicode_Check(py_mod_name)) { mod_name = PyUnicode_AsUTF8(py_mod_name); } else { // Might be a descriptor. + Py_DECREF(py_mod_name); py_mod_name = PyObject_GetAttrString(meth->m_self, "__module__"); if (py_mod_name != nullptr) { if (PyUnicode_Check(py_mod_name)) { mod_name = PyUnicode_AsUTF8(py_mod_name); } - Py_DECREF(py_mod_name); } else PyErr_Clear(); } } + else PyErr_Clear(); + if (mod_name == nullptr) { // Is it a built-in, like int or dict? PyObject *builtins = PyEval_GetBuiltins(); @@ -206,6 +224,7 @@ make_c_function_collector(PyCFunctionObject *meth) { } } len = snprintf(buffer, sizeof(buffer), "%s:%s:%s()", mod_name, cls->tp_name, meth->m_ml->ml_name) - 2; + Py_XDECREF(py_mod_name); } } else if (meth->m_self != nullptr) { diff --git a/panda/src/putil/bamReader_ext.cxx b/panda/src/putil/bamReader_ext.cxx index 308028cea3..84c5060e1e 100644 --- a/panda/src/putil/bamReader_ext.cxx +++ b/panda/src/putil/bamReader_ext.cxx @@ -85,7 +85,7 @@ static TypedWritable *factory_callback(const FactoryParams ¶ms){ Py_DECREF(result); } else if (DtoolInstance_TYPE(result) == &Dtool_TypedWritable && - Py_TYPE(result) != &Dtool_TypedWritable._PyType) { + !Py_IS_TYPE(result, Dtool_GetPyTypeObject(&Dtool_TypedWritable))) { // It is a custom subclass of TypedWritable, so we have to keep it // alive, and decrement it in finalize(), see typedWritable_ext.cxx. manager->register_finalize(ptr); diff --git a/panda/src/putil/bamWriter.I b/panda/src/putil/bamWriter.I index ad8b119edf..b9e36d421f 100644 --- a/panda/src/putil/bamWriter.I +++ b/panda/src/putil/bamWriter.I @@ -96,6 +96,9 @@ get_file_texture_mode() const { * Changes the BamTextureMode preference for the Bam file currently being * written. Texture objects written to this Bam file will be encoded * according to the specified mode. + * + * This should be called after the call to init(), or it will be overwritten + * with the default mode in the config file. */ INLINE void BamWriter:: set_file_texture_mode(BamTextureMode file_texture_mode) { diff --git a/panda/src/putil/bamWriter.h b/panda/src/putil/bamWriter.h index be07d80411..63328de177 100644 --- a/panda/src/putil/bamWriter.h +++ b/panda/src/putil/bamWriter.h @@ -96,7 +96,7 @@ PUBLISHED: MAKE_PROPERTY(file_version, get_file_version); MAKE_PROPERTY(file_endian, get_file_endian); MAKE_PROPERTY(file_stdfloat_double, get_file_stdfloat_double); - MAKE_PROPERTY(file_texture_mode, get_file_texture_mode); + MAKE_PROPERTY(file_texture_mode, get_file_texture_mode, set_file_texture_mode); MAKE_PROPERTY(root_node, get_root_node, set_root_node); public: @@ -135,7 +135,7 @@ private: // Stores the PandaNode representing the root of the node hierarchy we are // currently writing, if any, for the purpose of writing NodePaths. This is // a TypedWritable since PandaNode is defined in pgraph. - TypedWritable *_root_node; + TypedWritable *_root_node = nullptr; // This is the set of all TypeHandles already written. pset _types_written; diff --git a/panda/src/putil/bitArray_ext.cxx b/panda/src/putil/bitArray_ext.cxx index 2a48951040..b454593d1b 100644 --- a/panda/src/putil/bitArray_ext.cxx +++ b/panda/src/putil/bitArray_ext.cxx @@ -32,7 +32,11 @@ __init__(PyObject *init_value) { _PyLong_AsByteArray((PyLongObject *)init_value, (unsigned char *)&_this->_array[0], num_words * sizeof(BitArray::WordType), - 1, 0); + 1, 0 +#if PY_VERSION_HEX >= 0x030d0000 + , 1 // with_exceptions +#endif + ); } } diff --git a/panda/src/putil/clockObject.cxx b/panda/src/putil/clockObject.cxx index 8fa128616f..1add57a6e1 100644 --- a/panda/src/putil/clockObject.cxx +++ b/panda/src/putil/clockObject.cxx @@ -499,6 +499,8 @@ wait_until(double want_time) { double wait_interval = (want_time - _actual_frame_time) - sleep_precision; + double now = get_real_time(); + if (wait_interval > 0.0) { Thread::sleep(wait_interval); } @@ -507,6 +509,20 @@ wait_until(double want_time) { (*_start_clock_busy_wait)(); #endif + _actual_frame_time = get_real_time(); + if (_actual_frame_time > want_time) { + if (util_cat.is_debug()) { + util_cat.debug() + << "Overslept by " << (int)((_actual_frame_time - want_time) * 1000000) + << " us while waiting for next frame, consider raising sleep-precision.\n"; + } + } + else if (util_cat.is_spam()) { + util_cat.spam() + << "Busy waiting for " << (int)((want_time - _actual_frame_time) * 1000000) + << " us.\n"; + } + // Now busy-wait until the actual time elapses. while (_actual_frame_time < want_time) { _actual_frame_time = get_real_time(); diff --git a/panda/src/putil/config_putil.cxx b/panda/src/putil/config_putil.cxx index 93694b3d30..9849cd5b84 100644 --- a/panda/src/putil/config_putil.cxx +++ b/panda/src/putil/config_putil.cxx @@ -129,9 +129,9 @@ get_plugin_path() { ConfigVariableDouble sleep_precision ("sleep-precision", 0.01, - PRC_DESC("This is the accuracy within which we can expect select() to " - "return precisely. That is, if we use select() to request a " - "timeout of 1.0 seconds, we can expect to actually sleep for " + PRC_DESC("This is the accuracy within which we can expect the operating " + "system sleep call to return precisely. That is, if we request " + "a timeout of 1.0 seconds, we can expect to actually sleep for " "somewhere between 1.0 and 1.0 + sleep-precision seconds.")); ConfigVariableBool preload_textures diff --git a/panda/src/putil/doubleBitMask_ext.I b/panda/src/putil/doubleBitMask_ext.I index a40b91355d..1674cccd49 100644 --- a/panda/src/putil/doubleBitMask_ext.I +++ b/panda/src/putil/doubleBitMask_ext.I @@ -31,7 +31,11 @@ __init__(PyObject *init_value) { if (n > 0) { size_t num_bytes = (n + 7) / 8; unsigned char *bytes = (unsigned char *)alloca(num_bytes); - _PyLong_AsByteArray((PyLongObject *)init_value, bytes, num_bytes, 1, 0); + _PyLong_AsByteArray((PyLongObject *)init_value, bytes, num_bytes, 1, 0 +#if PY_VERSION_HEX >= 0x030d0000 + , 1 // with_exceptions +#endif + ); for (size_t i = 0; i < num_bytes; ++i) { this->_this->store(bytes[i], i * 8, 8); @@ -58,7 +62,13 @@ __int__() const { if (!this->_this->_hi.is_zero()) { PyObject *lo = result; PyObject *hi = invoke_extension(&this->_this->_hi).__int__(); +#if PY_VERSION_HEX >= 0x030d0000 + PyObject *half_bits = PyLong_FromUnsignedLong(DoubleBitMask::half_bits); + PyObject *shifted = PyNumber_Lshift(hi, half_bits); + Py_DECREF(half_bits); +#else PyObject *shifted = _PyLong_Lshift(hi, DoubleBitMask::half_bits); +#endif Py_DECREF(hi); result = PyNumber_Or(shifted, lo); Py_DECREF(shifted); diff --git a/panda/src/putil/pythonCallbackObject.cxx b/panda/src/putil/pythonCallbackObject.cxx index 454c9bdaf5..bd70b13641 100644 --- a/panda/src/putil/pythonCallbackObject.cxx +++ b/panda/src/putil/pythonCallbackObject.cxx @@ -87,7 +87,7 @@ get_function() { */ PyObject *PythonCallbackObject:: __reduce__() const { - return Py_BuildValue("O(O)", (PyObject *)&Dtool_PythonCallbackObject._PyType, _function); + return Py_BuildValue("O(O)", (PyObject *)Dtool_GetPyTypeObject(&Dtool_PythonCallbackObject), _function); } /** diff --git a/panda/src/putil/simpleHashMap.I b/panda/src/putil/simpleHashMap.I index 6c61aaeea7..b6641205c5 100644 --- a/panda/src/putil/simpleHashMap.I +++ b/panda/src/putil/simpleHashMap.I @@ -292,8 +292,8 @@ remove(const Key &key) { // Now remove this element. size_t last = _num_entries - 1; - size_t index = (size_t)index_array[slot]; - if (index < _num_entries) { + int index = index_array[slot]; + if ((size_t)index < _num_entries) { // Find the last element in the index array. int other_slot = find_slot(_table[last]._key); nassertr(other_slot != -1, false); @@ -301,7 +301,7 @@ remove(const Key &key) { // Swap it with the last one, so that we don't get any gaps in the table // of entries. - _table[index] = std::move(_table[last]); + _table[(size_t)index] = std::move(_table[last]); index_array[(size_t)other_slot] = index; } @@ -321,13 +321,13 @@ remove(const Key &key) { // Now we have put a hole in the index array. If there was a hash conflict // in the slot after this one, we have to move it down to close the hole. slot = next_hash(slot); - while (has_slot(slot)) { - size_t index = (size_t)index_array[slot]; + index = index_array[slot]; + while (index >= 0) { size_t wants_slot = get_hash(_table[index]._key); if (wants_slot != slot) { // This one was a hash conflict; try to put it where it belongs. We // can't just put it in n, since maybe it belongs somewhere after n. - while (wants_slot != slot && has_slot(wants_slot)) { + while (wants_slot != slot && index_array[wants_slot] >= 0) { wants_slot = next_hash(wants_slot); } if (wants_slot != slot) { @@ -341,6 +341,7 @@ remove(const Key &key) { // Continue until we encounter the next unused slot. Until we do, we // can't be sure we've found all of the potential hash conflicts. slot = next_hash(slot); + index = index_array[slot]; } #ifdef _DEBUG diff --git a/panda/src/putil/typedWritable_ext.cxx b/panda/src/putil/typedWritable_ext.cxx index 699794b368..0a328e228c 100644 --- a/panda/src/putil/typedWritable_ext.cxx +++ b/panda/src/putil/typedWritable_ext.cxx @@ -134,10 +134,10 @@ wrap_typed_writable(void *from_this, PyTypeObject *from_type) { nassertr(from_type != nullptr, nullptr); TypedWritableProxy *to_this; - if (from_type == &Dtool_TypedWritable._PyType) { + if (from_type == Dtool_GetPyTypeObject(&Dtool_TypedWritable)) { to_this = (TypedWritableProxy *)(TypedWritable *)from_this; } - else if (from_type == (PyTypeObject *)&Dtool_TypedObject._PyType) { + else if (from_type == Dtool_GetPyTypeObject(&Dtool_TypedObject)) { to_this = (TypedWritableProxy *)(TypedObject *)from_this; } else { @@ -336,35 +336,37 @@ find_global_decode(PyObject *this_class, const char *func_name) { // Get the module in which BamWriter is defined. PyObject *module_name = PyObject_GetAttrString((PyObject *)&Dtool_BamWriter, "__module__"); if (module_name != nullptr) { - // borrowed reference - PyObject *sys_modules = PyImport_GetModuleDict(); - if (sys_modules != nullptr) { - // borrowed reference - PyObject *module = PyDict_GetItem(sys_modules, module_name); - if (module != nullptr) { - PyObject *func = PyObject_GetAttrString(module, (char *)func_name); - if (func != nullptr) { - Py_DECREF(module_name); - return func; - } + PyObject *module = PyImport_GetModule(module_name); + Py_DECREF(module_name); + if (module != nullptr) { + PyObject *func = PyObject_GetAttrString(module, (char *)func_name); + Py_DECREF(module); + if (func != nullptr) { + return func; } } - Py_DECREF(module_name); } PyObject *bases = PyObject_GetAttrString(this_class, "__bases__"); if (bases != nullptr) { - if (PySequence_Check(bases)) { - Py_ssize_t size = PySequence_Size(bases); - for (Py_ssize_t i = 0; i < size; ++i) { - PyObject *base = PySequence_GetItem(bases, i); - if (base != nullptr) { - PyObject *func = find_global_decode(base, func_name); - Py_DECREF(base); - if (func != nullptr) { - Py_DECREF(bases); - return func; - } + { + PyObject *tuple = PySequence_Tuple(bases); + Py_DECREF(bases); + if (tuple == nullptr) { + PyErr_Clear(); + return nullptr; + } + bases = tuple; + } + + Py_ssize_t size = PyTuple_GET_SIZE(bases); + for (Py_ssize_t i = 0; i < size; ++i) { + PyObject *base = PyTuple_GET_ITEM(bases, i); + if (base != nullptr) { + PyObject *func = find_global_decode(base, func_name); + if (func != nullptr) { + Py_DECREF(bases); + return func; } } } diff --git a/panda/src/testbed/pview.cxx b/panda/src/testbed/pview.cxx index e656af4b45..367736e095 100644 --- a/panda/src/testbed/pview.cxx +++ b/panda/src/testbed/pview.cxx @@ -164,6 +164,17 @@ event_0(const Event *event, void *) { card_np.set_texture(buffer->get_texture()); } +void +event_R(const Event *event, void *) { + // shift-R(eload): reload all textures + TextureCollection collection = TexturePool::get_global_ptr()->find_all_textures("*"); + for (int i = 0; i < collection.size(); ++i) + { + nout << "Reloading texture " << collection[i]->get_filename() << std::endl; + collection[i]->reload(); + } +} + void usage() { cerr << @@ -513,6 +524,7 @@ main(int argc, char **argv) { framework.define_key("shift-f", "flatten hierarchy", event_F, nullptr); framework.define_key("alt-enter", "toggle between window/fullscreen", event_Enter, nullptr); framework.define_key("2", "split the window", event_2, nullptr); + framework.define_key("shift-r", "reload textures", event_R, nullptr); if (pview_test_hack) { framework.define_key("0", "run quick hacky test", event_0, nullptr); } diff --git a/panda/src/text/dynamicTextFont.cxx b/panda/src/text/dynamicTextFont.cxx index 4d933619b5..53cda9d62a 100644 --- a/panda/src/text/dynamicTextFont.cxx +++ b/panda/src/text/dynamicTextFont.cxx @@ -566,7 +566,7 @@ make_glyph(int character, FT_Face face, int glyph_index) { if (_render_mode == RM_texture) { // Render the glyph if necessary. if (slot->format != ft_glyph_format_bitmap) { - FT_Render_Glyph(slot, ft_render_mode_normal); + FT_Render_Glyph(slot, _native_antialias ? ft_render_mode_normal : ft_render_mode_mono); } tex_x_size = bitmap.width; diff --git a/panda/src/text/textAssembler.cxx b/panda/src/text/textAssembler.cxx index 5c7a929923..a98abb68b3 100644 --- a/panda/src/text/textAssembler.cxx +++ b/panda/src/text/textAssembler.cxx @@ -44,6 +44,10 @@ using std::max; using std::min; using std::wstring; +enum ClusterFlags { + CF_small_caps = 0x200000, +}; + // This is the factor by which CT_small scales the character down. static const PN_stdfloat small_accent_scale = 0.6f; @@ -427,14 +431,14 @@ calc_r_c(int &r, int &c, int n) const { c = 0; int i = row._row_start; while (i < n - 1) { - if (_text_string[i]._character != text_soft_hyphen_key && - _text_string[i]._character != text_soft_break_key) { + if (_text_string[i]._character != (char32_t)text_soft_hyphen_key && + _text_string[i]._character != (char32_t)text_soft_break_key) { ++c; } ++i; } - if (_text_string[n - 1]._character != text_soft_hyphen_key && - _text_string[n - 1]._character != text_soft_break_key) { + if (_text_string[n - 1]._character != (char32_t)text_soft_hyphen_key && + _text_string[n - 1]._character != (char32_t)text_soft_break_key) { ++c; if (_text_string[n - 1]._character == '\n') { is_real_char = false; @@ -478,8 +482,8 @@ calc_index(int r, int c) const { // we have to scan past them to get n precisely. int n = row._row_start; while (c > 0) { - if (_text_string[n]._character != text_soft_hyphen_key && - _text_string[n]._character != text_soft_break_key) { + if (_text_string[n]._character != (char32_t)text_soft_hyphen_key && + _text_string[n]._character != (char32_t)text_soft_break_key) { --c; } ++n; @@ -798,13 +802,13 @@ scan_wtext(TextAssembler::TextString &output_string, const wstring::const_iterator &send, TextAssembler::ComputedProperties *current_cprops) { while (si != send) { - if ((*si) == text_push_properties_key) { + if ((*si) == (wchar_t)text_push_properties_key) { // This indicates a nested properties structure. Pull off the name of // the TextProperties structure, which is everything until the next // text_push_properties_key. wstring wname; ++si; - while (si != send && (*si) != text_push_properties_key) { + while (si != send && (*si) != (wchar_t)text_push_properties_key) { wname += (*si); ++si; } @@ -835,20 +839,20 @@ scan_wtext(TextAssembler::TextString &output_string, } } - } else if ((*si) == text_pop_properties_key) { + } else if ((*si) == (wchar_t)text_pop_properties_key) { // This indicates the undoing of a previous push_properties_key. We // simply return to the previous level. ++si; return; - } else if ((*si) == text_embed_graphic_key) { + } else if ((*si) == (wchar_t)text_embed_graphic_key) { // This indicates an embedded graphic. Pull off the name of the // TextGraphic structure, which is everything until the next // text_embed_graphic_key. wstring graphic_wname; ++si; - while (si != send && (*si) != text_embed_graphic_key) { + while (si != send && (*si) != (wchar_t)text_embed_graphic_key) { graphic_wname += (*si); ++si; } @@ -980,7 +984,7 @@ wordwrap_text() { } if (isspacew(_text_string[q]._character) || - _text_string[q]._character == text_soft_break_key) { + _text_string[q]._character == (char32_t)text_soft_break_key) { if (!last_was_space) { any_spaces = true; // We only care about logging whether there is a soft-hyphen @@ -997,7 +1001,7 @@ wordwrap_text() { // A soft hyphen character is not printed, but marks a point at which we // might hyphenate a word if we need to. - if (_text_string[q]._character == text_soft_hyphen_key) { + if (_text_string[q]._character == (char32_t)text_soft_hyphen_key) { if (wordwrap_width > 0.0f) { // We only consider this as a possible hyphenation point if (a) it // is not the very first character, and (b) there is enough room for @@ -1104,8 +1108,8 @@ wordwrap_text() { } for (size_t pi = p; pi < q; pi++) { - if (_text_string[pi]._character != text_soft_hyphen_key && - _text_string[pi]._character != text_soft_break_key) { + if (_text_string[pi]._character != (char32_t)text_soft_hyphen_key && + _text_string[pi]._character != (char32_t)text_soft_break_key) { _text_block.back()._string.push_back(_text_string[pi]); } else { _text_block.back()._got_soft_hyphens = true; @@ -1538,7 +1542,20 @@ assemble_row(TextAssembler::TextRow &row, } if (graphic == nullptr && harfbuff != nullptr) { - hb_buffer_add(harfbuff, character, character); + unsigned int cluster = character; + + if (properties->get_small_caps()) { + const UnicodeLatinMap::Entry *map_entry = + UnicodeLatinMap::look_up((char32_t)character); + if (map_entry != nullptr && + map_entry->_toupper_character != (char32_t)character) { + character = map_entry->_toupper_character; + + // Set a high bit on the cluster to flag this as needing a scale. + cluster |= CF_small_caps; + } + } + hb_buffer_add(harfbuff, character, cluster); continue; } #endif @@ -1577,7 +1594,7 @@ assemble_row(TextAssembler::TextRow &row, xpos = (floor(xpos / tab_width) + 1.0f) * tab_width; prev_char = -1; - } else if (character == text_soft_hyphen_key) { + } else if (character == (char32_t)text_soft_hyphen_key) { // And so is the 'soft-hyphen' key character. } else if (graphic != nullptr) { @@ -1810,7 +1827,8 @@ shape_buffer(hb_buffer_t *buf, PlacedGlyphs &placed_glyphs, PN_stdfloat &xpos, hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count); for (unsigned int i = 0; i < glyph_count; ++i) { - int character = glyph_info[i].cluster; + unsigned int cluster = glyph_info[i].cluster; + int character = cluster & 0x1fffff; int glyph_index = glyph_info[i].codepoint; CPT(TextGlyph) glyph; @@ -1849,6 +1867,12 @@ shape_buffer(hb_buffer_t *buf, PlacedGlyphs &placed_glyphs, PN_stdfloat &xpos, placement._ypos = properties.get_glyph_shift() + y_offset; placement._slant = properties.get_slant(); placement._properties = &properties; + + if (cluster & CF_small_caps) { + advance *= properties.get_small_caps_scale(); + placement._scale *= properties.get_small_caps_scale(); + } + placed_glyphs.push_back(placement); xpos += advance; diff --git a/panda/src/tinydisplay/td_light.cxx b/panda/src/tinydisplay/td_light.cxx index c570e5347c..5e1abf4783 100644 --- a/panda/src/tinydisplay/td_light.cxx +++ b/panda/src/tinydisplay/td_light.cxx @@ -127,9 +127,13 @@ void gl_shade_vertex(GLContext *c,GLVertex *v) B+=att * lB; } - v->color.v[0]=clampf(R*v->color.v[0],0,1); - v->color.v[1]=clampf(G*v->color.v[1],0,1); - v->color.v[2]=clampf(B*v->color.v[2],0,1); - v->color.v[3]=clampf(A*v->color.v[3],0,1); + v->color.v[0]=clampf(R,0,1); + v->color.v[1]=clampf(G,0,1); + v->color.v[2]=clampf(B,0,1); + v->color.v[3]=clampf(A,0,1); + //v->color.v[0]=clampf(R*v->color.v[0],0,1); + //v->color.v[1]=clampf(G*v->color.v[1],0,1); + //v->color.v[2]=clampf(B*v->color.v[2],0,1); + //v->color.v[3]=clampf(A*v->color.v[3],0,1); } diff --git a/panda/src/tinydisplay/tinyGraphicsBuffer.cxx b/panda/src/tinydisplay/tinyGraphicsBuffer.cxx index 47c0327f1b..0fc76e492c 100644 --- a/panda/src/tinydisplay/tinyGraphicsBuffer.cxx +++ b/panda/src/tinydisplay/tinyGraphicsBuffer.cxx @@ -136,6 +136,8 @@ open_buffer() { return false; } + _fb_properties.set_depth_bits(ZB_Z_BITS); + tinygsg->_current_frame_buffer = _frame_buffer; tinygsg->reset_if_new(); diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx index 5e723cece8..a260b23b2d 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx @@ -685,8 +685,6 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, needs_normal = false; } - bool lighting_enabled = (needs_normal && _c->lighting_enabled); - for (i = 0; i < num_used_vertices; ++i) { GLVertex *v = &_vertices[i]; const LVecBase4 &d = rvertex.get_data4(); @@ -723,12 +721,14 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, v->color = _c->current_color; - if (lighting_enabled) { - const LVecBase3 &d = rnormal.get_data3(); - _c->current_normal.v[0] = d[0]; - _c->current_normal.v[1] = d[1]; - _c->current_normal.v[2] = d[2]; - _c->current_normal.v[3] = 0.0f; + if (_c->lighting_enabled) { + if (needs_normal) { + const LVecBase3 &d = rnormal.get_data3(); + _c->current_normal.v[0] = d[0]; + _c->current_normal.v[1] = d[1]; + _c->current_normal.v[2] = d[2]; + _c->current_normal.v[3] = 0.0f; + } gl_vertex_transform(_c, v); gl_shade_vertex(_c, v); @@ -882,7 +882,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot())); ShadeModelAttrib::Mode shade_model = target_shade_model->get_mode(); - if (!needs_normal && !needs_color) { + if (!needs_color && !_c->lighting_enabled) { // With no per-vertex lighting, and no per-vertex colors, we might as well // use the flat shading model. shade_model = ShadeModelAttrib::M_flat; @@ -1352,7 +1352,12 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, int xo, yo, w, h; dr->get_region_pixels_i(xo, yo, w, h); - tex->setup_2d_texture(w, h, Texture::T_unsigned_byte, Texture::F_rgba); + Texture::Format format = Texture::F_rgba; + if (_current_properties->get_srgb_color()) { + format = Texture::F_srgb_alpha; + } + + tex->setup_2d_texture(w, h, Texture::T_unsigned_byte, format); TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); nassertr(tc != nullptr, false); @@ -1412,6 +1417,9 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, Texture::ComponentType component_type = Texture::T_unsigned_byte; Texture::Format format = Texture::F_rgba; + if (_current_properties->get_srgb_color()) { + format = Texture::F_srgb_alpha; + } if (tex->get_x_size() != w || tex->get_y_size() != h || tex->get_z_size() != z_size || diff --git a/pandatool/src/deploy-stub/deploy-stub.c b/pandatool/src/deploy-stub/deploy-stub.c index 7e0b22464d..6cd2c2803c 100644 --- a/pandatool/src/deploy-stub/deploy-stub.c +++ b/pandatool/src/deploy-stub/deploy-stub.c @@ -712,7 +712,9 @@ int main(int argc, char *argv[]) { new_moddef->code = moddef->code; new_moddef->size = moddef->size < 0 ? -(moddef->size) : moddef->size; new_moddef->is_package = moddef->size < 0; +#if PY_VERSION_HEX < 0x030d0000 // 3.13 new_moddef->get_code = NULL; +#endif new_moddef++; } #endif diff --git a/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx b/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx index 2309c4dc36..7f0ad0a4bd 100644 --- a/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx +++ b/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx @@ -161,7 +161,7 @@ do_update() { _last_level_index = view.get_level_index(); const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data->get_num_collectors() > _collector_items.size()) { + if ((size_t)client_data->get_num_collectors() > _collector_items.size()) { _collector_items.resize(client_data->get_num_collectors(), std::make_pair(nullptr, nullptr)); } @@ -226,7 +226,7 @@ add_view(GtkWidget *parent_menu, const PStatViewLevel *view_level, } else if (menu_item != nullptr && menu == nullptr) { // Unhook the signal handler, we are creating a submenu. - GtkStatsMonitor::MenuDef smd(_thread_index, collector, GtkStatsMonitor::CT_strip_chart, show_level); + GtkStatsMonitor::MenuDef smd(GtkStatsMonitor::CT_strip_chart, _thread_index, collector, -1, show_level); const GtkStatsMonitor::MenuDef *menu_def = _monitor->add_menu(smd); g_signal_handlers_disconnect_by_data(G_OBJECT(menu_item), (void *)menu_def); @@ -277,7 +277,7 @@ add_view(GtkWidget *parent_menu, const PStatViewLevel *view_level, GtkWidget *GtkStatsChartMenu:: make_menu_item(const char *label, int collector_index, ChartType chart_type, bool show_level) { - GtkStatsMonitor::MenuDef smd(_thread_index, collector_index, chart_type, show_level); + GtkStatsMonitor::MenuDef smd(chart_type, _thread_index, collector_index, -1, show_level); const GtkStatsMonitor::MenuDef *menu_def = _monitor->add_menu(smd); GtkWidget *menu_item = gtk_menu_item_new_with_label(label); diff --git a/pandatool/src/gtk-stats/gtkStatsFlameGraph.cxx b/pandatool/src/gtk-stats/gtkStatsFlameGraph.cxx index dcd1491485..ea20558b9b 100644 --- a/pandatool/src/gtk-stats/gtkStatsFlameGraph.cxx +++ b/pandatool/src/gtk-stats/gtkStatsFlameGraph.cxx @@ -24,13 +24,16 @@ static const int default_flame_graph_height = 150; */ GtkStatsFlameGraph:: GtkStatsFlameGraph(GtkStatsMonitor *monitor, int thread_index, - int collector_index) : - PStatFlameGraph(monitor, thread_index, collector_index, 0, 0), + int collector_index, int frame_number) : + PStatFlameGraph(monitor, thread_index, collector_index, frame_number, 0, 0), GtkStatsGraph(monitor, false) { // Let's show the units on the guide bar labels. There's room. set_guide_bar_units(get_guide_bar_units() | GBU_show_units); + std::string window_title = get_title_text(); + gtk_window_set_title(GTK_WINDOW(_window), window_title.c_str()); + // Put some stuff on top of the graph. _top_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start(GTK_BOX(_graph_vbox), _top_hbox, @@ -51,6 +54,13 @@ GtkStatsFlameGraph(GtkStatsMonitor *monitor, int thread_index, gtk_box_pack_start(GTK_BOX(_top_hbox), _scale_area, TRUE, TRUE, 0); gtk_box_pack_end(GTK_BOX(_top_hbox), _total_label, FALSE, FALSE, 0); + // Listen for mouse scroll and keyboard events. + gtk_widget_add_events(_window, GDK_SCROLL_MASK | GDK_KEY_PRESS_MASK); + g_signal_connect(G_OBJECT(_window), "scroll_event", + G_CALLBACK(scroll_callback), this); + g_signal_connect(G_OBJECT(_window), "key_press_event", + G_CALLBACK(key_press_callback), this); + gtk_widget_set_size_request(_graph_window, default_flame_graph_width * monitor->get_resolution() / 96, default_flame_graph_height * monitor->get_resolution() / 96); @@ -151,7 +161,7 @@ set_time_units(int unit_mask) { */ void GtkStatsFlameGraph:: on_click_label(int collector_index) { - set_collector_index(collector_index); + push_collector_index(collector_index); } /** @@ -284,6 +294,15 @@ draw_bar(int depth, int from_x, int to_x, int collector_index, int parent_index) pango_layout_set_text(layout, def._name.c_str(), def._name.size()); } } + else if (collector_index == 0 && get_frame_number() >= 0) { + char text[32]; + sprintf(text, "Frame %d", get_frame_number()); + pango_layout_set_text(layout, text, -1); + if (pango_layout_is_ellipsized(layout)) { + // Nope, it's too long, go back. + pango_layout_set_text(layout, def._name.c_str(), def._name.size()); + } + } } int width, height; @@ -421,7 +440,7 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(+[] (GtkWidget *widget, gpointer data) { GtkStatsFlameGraph *self = (GtkStatsFlameGraph *)data; - self->set_collector_index(self->_popup_index); + self->push_collector_index(self->_popup_index); }), this); } @@ -429,8 +448,7 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - get_thread_index(), collector_index, - GtkStatsMonitor::CT_strip_chart, false, + GtkStatsMonitor::CT_strip_chart, get_thread_index(), collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Strip Chart"); @@ -442,8 +460,7 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - get_thread_index(), collector_index, - GtkStatsMonitor::CT_flame_graph, + GtkStatsMonitor::CT_flame_graph, get_thread_index(), collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Flame Graph"); @@ -460,8 +477,7 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - -1, collector_index, - GtkStatsMonitor::CT_choose_color, + GtkStatsMonitor::CT_choose_color, -1, collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Change Color..."); @@ -473,8 +489,7 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - -1, collector_index, - GtkStatsMonitor::CT_reset_color, + GtkStatsMonitor::CT_reset_color, -1, collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Reset Color"); @@ -493,7 +508,13 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { else if (double_click && button == 1) { // Double-clicking on a color bar in the graph will zoom the graph into // that collector. - set_collector_index(collector_index); + if (collector_index >= 0) { + push_collector_index(collector_index); + } else { + // Double-clicking the background goes to the top. + clear_history(); + set_collector_index(-1); + } return TRUE; } } @@ -721,3 +742,73 @@ draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data) { return TRUE; } + +/** + * + */ +gboolean GtkStatsFlameGraph:: +scroll_callback(GtkWidget *widget, GdkEventScroll *event, gpointer data) { + GtkStatsFlameGraph *self = (GtkStatsFlameGraph *)data; + bool changed = false; + switch (event->direction) { + case GDK_SCROLL_LEFT: + changed = self->prev_frame(); + break; + + case GDK_SCROLL_RIGHT: + changed = self->next_frame(); + break; + } + + if (changed) { + std::string window_title = self->get_title_text(); + gtk_window_set_title(GTK_WINDOW(self->_window), window_title.c_str()); + return TRUE; + } else { + return FALSE; + } +} + +/** + * + */ +gboolean GtkStatsFlameGraph:: +key_press_callback(GtkWidget *widget, GdkEventKey *event, gpointer data) { + GtkStatsFlameGraph *self = (GtkStatsFlameGraph *)data; + bool changed = false; + switch (event->keyval) { + case GDK_KEY_Left: + if (event->state & GDK_MOD1_MASK) { + changed = self->pop_collector_index(); + } else { + changed = self->prev_frame(); + } + break; + + case GDK_KEY_Right: + if ((event->state & GDK_MOD1_MASK) == 0) { + changed = self->next_frame(); + } + break; + + case GDK_KEY_Home: + if ((event->state & GDK_MOD1_MASK) == 0) { + changed = self->first_frame(); + } + break; + + case GDK_KEY_End: + if ((event->state & GDK_MOD1_MASK) == 0) { + changed = self->last_frame(); + } + break; + } + + if (changed) { + std::string window_title = self->get_title_text(); + gtk_window_set_title(GTK_WINDOW(self->_window), window_title.c_str()); + return TRUE; + } else { + return FALSE; + } +} diff --git a/pandatool/src/gtk-stats/gtkStatsFlameGraph.h b/pandatool/src/gtk-stats/gtkStatsFlameGraph.h index eb2eb5e5e4..1381ca801f 100644 --- a/pandatool/src/gtk-stats/gtkStatsFlameGraph.h +++ b/pandatool/src/gtk-stats/gtkStatsFlameGraph.h @@ -28,7 +28,7 @@ class GtkStatsLabel; class GtkStatsFlameGraph final : public PStatFlameGraph, public GtkStatsGraph { public: GtkStatsFlameGraph(GtkStatsMonitor *monitor, int thread_index, - int collector_index=-1); + int collector_index=-1, int frame_number=-1); virtual ~GtkStatsFlameGraph(); virtual void new_collector(int collector_index); @@ -76,6 +76,8 @@ private: static void toggled_callback(GtkToggleButton *button, gpointer data); static gboolean draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data); + static gboolean scroll_callback(GtkWidget *widget, GdkEventScroll *event, gpointer data); + static gboolean key_press_callback(GtkWidget *widget, GdkEventKey *event, gpointer data); private: std::string _net_value_text; diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.I b/pandatool/src/gtk-stats/gtkStatsMonitor.I index b3e8e55b13..867c4349fb 100644 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.I +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.I @@ -15,10 +15,12 @@ * */ INLINE GtkStatsMonitor::MenuDef:: -MenuDef(int thread_index, int collector_index, ChartType chart_type, bool show_level) : +MenuDef(ChartType chart_type, int thread_index, int collector_index, + int frame_number, bool show_level) : + _chart_type(chart_type), _thread_index(thread_index), _collector_index(collector_index), - _chart_type(chart_type), + _frame_number(frame_number), _show_level(show_level), _monitor(nullptr) { @@ -29,14 +31,17 @@ MenuDef(int thread_index, int collector_index, ChartType chart_type, bool show_l */ INLINE bool GtkStatsMonitor::MenuDef:: operator < (const MenuDef &other) const { + if (_chart_type != other._chart_type) { + return _chart_type < other._chart_type; + } if (_thread_index != other._thread_index) { return _thread_index < other._thread_index; } if (_collector_index != other._collector_index) { return _collector_index < other._collector_index; } - if (_chart_type != other._chart_type) { - return _chart_type < other._chart_type; + if (_frame_number != other._frame_number) { + return _frame_number < other._frame_number; } return (int)_show_level < (int)other._show_level; } diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx index 0410504457..2be16d9434 100644 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx @@ -316,8 +316,8 @@ open_timeline() { * Opens a new flame graph showing the indicated data. */ PStatGraph *GtkStatsMonitor:: -open_flame_graph(int thread_index, int collector_index) { - GtkStatsFlameGraph *graph = new GtkStatsFlameGraph(this, thread_index, collector_index); +open_flame_graph(int thread_index, int collector_index, int frame_number) { + GtkStatsFlameGraph *graph = new GtkStatsFlameGraph(this, thread_index, collector_index, frame_number); add_graph(graph); return graph; } @@ -734,7 +734,7 @@ status_bar_button_event(GtkWidget *widget, GdkEventButton *event, gpointer data) const PStatViewLevel *child_level = view_level->get_child(c); int child_collector = child_level->get_collector(); - const MenuDef *menu_def = monitor->add_menu({0, child_collector, CT_strip_chart, true}); + const MenuDef *menu_def = monitor->add_menu({CT_strip_chart, 0, child_collector, -1, true}); double value = child_level->get_net_value(); @@ -787,7 +787,8 @@ menu_activate(GtkWidget *widget, gpointer data) { case CT_flame_graph: monitor->open_flame_graph(menu_def._thread_index, - menu_def._collector_index); + menu_def._collector_index, + menu_def._frame_number); break; case CT_piano_roll: @@ -853,7 +854,7 @@ handle_status_bar_popup(int item) { const PStatViewLevel *child_level = view_level->get_child(c); int child_collector = child_level->get_collector(); - const MenuDef *menu_def = add_menu({0, child_collector, CT_strip_chart, true}); + const MenuDef *menu_def = add_menu({CT_strip_chart, 0, child_collector, -1, true}); double value = child_level->get_net_value(); diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.h b/pandatool/src/gtk-stats/gtkStatsMonitor.h index 6a6c1e091f..3ac15abad5 100644 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.h +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.h @@ -46,13 +46,14 @@ public: class MenuDef { public: - INLINE MenuDef(int thread_index, int collector_index, - ChartType chart_type, bool show_level = false); + INLINE MenuDef(ChartType chart_type, int thread_index, int collector_index, + int frame_number = -1, bool show_level = false); INLINE bool operator < (const MenuDef &other) const; + ChartType _chart_type; int _thread_index; int _collector_index; - ChartType _chart_type; + int _frame_number; bool _show_level; GtkStatsMonitor *_monitor; }; @@ -84,7 +85,7 @@ public: PStatGraph *open_timeline(); PStatGraph *open_strip_chart(int thread_index, int collector_index, bool show_level); - PStatGraph *open_flame_graph(int thread_index, int collector_index = -1); + PStatGraph *open_flame_graph(int thread_index, int collector_index = -1, int frame_number = -1); PStatGraph *open_piano_roll(int thread_index); void choose_collector_color(int collector_index); diff --git a/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx b/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx index fbab6cb1ef..da5e6b3694 100644 --- a/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx +++ b/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx @@ -149,7 +149,7 @@ on_popup_label(int collector_index) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - _thread_index, collector_index, GtkStatsMonitor::CT_strip_chart, false, + GtkStatsMonitor::CT_strip_chart, _thread_index, collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Strip Chart"); @@ -161,7 +161,7 @@ on_popup_label(int collector_index) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - _thread_index, collector_index, GtkStatsMonitor::CT_flame_graph, + GtkStatsMonitor::CT_flame_graph, _thread_index, collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Flame Graph"); @@ -178,7 +178,7 @@ on_popup_label(int collector_index) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - -1, collector_index, GtkStatsMonitor::CT_choose_color, + GtkStatsMonitor::CT_choose_color, -1, collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Change Color..."); @@ -190,7 +190,7 @@ on_popup_label(int collector_index) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - -1, collector_index, GtkStatsMonitor::CT_reset_color, + GtkStatsMonitor::CT_reset_color, -1, collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Reset Color"); diff --git a/pandatool/src/gtk-stats/gtkStatsStripChart.cxx b/pandatool/src/gtk-stats/gtkStatsStripChart.cxx index f956cdfa9a..0be191da40 100644 --- a/pandatool/src/gtk-stats/gtkStatsStripChart.cxx +++ b/pandatool/src/gtk-stats/gtkStatsStripChart.cxx @@ -243,8 +243,8 @@ on_popup_label(int collector_index) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - _thread_index, collector_index, - GtkStatsMonitor::CT_strip_chart, get_view().get_show_level(), + GtkStatsMonitor::CT_strip_chart, _thread_index, collector_index, -1, + get_view().get_show_level(), }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Strip Chart"); @@ -256,7 +256,7 @@ on_popup_label(int collector_index) { if (!get_view().get_show_level()) { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - _thread_index, collector_index, GtkStatsMonitor::CT_flame_graph, + GtkStatsMonitor::CT_flame_graph, _thread_index, collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Flame Graph"); @@ -273,7 +273,7 @@ on_popup_label(int collector_index) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - -1, collector_index, GtkStatsMonitor::CT_choose_color, + GtkStatsMonitor::CT_choose_color, -1, collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Change Color..."); @@ -285,7 +285,7 @@ on_popup_label(int collector_index) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - -1, collector_index, GtkStatsMonitor::CT_reset_color, + GtkStatsMonitor::CT_reset_color, -1, collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Reset Color"); diff --git a/pandatool/src/gtk-stats/gtkStatsTimeline.cxx b/pandatool/src/gtk-stats/gtkStatsTimeline.cxx index a58100f637..5010b2dabc 100644 --- a/pandatool/src/gtk-stats/gtkStatsTimeline.cxx +++ b/pandatool/src/gtk-stats/gtkStatsTimeline.cxx @@ -409,8 +409,8 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ + GtkStatsMonitor::CT_strip_chart, bar._thread_index, bar._collector_index, - GtkStatsMonitor::CT_strip_chart, false, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Strip Chart"); @@ -422,8 +422,8 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - bar._thread_index, bar._collector_index, GtkStatsMonitor::CT_flame_graph, + bar._thread_index, bar._collector_index, bar._frame_number, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Flame Graph"); @@ -435,7 +435,7 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - bar._thread_index, -1, GtkStatsMonitor::CT_piano_roll, + GtkStatsMonitor::CT_piano_roll, bar._thread_index, -1, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Piano Roll"); @@ -452,8 +452,7 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - -1, bar._collector_index, - GtkStatsMonitor::CT_choose_color, + GtkStatsMonitor::CT_choose_color, -1, bar._collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Change Color..."); @@ -465,8 +464,7 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { { const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - -1, bar._collector_index, - GtkStatsMonitor::CT_reset_color, + GtkStatsMonitor::CT_reset_color, -1, bar._collector_index, }); GtkWidget *menu_item = gtk_menu_item_new_with_label("Reset Color"); diff --git a/pandatool/src/imageprogs/imageFixHiddenColor.cxx b/pandatool/src/imageprogs/imageFixHiddenColor.cxx index a3d176bfb4..44d1c91aaf 100644 --- a/pandatool/src/imageprogs/imageFixHiddenColor.cxx +++ b/pandatool/src/imageprogs/imageFixHiddenColor.cxx @@ -104,7 +104,7 @@ run() { // First, get the average color of all the opaque pixels. int count = 0; - LRGBColor color(0.0, 0.0, 0.0); + LRGBColorf color(0.0, 0.0, 0.0); int xi, yi; for (yi = 0; yi < _image.get_y_size(); ++yi) { for (xi = 0; xi < _image.get_x_size(); ++xi) { diff --git a/pandatool/src/mac-stats/macStatsFlameGraph.h b/pandatool/src/mac-stats/macStatsFlameGraph.h index 25df1f96c8..a678e887ba 100644 --- a/pandatool/src/mac-stats/macStatsFlameGraph.h +++ b/pandatool/src/mac-stats/macStatsFlameGraph.h @@ -25,7 +25,7 @@ class MacStatsFlameGraph final : public PStatFlameGraph, public MacStatsGraph { public: MacStatsFlameGraph(MacStatsMonitor *monitor, int thread_index, - int collector_index=-1); + int collector_index=-1, int frame_number=-1); virtual ~MacStatsFlameGraph(); virtual void new_collector(int collector_index); @@ -60,11 +60,14 @@ protected: virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; virtual DragMode consider_drag_start(int graph_x, int graph_y); + virtual bool handle_key(int graph_x, int graph_y, bool pressed, + UniChar c, unsigned short key_code); virtual void handle_button_press(int graph_x, int graph_y, - bool double_click, int button); + bool double_click, int button); virtual void handle_button_release(int graph_x, int graph_y); virtual void handle_motion(int graph_x, int graph_y); virtual void handle_leave(); + virtual void handle_wheel(int graph_x, int graph_y, double dx, double dy); virtual void handle_draw_graph(CGContextRef ctx, NSRect rect); virtual void handle_back(); @@ -81,8 +84,6 @@ private: NSToolbarItem *_total_item; MacStatsChartMenuDelegate *_menu_delegate; - - std::vector _back_stack; }; #endif diff --git a/pandatool/src/mac-stats/macStatsFlameGraph.mm b/pandatool/src/mac-stats/macStatsFlameGraph.mm index 60314147f8..003629d474 100644 --- a/pandatool/src/mac-stats/macStatsFlameGraph.mm +++ b/pandatool/src/mac-stats/macStatsFlameGraph.mm @@ -29,8 +29,8 @@ static const int default_flame_graph_height = 250; */ MacStatsFlameGraph:: MacStatsFlameGraph(MacStatsMonitor *monitor, int thread_index, - int collector_index) : - PStatFlameGraph(monitor, thread_index, collector_index, 0, 0), + int collector_index, int frame_number) : + PStatFlameGraph(monitor, thread_index, collector_index, frame_number, 0, 0), MacStatsGraph(monitor, [MacStatsFlameGraphViewController alloc]) { // Used for popup menus. @@ -177,11 +177,10 @@ void MacStatsFlameGraph:: on_click_label(int collector_index) { int current = get_collector_index(); if (collector_index != current) { - if (_back_stack.empty()) { + if (get_history_depth() == 0) { _graph_view_controller.backToolbarItemVisible = YES; } - _back_stack.push_back(current); - set_collector_index(collector_index); + push_collector_index(collector_index); std::string window_title = get_title_text(); if (!is_title_unknown()) { @@ -538,6 +537,43 @@ consider_drag_start(int graph_x, int graph_y) { return DM_none; } +/** + * + */ +bool MacStatsFlameGraph:: +handle_key(int graph_x, int graph_y, bool pressed, UniChar c, unsigned short key_code) { + bool changed = false; + + if (pressed) { + switch (c) { + case NSLeftArrowFunctionKey: + changed = prev_frame(); + break; + + case NSRightArrowFunctionKey: + changed = next_frame(); + break; + + case NSHomeFunctionKey: + changed = first_frame(); + break; + + case NSEndFunctionKey: + changed = last_frame(); + break; + } + } + + if (changed) { + std::string window_title = get_title_text(); + if (!is_title_unknown()) { + _window.title = [NSString stringWithUTF8String:window_title.c_str()]; + } + } + + return changed; +} + /** * Called when the mouse button is depressed within the graph window. */ @@ -552,11 +588,12 @@ handle_button_press(int graph_x, int graph_y, bool double_click, int button) { if (collector_index >= 0) { on_click_label(collector_index); } else { - if (!_back_stack.empty()) { - _back_stack.clear(); + if (get_history_depth() > 0) { + clear_history(); _graph_view_controller.backToolbarItemVisible = NO; } set_collector_index(-1); + std::string window_title = get_title_text(); if (!is_title_unknown()) { _window.title = [NSString stringWithUTF8String:window_title.c_str()]; @@ -652,6 +689,21 @@ handle_leave() { return; } +/** + * + */ +void MacStatsFlameGraph:: +handle_wheel(int graph_x, int graph_y, double dx, double dy) { + if (dx != 0.0) { + if ((dx > 0.0) ? prev_frame() : next_frame()) { + std::string window_title = get_title_text(); + if (!is_title_unknown()) { + _window.title = [NSString stringWithUTF8String:window_title.c_str()]; + } + } + } +} + /** * Fills in the graph window. */ @@ -674,12 +726,8 @@ handle_draw_graph(CGContextRef ctx, NSRect rect) { */ void MacStatsFlameGraph:: handle_back() { - if (!_back_stack.empty()) { - int collector_index = _back_stack.back(); - _back_stack.pop_back(); - set_collector_index(collector_index); - - if (_back_stack.empty()) { + if (pop_collector_index()) { + if (get_history_depth() == 0) { _graph_view_controller.backToolbarItemVisible = NO; } diff --git a/pandatool/src/mac-stats/macStatsGraphView.mm b/pandatool/src/mac-stats/macStatsGraphView.mm index 013b424139..82b2d5d8e8 100644 --- a/pandatool/src/mac-stats/macStatsGraphView.mm +++ b/pandatool/src/mac-stats/macStatsGraphView.mm @@ -45,15 +45,13 @@ } - (void)keyDown:(NSEvent *)event { - if (!event.isARepeat) { - NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; - UniChar c = 0; - NSString *str = [event charactersIgnoringModifiers]; - if (str != nil && str.length == 1) { - c = [str characterAtIndex:0]; - } - _graph->handle_key(pos.x, pos.y, true, c, event.keyCode); + NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; + UniChar c = 0; + NSString *str = [event charactersIgnoringModifiers]; + if (str != nil && str.length == 1) { + c = [str characterAtIndex:0]; } + _graph->handle_key(pos.x, pos.y, true, c, event.keyCode); } - (void)keyUp:(NSEvent *)event { diff --git a/pandatool/src/mac-stats/macStatsMonitor.h b/pandatool/src/mac-stats/macStatsMonitor.h index 8e12677963..8c5d0c3164 100644 --- a/pandatool/src/mac-stats/macStatsMonitor.h +++ b/pandatool/src/mac-stats/macStatsMonitor.h @@ -57,7 +57,7 @@ public: PStatGraph *open_timeline(); PStatGraph *open_strip_chart(int thread_index, int collector_index, bool show_level); - PStatGraph *open_flame_graph(int thread_index, int collector_index = -1); + PStatGraph *open_flame_graph(int thread_index, int collector_index = -1, int frame_number = -1); PStatGraph *open_piano_roll(int thread_index); CGColorRef get_collector_color(int collector_index, bool highlight = false); diff --git a/pandatool/src/mac-stats/macStatsMonitor.mm b/pandatool/src/mac-stats/macStatsMonitor.mm index 7d001e39a5..57245e0208 100644 --- a/pandatool/src/mac-stats/macStatsMonitor.mm +++ b/pandatool/src/mac-stats/macStatsMonitor.mm @@ -312,9 +312,9 @@ open_timeline() { * Opens a new flame graph showing the indicated data. */ PStatGraph *MacStatsMonitor:: -open_flame_graph(int thread_index, int collector_index) { +open_flame_graph(int thread_index, int collector_index, int frame_number) { MacStatsFlameGraph *graph = - new MacStatsFlameGraph(this, thread_index, collector_index); + new MacStatsFlameGraph(this, thread_index, collector_index, frame_number); add_graph(graph); return graph; } diff --git a/pandatool/src/mac-stats/macStatsTimeline.mm b/pandatool/src/mac-stats/macStatsTimeline.mm index 464edde12d..85f5c89e30 100644 --- a/pandatool/src/mac-stats/macStatsTimeline.mm +++ b/pandatool/src/mac-stats/macStatsTimeline.mm @@ -819,7 +819,7 @@ handle_open_strip_chart() { void MacStatsTimeline:: handle_open_flame_graph() { const ColorBar &bar = _popup_bar; - MacStatsGraph::_monitor->open_flame_graph(bar._thread_index, bar._collector_index); + MacStatsGraph::_monitor->open_flame_graph(bar._thread_index, bar._collector_index, bar._frame_number); } /** diff --git a/pandatool/src/palettizer/txaLine.cxx b/pandatool/src/palettizer/txaLine.cxx index 6d04b5daf1..bf3b645ca6 100644 --- a/pandatool/src/palettizer/txaLine.cxx +++ b/pandatool/src/palettizer/txaLine.cxx @@ -357,6 +357,7 @@ match_egg(EggFile *egg_file) const { case KW_linear: case KW_mipmap: case KW_anisotropic: + case KW_srgb: // These mean nothing to an egg file. break; diff --git a/pandatool/src/pstatserver/pStatFlameGraph.I b/pandatool/src/pstatserver/pStatFlameGraph.I index 2ab06a159c..e99afd04af 100644 --- a/pandatool/src/pstatserver/pStatFlameGraph.I +++ b/pandatool/src/pstatserver/pStatFlameGraph.I @@ -27,6 +27,31 @@ get_collector_index() const { return _collector_index; } +/** + * Clears the history stack. + */ +INLINE void PStatFlameGraph:: +clear_history() { + _history.clear(); +} + +/** + * Returns the depth of the history stack. + */ +INLINE size_t PStatFlameGraph:: +get_history_depth() const { + return _history.size(); +} + +/** + * Returns the particular frame number whose data this flame graph reflects. + * Returns -1 if we're looking at a moving average instead. + */ +INLINE int PStatFlameGraph:: +get_frame_number() const { + return _frame_number; +} + /** * Returns the amount of total time the width of the horizontal axis * represents. diff --git a/pandatool/src/pstatserver/pStatFlameGraph.cxx b/pandatool/src/pstatserver/pStatFlameGraph.cxx index b549be26bf..9343682955 100644 --- a/pandatool/src/pstatserver/pStatFlameGraph.cxx +++ b/pandatool/src/pstatserver/pStatFlameGraph.cxx @@ -25,12 +25,13 @@ * */ PStatFlameGraph:: -PStatFlameGraph(PStatMonitor *monitor, - int thread_index, int collector_index, int xsize, int ysize) : +PStatFlameGraph(PStatMonitor *monitor, int thread_index, int collector_index, + int frame_number, int xsize, int ysize) : PStatGraph(monitor, xsize, ysize), _thread_index(thread_index), _collector_index(collector_index), - _orig_collector_index(collector_index) + _orig_collector_index(collector_index), + _frame_number(frame_number) { _average_mode = true; _average_cursor = 0; @@ -73,11 +74,20 @@ update() { const PStatThreadData *thread_data = client_data->get_thread_data(_thread_index); if (!thread_data->is_empty()) { - int frame_number = thread_data->get_latest_frame_number(); - if (frame_number != _current_frame) { - _current_frame = frame_number; + if (_frame_number >= 0) { + if (thread_data->has_frame(_frame_number)) { + if (_current_frame != _frame_number) { + _current_frame = _frame_number; + update_data(); + } + } + } else { + int frame_number = thread_data->get_latest_frame_number(); + if (frame_number != _current_frame) { + _current_frame = frame_number; - update_data(); + update_data(); + } } } } @@ -88,6 +98,8 @@ update() { /** * Changes the collector represented by this flame graph. This may force a * redraw. + * + * Leaves the history stack untouched. */ void PStatFlameGraph:: set_collector_index(int collector_index) { @@ -117,6 +129,168 @@ set_collector_index(int collector_index) { } } +/** + * Goes to a different collector, but remembers the previous collector. + */ +void PStatFlameGraph:: +push_collector_index(int collector_index) { + if (_collector_index != collector_index) { + _history.push_back(_collector_index); + set_collector_index(collector_index); + } +} + +/** + * Goes to the previous visited collector. Returns true if the history stack + * was non-empty. + */ +bool PStatFlameGraph:: +pop_collector_index() { + if (!_history.empty()) { + int collector_index = _history.back(); + _history.pop_back(); + set_collector_index(collector_index); + return true; + } + return false; +} + +/** + * Changes the frame number shown by this flame graph. This may force a redraw. + */ +void PStatFlameGraph:: +set_frame_number(int frame_number) { + if (_frame_number != frame_number) { + _frame_number = frame_number; + _current_frame = frame_number; + _title_unknown = true; + _stack.clear(); + update_data(); + + if (_average_mode) { + _stack.update_averages(_average_cursor); + _time_width = _stack.get_net_value(true); + if (_time_width == 0.0) { + _time_width = 1.0 / pstats_target_frame_rate; + } + normal_guide_bars(); + } + } +} + +/** + * Sets the frame number to the oldest available frame. + */ +bool PStatFlameGraph:: +first_frame() { + const PStatClientData *client_data = _monitor->get_client_data(); + if (client_data == nullptr) { + return false; + } + + const PStatThreadData *thread_data = client_data->get_thread_data(_thread_index); + if (thread_data == nullptr || thread_data->is_empty()) { + return false; + } + + int oldest = thread_data->get_oldest_frame_number(); + if (_frame_number != oldest && thread_data->has_frame(oldest)) { + set_frame_number(oldest); + return true; + } + return false; +} + +/** + * Advances to the next available frame. Returns true if the frame number was + * changed after a call to this method. + */ +bool PStatFlameGraph:: +next_frame() { + const PStatClientData *client_data = _monitor->get_client_data(); + if (client_data == nullptr) { + return false; + } + + const PStatThreadData *thread_data = client_data->get_thread_data(_thread_index); + if (thread_data == nullptr || thread_data->is_empty()) { + return false; + } + + int latest = thread_data->get_latest_frame_number(); + if (_frame_number < 0 || _frame_number > latest) { + set_frame_number(latest); + return true; + } + + for (int i = _frame_number + 1; i <= latest; ++i) { + if (thread_data->has_frame(i)) { + set_frame_number(i); + return true; + } + } + + return false; +} + +/** + * Reverts to the previous frame. Returns true if the frame number was changed + * after a call to this method. + */ +bool PStatFlameGraph:: +prev_frame() { + const PStatClientData *client_data = _monitor->get_client_data(); + if (client_data == nullptr) { + return false; + } + + const PStatThreadData *thread_data = client_data->get_thread_data(_thread_index); + if (thread_data == nullptr || thread_data->is_empty()) { + return false; + } + + int oldest = thread_data->get_oldest_frame_number(); + + int i; + if (_frame_number < 0) { + i = thread_data->get_latest_frame_number(); + } else { + i = _frame_number - 1; + } + while (i >= oldest) { + if (thread_data->has_frame(i)) { + set_frame_number(i); + return true; + } + --i; + } + + return false; +} + +/** + * Sets the frame number to the latest available frame. + */ +bool PStatFlameGraph:: +last_frame() { + const PStatClientData *client_data = _monitor->get_client_data(); + if (client_data == nullptr) { + return false; + } + + const PStatThreadData *thread_data = client_data->get_thread_data(_thread_index); + if (thread_data == nullptr || thread_data->is_empty()) { + return false; + } + + int latest = thread_data->get_latest_frame_number(); + if (_frame_number != latest && thread_data->has_frame(latest)) { + set_frame_number(latest); + return true; + } + return false; +} + /** * Returns the text suitable for the title label on the top line. */ @@ -150,6 +324,10 @@ get_title_text() { _title_unknown = true; } + if (_frame_number >= 0) { + text += " (frame " + format_string(_frame_number) + ")"; + } + return text; } diff --git a/pandatool/src/pstatserver/pStatFlameGraph.h b/pandatool/src/pstatserver/pStatFlameGraph.h index 721651e43d..5e742383b2 100644 --- a/pandatool/src/pstatserver/pStatFlameGraph.h +++ b/pandatool/src/pstatserver/pStatFlameGraph.h @@ -36,7 +36,7 @@ class PStatFrameData; class PStatFlameGraph : public PStatGraph { public: PStatFlameGraph(PStatMonitor *monitor, - int thread_index, int collector_index, + int thread_index, int collector_index, int frame_number, int xsize, int ysize); virtual ~PStatFlameGraph(); @@ -45,6 +45,17 @@ public: INLINE int get_thread_index() const; INLINE int get_collector_index() const; void set_collector_index(int collector_index); + void push_collector_index(int collector_index); + bool pop_collector_index(); + INLINE void clear_history(); + INLINE size_t get_history_depth() const; + + INLINE int get_frame_number() const; + void set_frame_number(int collector_index); + bool first_frame(); + bool next_frame(); + bool prev_frame(); + bool last_frame(); INLINE double get_horizontal_scale() const; @@ -123,12 +134,15 @@ private: int _thread_index; int _collector_index; int _orig_collector_index; + int _frame_number; bool _average_mode; size_t _average_cursor; double _time_width; int _current_frame; bool _title_unknown; + + std::vector _history; }; #include "pStatFlameGraph.I" diff --git a/pandatool/src/pstatserver/pStatMonitor.cxx b/pandatool/src/pstatserver/pStatMonitor.cxx index 86390d5ab7..cbc49a7140 100644 --- a/pandatool/src/pstatserver/pStatMonitor.cxx +++ b/pandatool/src/pstatserver/pStatMonitor.cxx @@ -654,7 +654,7 @@ open_strip_chart(int thread_index, int collector_index, bool show_level) { * Opens a new flame graph showing the indicated data. */ PStatGraph *PStatMonitor:: -open_flame_graph(int thread_index, int collector_index) { +open_flame_graph(int thread_index, int collector_index, int frame_number) { return nullptr; } diff --git a/pandatool/src/pstatserver/pStatMonitor.h b/pandatool/src/pstatserver/pStatMonitor.h index 5e71be4b53..d98ce2b9b0 100644 --- a/pandatool/src/pstatserver/pStatMonitor.h +++ b/pandatool/src/pstatserver/pStatMonitor.h @@ -104,7 +104,7 @@ public: virtual PStatGraph *open_timeline(); virtual PStatGraph *open_strip_chart(int thread_index, int collector_index, bool show_level); - virtual PStatGraph *open_flame_graph(int thread_index, int collector_index = -1); + virtual PStatGraph *open_flame_graph(int thread_index, int collector_index = -1, int frame_number = -1); virtual PStatGraph *open_piano_roll(int thread_index); void write_datagram(Datagram &dg) const; diff --git a/pandatool/src/pstatserver/pStatThreadData.cxx b/pandatool/src/pstatserver/pStatThreadData.cxx index 39957916c1..f7bf9e2c5f 100644 --- a/pandatool/src/pstatserver/pStatThreadData.cxx +++ b/pandatool/src/pstatserver/pStatThreadData.cxx @@ -235,7 +235,7 @@ get_frame_number_after(double time, int start_at) const { while (end < time) { ++i; - if (i >= _frames.size()) { + if ((size_t)i >= _frames.size()) { break; } if (_frames[i] != nullptr) { diff --git a/pandatool/src/win-stats/winStatsFlameGraph.cxx b/pandatool/src/win-stats/winStatsFlameGraph.cxx index 3b1f991dba..9c4d2f67ee 100644 --- a/pandatool/src/win-stats/winStatsFlameGraph.cxx +++ b/pandatool/src/win-stats/winStatsFlameGraph.cxx @@ -29,9 +29,9 @@ const char * const WinStatsFlameGraph::_window_class_name = "flame"; */ WinStatsFlameGraph:: WinStatsFlameGraph(WinStatsMonitor *monitor, int thread_index, - int collector_index) : + int collector_index, int frame_number) : PStatFlameGraph(monitor, - thread_index, collector_index, + thread_index, collector_index, frame_number, monitor->get_pixel_scale() * default_flame_graph_width / 4, monitor->get_pixel_scale() * default_flame_graph_height / 4), WinStatsGraph(monitor) @@ -127,7 +127,21 @@ set_time_units(int unit_mask) { */ void WinStatsFlameGraph:: on_click_label(int collector_index) { - set_collector_index(collector_index); + if (collector_index != get_collector_index()) { + if (collector_index == -1) { + clear_history(); + set_collector_index(-1); + } else { + push_collector_index(collector_index); + } + + if (is_title_unknown()) { + std::string window_title = get_title_text(); + if (!is_title_unknown()) { + SetWindowText(_window, window_title.c_str()); + } + } + } } /** @@ -159,22 +173,6 @@ on_leave_label(int collector_index) { } } -/** - * Changes the collector represented by this flame graph. This may force a - * redraw. - */ -void WinStatsFlameGraph:: -set_collector_index(int collector_index) { - PStatFlameGraph::set_collector_index(collector_index); - - if (is_title_unknown()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - SetWindowText(_window, window_title.c_str()); - } - } -} - /** * Calls update_guide_bars with parameters suitable to this kind of graph. */ @@ -349,6 +347,7 @@ LONG WinStatsFlameGraph:: window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case WM_LBUTTONDOWN: + SetFocus(_window); if (_potential_drag_mode == DM_new_guide_bar) { set_drag_mode(DM_new_guide_bar); SetCapture(_graph_window); @@ -372,7 +371,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { break; case 101: - set_collector_index(_popup_index); + on_click_label(_popup_index); return 0; case 102: @@ -393,6 +392,51 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } break; + case WM_KEYDOWN: + { + bool changed = false; + switch (wparam) { + case VK_LEFT: + changed = prev_frame(); + break; + case VK_RIGHT: + changed = next_frame(); + break; + case VK_HOME: + changed = first_frame(); + break; + case VK_END: + changed = last_frame(); + break; + } + if (changed) { + std::string window_title = get_title_text(); + SetWindowText(_window, window_title.c_str()); + return 0; + } + } + break; + + case WM_SYSKEYDOWN: + if (((lparam >> 16) & KF_ALTDOWN) != 0 && wparam == VK_LEFT) { + if (pop_collector_index()) { + std::string window_title = get_title_text(); + SetWindowText(_window, window_title.c_str()); + } + return 0; + } + break; + + case WM_APPCOMMAND: + if (GET_APPCOMMAND_LPARAM(lparam) == APPCOMMAND_BROWSER_BACKWARD) { + if (pop_collector_index()) { + std::string window_title = get_title_text(); + SetWindowText(_window, window_title.c_str()); + } + return TRUE; + } + break; + default: break; } @@ -407,6 +451,7 @@ LONG WinStatsFlameGraph:: graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case WM_LBUTTONDOWN: + SetFocus(_window); if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { set_drag_mode(DM_guide_bar); int16_t x = LOWORD(lparam); @@ -479,7 +524,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // that collector. int16_t x = LOWORD(lparam); int16_t y = HIWORD(lparam); - set_collector_index(get_bar_collector(pixel_to_depth(y), x)); + on_click_label(get_bar_collector(pixel_to_depth(y), x)); return 0; } break; @@ -518,6 +563,19 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } break; + case WM_MOUSEHWHEEL: + { + int delta = GET_WHEEL_DELTA_WPARAM(wparam); + if (delta != 0) { + if (delta > 0 ? next_frame() : prev_frame()) { + std::string window_title = get_title_text(); + SetWindowText(_window, window_title.c_str()); + } + } + return 0; + } + break; + default: break; } @@ -760,6 +818,8 @@ create_window() { // Ensure that the window is on top of the stack. SetWindowPos(_window, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + + SetFocus(_window); } /** diff --git a/pandatool/src/win-stats/winStatsFlameGraph.h b/pandatool/src/win-stats/winStatsFlameGraph.h index 950f046b17..6edae514ce 100644 --- a/pandatool/src/win-stats/winStatsFlameGraph.h +++ b/pandatool/src/win-stats/winStatsFlameGraph.h @@ -28,7 +28,7 @@ class WinStatsLabel; class WinStatsFlameGraph : public PStatFlameGraph, public WinStatsGraph { public: WinStatsFlameGraph(WinStatsMonitor *monitor, int thread_index, - int collector_index=-1); + int collector_index=-1, int frame_number=-1); virtual ~WinStatsFlameGraph(); virtual void new_data(int thread_index, int frame_number); @@ -40,8 +40,6 @@ public: virtual void on_enter_label(int collector_index); virtual void on_leave_label(int collector_index); - void set_collector_index(int collector_index); - protected: virtual void normal_guide_bars(); diff --git a/pandatool/src/win-stats/winStatsGraph.cxx b/pandatool/src/win-stats/winStatsGraph.cxx index a363a91805..d8d4118717 100644 --- a/pandatool/src/win-stats/winStatsGraph.cxx +++ b/pandatool/src/win-stats/winStatsGraph.cxx @@ -413,6 +413,13 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { close(); break; + case WM_APPCOMMAND: + if (GET_APPCOMMAND_LPARAM(lparam) == APPCOMMAND_CLOSE) { + close(); + return TRUE; + } + break; + case WM_GETMINMAXINFO: { WINDOWINFO winfo; diff --git a/pandatool/src/win-stats/winStatsMonitor.cxx b/pandatool/src/win-stats/winStatsMonitor.cxx index 18623f5c66..410d638884 100644 --- a/pandatool/src/win-stats/winStatsMonitor.cxx +++ b/pandatool/src/win-stats/winStatsMonitor.cxx @@ -332,8 +332,8 @@ open_strip_chart(int thread_index, int collector_index, bool show_level) { * Opens a new flame graph showing the indicated data. */ PStatGraph *WinStatsMonitor:: -open_flame_graph(int thread_index, int collector_index) { - WinStatsFlameGraph *graph = new WinStatsFlameGraph(this, thread_index, collector_index); +open_flame_graph(int thread_index, int collector_index, int frame_number) { + WinStatsFlameGraph *graph = new WinStatsFlameGraph(this, thread_index, collector_index, frame_number); add_graph(graph); return graph; } diff --git a/pandatool/src/win-stats/winStatsMonitor.h b/pandatool/src/win-stats/winStatsMonitor.h index 34338dc1a0..1fed3f9a9f 100644 --- a/pandatool/src/win-stats/winStatsMonitor.h +++ b/pandatool/src/win-stats/winStatsMonitor.h @@ -84,7 +84,7 @@ public: PStatGraph *open_timeline(); PStatGraph *open_strip_chart(int thread_index, int collector_index, bool show_level); - PStatGraph *open_flame_graph(int thread_index, int collector_index = -1); + PStatGraph *open_flame_graph(int thread_index, int collector_index = -1, int frame_number = -1); PStatGraph *open_piano_roll(int thread_index); void choose_collector_color(int collector_index); diff --git a/pandatool/src/win-stats/winStatsServer.cxx b/pandatool/src/win-stats/winStatsServer.cxx index 90faef49af..dd77cfbf0d 100644 --- a/pandatool/src/win-stats/winStatsServer.cxx +++ b/pandatool/src/win-stats/winStatsServer.cxx @@ -858,6 +858,18 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } break; + case WM_APPCOMMAND: + switch (GET_APPCOMMAND_LPARAM(lparam)) { + case APPCOMMAND_OPEN: + open_session(); + return TRUE; + + case APPCOMMAND_SAVE: + save_session(); + return TRUE; + } + break; + case WM_COMMAND: if (HIWORD(wparam) <= 1) { int menu_id = LOWORD(wparam); diff --git a/pandatool/src/win-stats/winStatsTimeline.cxx b/pandatool/src/win-stats/winStatsTimeline.cxx index 6a53415253..a9c3f6688a 100644 --- a/pandatool/src/win-stats/winStatsTimeline.cxx +++ b/pandatool/src/win-stats/winStatsTimeline.cxx @@ -463,7 +463,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { return 0; case 103: - WinStatsGraph::_monitor->open_flame_graph(_popup_bar._thread_index, _popup_bar._collector_index); + WinStatsGraph::_monitor->open_flame_graph(_popup_bar._thread_index, _popup_bar._collector_index, _popup_bar._frame_number); return 0; case 104: diff --git a/setup.cfg b/setup.cfg index f67637e357..c6e478a40e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,6 +19,7 @@ classifiers = Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 + Programming Language :: Python :: 3.13 Programming Language :: Python :: Implementation :: CPython Topic :: Games/Entertainment Topic :: Multimedia diff --git a/tests/dist/test_FreezeTool.py b/tests/dist/test_FreezeTool.py index e0eb82b7a5..d7b80b368c 100644 --- a/tests/dist/test_FreezeTool.py +++ b/tests/dist/test_FreezeTool.py @@ -103,5 +103,13 @@ def test_Freezer_generateRuntimeFromStub(tmp_path, use_console): # Not supported; see #1348 return - output = subprocess.check_output(target) + env = None + if sys.platform == "win32": + env = dict(os.environ) + if not os.environ.get('PATH'): + env['PATH'] = bin_dir + else: + env['PATH'] = bin_dir + os.pathsep + os.environ['PATH'] + + output = subprocess.check_output(target, env=env) assert output.replace(b'\r\n', b'\n') == b'Module imported\nHello world\n' diff --git a/tests/event/test_event.py b/tests/event/test_event.py index 947ed093a3..dbf98ba58c 100644 --- a/tests/event/test_event.py +++ b/tests/event/test_event.py @@ -31,8 +31,7 @@ def test_event_subclass_gc(): with gc_disabled(): event = PythonEvent('test_event_subclass_gc1') - assert len(gc.get_objects()) == 1 - assert gc.get_objects()[0] == event + assert event in gc.get_objects() event = None diff --git a/tests/event/test_futures.py b/tests/event/test_futures.py index a996f32eef..c1bf870c1c 100644 --- a/tests/event/test_futures.py +++ b/tests/event/test_futures.py @@ -705,3 +705,32 @@ def test_task_manager_cleanup_non_panda_future(): del coro_main # this should break the last strong reference to the mock future assert future_ref() is None, "MockFuture was not cleaned up!" + +def test_await_future_result_cleanup(): + # Create a simple future and an object for it to return + future = core.AsyncFuture() + + class TestObject: + pass + + test_result = TestObject() + future_result_ref = weakref.ref(test_result) + + # Setup an async environment and dispatch it to a task chain to await the future + async def coro_main(): + nonlocal test_result + future.set_result(test_result) + del test_result + await future + + task = core.PythonTask(coro_main(), 'coro_main') + task_mgr = core.AsyncTaskManager.get_global_ptr() + task_mgr.add(task) + # Poll the task_mgr so the PythonTask starts polling on future.done() + task_mgr.poll() + # Break all possible references to the future object + del task + del coro_main + del future # this should break the last strong reference to the future + + assert future_result_ref() is None, "TestObject was not cleaned up!" diff --git a/tests/event/test_pythontask.py b/tests/event/test_pythontask.py index 584788494f..c793067f8b 100644 --- a/tests/event/test_pythontask.py +++ b/tests/event/test_pythontask.py @@ -1,4 +1,4 @@ -from panda3d.core import PythonTask +from panda3d.core import AsyncTaskManager, PythonTask from contextlib import contextmanager import pytest import types @@ -115,3 +115,39 @@ def test_pythontask_cycle(): break else: pytest.fail('not found in garbage') + +def test_task_persistent_wrapper(): + task_mgr = AsyncTaskManager.get_global_ptr() + task_chain = task_mgr.make_task_chain("test_task_persistent_wrapper") + + # Create a subclass of PythonTask + class PythonTaskSubclassTest(PythonTask): + pass + + def task_main(task): + # Set our result to be the input task we got into this function + task.set_result(task) + # Verify we got the subclass + assert isinstance(task, PythonTaskSubclassTest) + return task.done + + done_callback_reached = False + + def done_callback(task): + # Verify we got the subclass + assert isinstance(task, PythonTaskSubclassTest) + nonlocal done_callback_reached + done_callback_reached = True + + task = PythonTaskSubclassTest(task_main) + task.set_task_chain(task_chain.name) + task.set_upon_death(done_callback) + task_mgr.add(task) + task_chain.wait_for_tasks() + + assert task.done() + assert not task.cancelled() + # Verify the task passed into the function is the same task we created + assert task.result() is task + # Verify the done callback worked and was tested + assert done_callback_reached diff --git a/tests/gui/test_DirectGui.py b/tests/gui/test_DirectGui.py index f72419a5c3..50b6122fda 100644 --- a/tests/gui/test_DirectGui.py +++ b/tests/gui/test_DirectGui.py @@ -8,7 +8,7 @@ from direct.gui.DirectGui import DirectButton, DirectDialog, DirectEntry, Direct def test_DirectGui(base): # EXAMPLE CODE # Load a model - smiley = base.loader.loadModel('models/misc/smiley') + smiley = base.loader.loadModel('models/misc/smiley.egg') # Here we specify the button's command def dummyCmd(index): diff --git a/tests/interrogate/test_property.py b/tests/interrogate/test_property.py index 12da75f457..7a708b2ab6 100644 --- a/tests/interrogate/test_property.py +++ b/tests/interrogate/test_property.py @@ -609,3 +609,9 @@ def test_map_property_items(): assert isinstance(prop.items(), collections_abc.MappingView) assert frozenset(prop.items()) == frozenset((('key', 'value'), ('key2', 'value2'))) + + +def test_static_property(): + v1 = core.PandaSystem.version_string + v2 = core.PandaSystem.get_version_string() + assert v1 == v2 diff --git a/tests/linmath/test_compose_matrix.py b/tests/linmath/test_compose_matrix.py new file mode 100644 index 0000000000..82497cb67d --- /dev/null +++ b/tests/linmath/test_compose_matrix.py @@ -0,0 +1,26 @@ +from panda3d import core +import pytest + + +@pytest.mark.parametrize("coordsys", (core.CS_zup_right, core.CS_yup_right, core.CS_zup_left, core.CS_yup_left)) +def test_compose_matrix(coordsys): + scale = core.LVecBase3(1.2, 0.5, 2) + hpr = core.LVecBase3(45, -90, 12.5) + shear = core.LVecBase3(0, 0, 0) + + mat = core.LMatrix3() + core.compose_matrix(mat, scale, shear, hpr, coordsys) + + new_scale = core.LVecBase3() + new_hpr = core.LVecBase3() + new_shear = core.LVecBase3() + core.decompose_matrix(mat, new_scale, new_shear, new_hpr, coordsys) + + assert new_scale.almost_equal(scale) + assert new_shear.almost_equal(shear) + + quat = core.LQuaternion() + quat.set_hpr(hpr, coordsys) + new_quat = core.LQuaternion() + new_quat.set_hpr(new_hpr, coordsys) + assert quat.is_same_direction(new_quat) diff --git a/tests/main.c b/tests/main.c new file mode 100644 index 0000000000..acf26dd10e --- /dev/null +++ b/tests/main.c @@ -0,0 +1,164 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file main.c + * @author rdb + * @date 2024-11-03 + */ + +/** + * This script embeds the Python interpreter and runs the unit testing suite. + * It is designed for use with a statically built Panda3D, where the Panda3D + * modules are linked directly into the interpreter. + */ + +#include + +#ifdef __EMSCRIPTEN__ +#include +#include +#endif + +#include "pandabase.h" + +#ifdef LINK_ALL_STATIC +extern PyObject *PyInit_core(); + +#ifdef HAVE_DIRECT +extern PyObject *PyInit_direct(); +#endif + +#ifdef HAVE_PHYSICS +extern PyObject *PyInit_physics(); +#endif + +#ifdef HAVE_EGG +extern PyObject *PyInit_egg(); +extern EXPCL_PANDAEGG void init_libpandaegg(); +#endif + +#ifdef HAVE_BULLET +extern PyObject *PyInit_bullet(); +#endif + +extern EXPCL_PANDA_PNMIMAGETYPES void init_libpnmimagetypes(); +#endif // LINK_ALL_STATIC + + +int main(int argc, char **argv) { + PyStatus status; + PyConfig config; + PyConfig_InitPythonConfig(&config); + +#ifdef __EMSCRIPTEN__ + // getenv does not work with emscripten, instead read the PYTHONPATH and + // PYTHONHOME from the process.env variable if we're running in node.js. + char path[4096], home[4096]; + path[0] = 0; + home[0] = 0; + + EM_ASM({ + if (typeof process === 'object' && typeof process.env === 'object') { + var path = process.env.PYTHONPATH; + var home = process.env.PYTHONHOME; + if (path) { + if (process.platform === 'win32') { + path = path.replace(/;/g, ':'); + } + stringToUTF8(path, $0, $1); + } + if (home) { + stringToUTF8(home, $2, $3); + } + } + }, path, sizeof(path), home, sizeof(home)); + + if (path[0] != 0) { + status = PyConfig_SetBytesString(&config, &config.pythonpath_env, path); + if (PyStatus_Exception(status)) { + goto exception; + } + } + if (home[0] != 0) { + status = PyConfig_SetBytesString(&config, &config.home, home); + if (PyStatus_Exception(status)) { + goto exception; + } + } +#endif + + PyConfig_SetBytesString(&config, &config.run_module, "pytest"); + config.parse_argv = 0; + + status = PyConfig_SetBytesArgv(&config, argc, argv); + if (PyStatus_Exception(status)) { + goto exception; + } + + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + goto exception; + } + PyConfig_Clear(&config); + +#ifdef LINK_ALL_STATIC +#ifdef HAVE_EGG + init_libpandaegg(); +#endif + + init_libpnmimagetypes(); + + { + PyObject *panda3d_module = PyImport_ImportModule("panda3d"); + PyObject *panda3d_dict = PyModule_GetDict(panda3d_module); + PyObject *sys_modules = PySys_GetObject("modules"); + + PyObject *core_module = PyInit_core(); + PyDict_SetItemString(panda3d_dict, "core", core_module); + PyDict_SetItemString(sys_modules, "panda3d.core", core_module); + +#ifdef HAVE_DIRECT + PyObject *direct_module = PyInit_direct(); + PyDict_SetItemString(panda3d_dict, "direct", direct_module); + PyDict_SetItemString(sys_modules, "panda3d.direct", direct_module); +#endif + +#ifdef HAVE_PHYSICS + PyObject *physics_module = PyInit_physics(); + PyDict_SetItemString(panda3d_dict, "physics", physics_module); + PyDict_SetItemString(sys_modules, "panda3d.physics", physics_module); +#endif + +#ifdef HAVE_EGG + PyObject *egg_module = PyInit_egg(); + PyDict_SetItemString(panda3d_dict, "egg", egg_module); + PyDict_SetItemString(sys_modules, "panda3d.egg", egg_module); +#endif + +#ifdef HAVE_BULLET + PyObject *bullet_module = PyInit_bullet(); + PyDict_SetItemString(panda3d_dict, "bullet", bullet_module); + PyDict_SetItemString(sys_modules, "panda3d.bullet", bullet_module); +#endif + } +#endif // LINK_ALL_STATIC + +#ifdef __EMSCRIPTEN__ + // Default fd capturing doesn't work on emscripten + PyRun_SimpleString("import sys; sys.argv.insert(1, '--capture=sys')"); +#endif + + return Py_RunMain(); + +exception: + PyConfig_Clear(&config); + if (PyStatus_IsExit(status)) { + return status.exitcode; + } + Py_ExitStatusException(status); +} diff --git a/tests/pgraph/test_nodepath.py b/tests/pgraph/test_nodepath.py index 9339394724..ef9d44ab33 100644 --- a/tests/pgraph/test_nodepath.py +++ b/tests/pgraph/test_nodepath.py @@ -106,7 +106,7 @@ def test_nodepath_transform_composition(): leg1 = node2.get_transform().compose(node3.get_transform()) leg2 = node1.get_transform().compose(node3.get_transform()) relative_transform = leg1.get_inverse().compose(leg2) - assert np1.get_transform(np2) == relative_transform + assert np1.get_transform(np2).compare_to(relative_transform, True) == 0 def test_nodepath_comparison(): diff --git a/tests/pgraph/test_pandanode.py b/tests/pgraph/test_pandanode.py index 9870b4d3c6..2b24168b1e 100644 --- a/tests/pgraph/test_pandanode.py +++ b/tests/pgraph/test_pandanode.py @@ -144,8 +144,7 @@ def test_node_subclass_gc(): with gc_disabled(): node = NodeSubclass('test_node_subclass_gc1') - assert len(gc.get_objects()) == 1 - assert gc.get_objects()[0] == node + assert node in gc.get_objects() node = None diff --git a/tests/physics/test_fall.py b/tests/physics/test_fall.py index 99397072a8..1b261e8628 100644 --- a/tests/physics/test_fall.py +++ b/tests/physics/test_fall.py @@ -23,7 +23,7 @@ class FallTest(NodePath): #self.setPos(avatarNodePath, Vec3(0)) #self.setHpr(avatarNodePath, Vec3(0)) - avatarNodePath = base.loader.loadModel("models/misc/smiley") + avatarNodePath = base.loader.loadModel("models/misc/smiley.egg") assert not avatarNodePath.isEmpty() # camLL = base.render.find("**/camLL") diff --git a/tests/physics/test_rotation.py b/tests/physics/test_rotation.py index ec24cf433b..1260651cd2 100644 --- a/tests/physics/test_rotation.py +++ b/tests/physics/test_rotation.py @@ -24,7 +24,7 @@ class RotationTest(NodePath): #self.setPos(avatarNodePath, Vec3(0)) #self.setHpr(avatarNodePath, Vec3(0)) - avatarNodePath = base.loader.loadModel("models/misc/smiley") + avatarNodePath = base.loader.loadModel("models/misc/smiley.egg") assert not avatarNodePath.isEmpty() # camLL = base.render.find("**/camLL") diff --git a/tests/stdpy/test_threading.py b/tests/stdpy/test_threading.py index a105ad20e1..3a4363e810 100644 --- a/tests/stdpy/test_threading.py +++ b/tests/stdpy/test_threading.py @@ -9,6 +9,7 @@ def test_threading_error(): threading.stack_size() +@pytest.mark.skipif(sys.platform == "emscripten", reason="No threading") def test_threading(): from collections import deque diff --git a/tests/stdpy/test_threading2.py b/tests/stdpy/test_threading2.py index f2a31dc172..fd7560def9 100644 --- a/tests/stdpy/test_threading2.py +++ b/tests/stdpy/test_threading2.py @@ -1,8 +1,11 @@ +import sys from collections import deque from panda3d import core from direct.stdpy import threading2 +import pytest +@pytest.mark.skipif(sys.platform == "emscripten", reason="No threading") def test_threading2(): class BoundedQueue(threading2._Verbose): diff --git a/tests/test_imports.py b/tests/test_imports.py index c6295bc7d0..565ecca2b2 100644 --- a/tests/test_imports.py +++ b/tests/test_imports.py @@ -18,7 +18,7 @@ def test_imports_panda3d(): if mod.startswith('panda3d.'): importlib.import_module(mod) - if panda3d.__spec__.origin != 'frozen': + if hasattr(panda3d, '__file__') and panda3d.__spec__.origin != 'frozen': dir = os.path.dirname(panda3d.__file__) # Iterate over the things in the panda3d package that look like modules. @@ -32,12 +32,18 @@ def test_imports_panda3d(): module = basename.split('.', 1)[0] ext = basename[len(module):] + if module == 'dtoolconfig' or module == 'interrogatedb': + continue + if ext in extensions: importlib.import_module('panda3d.%s' % (module)) def test_imports_panda3d_net(): from panda3d import core + if not hasattr(core, 'ConnectionWriter'): + pytest.skip("Build without HAVE_NET") + from panda3d import net assert core.ConnectionWriter == net.ConnectionWriter assert core.ConnectionWriter.__module__ == 'panda3d.net' @@ -265,6 +271,7 @@ def test_imports_direct_net(): def test_imports_tk(): + pytest.importorskip('tkinter') Pmw = pytest.importorskip('Pmw') import direct.showbase.TkGlobal diff --git a/tests/test_tools.py b/tests/test_tools.py index b6b187ebc2..c4ac081d6a 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -5,6 +5,9 @@ import os import tempfile import panda3d +if sys.platform == "emscripten": + pytest.skip(allow_module_level=True) + try: panda3d_tools = pytest.importorskip("panda3d_tools") except: diff --git a/tests/tkpanels/test_ParticlePanel.py b/tests/tkpanels/test_ParticlePanel.py index e1498a4868..d80c0eac2f 100644 --- a/tests/tkpanels/test_ParticlePanel.py +++ b/tests/tkpanels/test_ParticlePanel.py @@ -1,4 +1,5 @@ import pytest +pytest.importorskip('tkinter') Pmw = pytest.importorskip('Pmw') from direct.tkpanels.ParticlePanel import ParticlePanel diff --git a/tests/tkpanels/test_Placer.py b/tests/tkpanels/test_Placer.py index 1cc146efeb..353afdf5a8 100644 --- a/tests/tkpanels/test_Placer.py +++ b/tests/tkpanels/test_Placer.py @@ -1,4 +1,5 @@ import pytest +pytest.importorskip('tkinter') Pmw = pytest.importorskip('Pmw') from direct.showbase.ShowBase import ShowBase from direct.tkpanels.Placer import Placer diff --git a/tests/tkwidgets/test_AppShell.py b/tests/tkwidgets/test_AppShell.py index e87889d34b..831407ed04 100644 --- a/tests/tkwidgets/test_AppShell.py +++ b/tests/tkwidgets/test_AppShell.py @@ -1,4 +1,5 @@ import pytest +pytest.importorskip('tkinter') pytest.importorskip('Pmw') from direct.tkwidgets import AppShell diff --git a/tests/tkwidgets/test_EntryScale.py b/tests/tkwidgets/test_EntryScale.py index f06fb036ed..496376328d 100644 --- a/tests/tkwidgets/test_EntryScale.py +++ b/tests/tkwidgets/test_EntryScale.py @@ -1,4 +1,5 @@ import pytest +pytest.importorskip('tkinter') pytest.importorskip('Pmw') from direct.tkwidgets.EntryScale import EntryScale, EntryScaleGroup diff --git a/tests/tkwidgets/test_Floater.py b/tests/tkwidgets/test_Floater.py index dfd470763f..45a3b0ae7d 100644 --- a/tests/tkwidgets/test_Floater.py +++ b/tests/tkwidgets/test_Floater.py @@ -1,4 +1,5 @@ import pytest +pytest.importorskip('tkinter') pytest.importorskip('Pmw') from direct.tkwidgets.Floater import Floater, FloaterGroup diff --git a/tests/tkwidgets/test_VectorWidgets.py b/tests/tkwidgets/test_VectorWidgets.py index fecad4cfa7..892701a149 100644 --- a/tests/tkwidgets/test_VectorWidgets.py +++ b/tests/tkwidgets/test_VectorWidgets.py @@ -1,4 +1,5 @@ import pytest +pytest.importorskip('tkinter') pytest.importorskip('Pmw') from direct.tkwidgets import VectorWidgets