Merge remote-tracking branch 'upstream/master'

This commit is contained in:
John Cote 2024-11-13 23:11:44 -05:00
commit c4f1842505
No known key found for this signature in database
GPG Key ID: 2CBB7FE216D556FB
260 changed files with 3149 additions and 14687 deletions

View File

@ -2,6 +2,7 @@
name: Bug report
about: Report a defect
title:
type: bug
labels:
assignees:
---

12
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -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.

View File

@ -2,6 +2,7 @@
name: Enhancement request
about: Request new functionality or improvement to existing functionality
title:
type: feature
labels: enhancement
assignees:
---

7
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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}")

View File

@ -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());

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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):

View File

@ -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()

View File

@ -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;

View File

@ -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,

View File

@ -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()`.

View File

@ -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

View File

@ -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] != '.':

View File

@ -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.

View File

@ -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

View File

@ -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 "$<$<OR:$<COMPILE_LANGUAGE:CXX>,$<COMPILE_LANGUAGE:OBJCXX>>:-frtti>")
set(cxx_rtti_off "$<$<OR:$<COMPILE_LANGUAGE:CXX>,$<COMPILE_LANGUAGE:OBJCXX>>:-fno-rtti>")
else()
set(cxx_rtti_on)

View File

@ -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

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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.

View File

@ -32,6 +32,8 @@ THE SOFTWARE.
#include <intrin.h>
#include <float.h>
#define copysign _copysign
#pragma float_control(precise, on, push)
#endif
#define UINT64_C2(h, l) ((static_cast<uint64_t>(h) << 32) | static_cast<uint64_t>(l))
@ -586,3 +588,7 @@ void pftoa(float value, char *buffer) {
}
}
}
#ifdef _MSC_VER
#pragma float_control(pop)
#endif

View File

@ -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();
}
}

View File

@ -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

View File

@ -21,6 +21,13 @@
#include <map>
#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"

View File

@ -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;

View File

@ -185,7 +185,7 @@ is_open() const {
*/
bool PipeStreamBuf::
eof_pipe() const {
return (_pipe == nullptr) && feof(_pipe);
return (_pipe == nullptr) || feof(_pipe);
}
/**

View File

@ -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)

View File

@ -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 <crtdbg.h>
#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.");

View File

@ -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

View File

@ -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

View File

@ -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<int, int>::const_iterator mi;
mi = _map_int.find(from);
if (mi == _map_int.end()) {
return from;
}
return (*mi).second;
}

View File

@ -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 <map>
/**
* 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<int, int> _map_int;
};
#endif

View File

@ -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 &copy) :
_def(copy._def),
_name(copy._name)
{
}
/**
*
*/
INLINE void InterrogateComponent::
operator = (const InterrogateComponent &copy) {
_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;
}

View File

@ -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);
}
}

View File

@ -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 <vector>
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 &copy);
INLINE void operator = (const InterrogateComponent &copy);
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<std::string> Strings;
Strings _alt_names;
friend class InterrogateBuilder;
friend class FunctionRemap;
};
#include "interrogateComponent.I"
#endif

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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 <map>
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<TypeIndex, InterrogateType> TypeMap;
TypeMap _type_map;
typedef std::map<FunctionIndex, InterrogateFunction *> FunctionMap;
FunctionMap _function_map;
typedef std::map<FunctionWrapperIndex, InterrogateFunctionWrapper> FunctionWrapperMap;
FunctionWrapperMap _wrapper_map;
typedef std::map<ManifestIndex, InterrogateManifest> ManifestMap;
ManifestMap _manifest_map;
typedef std::map<ElementIndex, InterrogateElement> ElementMap;
ElementMap _element_map;
typedef std::map<MakeSeqIndex, InterrogateMakeSeq> MakeSeqMap;
MakeSeqMap _make_seq_map;
typedef std::vector<TypeIndex> GlobalTypes;
GlobalTypes _global_types;
GlobalTypes _all_types;
typedef std::vector<FunctionIndex> GlobalFunctions;
GlobalFunctions _global_functions;
GlobalFunctions _all_functions;
typedef std::vector<ManifestIndex> GlobalManifests;
GlobalManifests _global_manifests;
typedef std::vector<ElementIndex> GlobalElements;
GlobalElements _global_elements;
// This data is compiled in directly to the shared libraries that we link
// with.
typedef std::vector<InterrogateModuleDef *> Modules;
Modules _modules;
typedef std::map<std::string, InterrogateModuleDef *> ModulesByHash;
ModulesByHash _modules_by_hash;
// This records the set of database files that are still to be loaded.
typedef std::vector<InterrogateModuleDef *> 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<std::string, int> 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

View File

@ -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 &copy) {
(*this) = copy;
}
/**
*
*/
INLINE void InterrogateElement::
operator = (const InterrogateElement &copy) {
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;
}

View File

@ -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);
}

View File

@ -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 &copy);
INLINE void operator = (const InterrogateElement &copy);
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

View File

@ -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;
}

View File

@ -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 &copy) {
(*this) = copy;
}
/**
*
*/
void InterrogateFunction::
operator = (const InterrogateFunction &copy) {
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);
}
}

View File

@ -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 <vector>
#include <map>
class IndexRemapper;
class CPPInstance;
/**
* An internal representation of a function.
*/
class EXPCL_INTERROGATEDB InterrogateFunction : public InterrogateComponent {
public:
InterrogateFunction(InterrogateModuleDef *def = nullptr);
InterrogateFunction(const InterrogateFunction &copy);
void operator = (const InterrogateFunction &copy);
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<FunctionWrapperIndex> 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<std::string, CPPInstance *> 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

View File

@ -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 &copy) {
(*this) = copy;
}
/**
*
*/
INLINE void InterrogateFunctionWrapper::
operator = (const InterrogateFunctionWrapper &copy) {
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;
}

View File

@ -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 <algorithm>
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);
}
}

View File

@ -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 <vector>
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 &copy);
INLINE void operator = (const InterrogateFunctionWrapper &copy);
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 &parameter_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<Parameter> 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

View File

@ -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 &copy) {
(*this) = copy;
}
/**
*
*/
INLINE void InterrogateMakeSeq::
operator = (const InterrogateMakeSeq &copy) {
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;
}

View File

@ -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);
}

View File

@ -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 &copy);
INLINE void operator = (const InterrogateMakeSeq &copy);
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

View File

@ -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 &copy) {
(*this) = copy;
}
/**
*
*/
INLINE void InterrogateManifest::
operator = (const InterrogateManifest &copy) {
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;
}

View File

@ -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);
}

View File

@ -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 &copy);
INLINE void operator = (const InterrogateManifest &copy);
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

View File

@ -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;
}

View File

@ -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 <algorithm>
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 &copy) {
(*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 &copy) {
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);
}
}

View File

@ -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 <vector>
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 &copy);
void operator = (const InterrogateType &copy);
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<FunctionIndex> Functions;
Functions _constructors;
FunctionIndex _destructor;
typedef std::vector<ElementIndex> Elements;
Elements _elements;
Functions _methods;
Functions _casts;
typedef std::vector<MakeSeqIndex> 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<Derivation> 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<EnumValue> EnumValues;
EnumValues _enum_values;
typedef std::vector<TypeIndex> 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

View File

@ -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<class Element>
void
idf_output_vector(std::ostream &out, const std::vector<Element> &vec) {
out << vec.size() << " ";
typename std::vector<Element>::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<class Element>
void
idf_input_vector(std::istream &in, std::vector<Element> &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--;
}
}

View File

@ -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;
}

View File

@ -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 <vector>
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<class Element>
void idf_output_vector(std::ostream &out, const std::vector<Element> &vec);
template<class Element>
void idf_input_vector(std::istream &in, std::vector<Element> &vec);
#include "interrogate_datafile.I"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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 <string.h> // 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);
}

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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: <list of overloads>
*
* 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

View File

@ -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<std::string, Dtool_PyTypedObject *> {
public:
PyMutex _lock { 0 };
};
#else
typedef std::map<std::string, Dtool_PyTypedObject *> 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

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,11 @@ namespace std {
constexpr const T &min(const T &a, const T &b);
template<class T>
constexpr const T &max(const T &a, const T &b);
template<class RandomIt>
void sort(RandomIt first, RandomIt last);
template<class RandomIt, class Compare>
void sort(RandomIt first, RandomIt last, Compare comp);
}
#endif

View File

@ -0,0 +1,9 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <emscripten/emscripten.h>
#define WASM_PAGE_SIZE 65536
#define EMSCRIPTEN_PAGE_SIZE WASM_PAGE_SIZE

View File

@ -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)

View File

@ -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")

View File

@ -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])

View File

@ -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)

View File

@ -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):

View File

@ -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')

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -29,6 +29,7 @@
#else
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alext.h>
#endif
class OpenALAudioSound;

View File

@ -27,6 +27,7 @@
#else
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alext.h>
#endif
class EXPCL_OPENAL_AUDIO OpenALAudioSound final : public AudioSound {

View File

@ -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);
}
/**

View File

@ -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;

View File

@ -32,7 +32,6 @@
#import "cocoaPandaAppDelegate.h"
#import <ApplicationServices/ApplicationServices.h>
#import <Foundation/NSAutoreleasePool.h>
#import <AppKit/NSApplication.h>
#import <AppKit/NSCursor.h>
#import <AppKit/NSEvent.h>
@ -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()];

View File

@ -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];

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