OpenGLContext 3.0.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- OpenGLContext/__init__.py +151 -0
- OpenGLContext/arrays.py +2 -0
- OpenGLContext/atlas.py +300 -0
- OpenGLContext/audio/__init__.py +32 -0
- OpenGLContext/audio/scene.py +130 -0
- OpenGLContext/audio/settings.py +82 -0
- OpenGLContext/bin/__init__.py +0 -0
- OpenGLContext/bin/choosecontext.py +224 -0
- OpenGLContext/bin/choosefonts.py +209 -0
- OpenGLContext/bin/gltest.py +121 -0
- OpenGLContext/bin/gltf_demo.py +492 -0
- OpenGLContext/bin/gltf_regression.py +645 -0
- OpenGLContext/bin/gltf_view.py +30 -0
- OpenGLContext/bin/keyboardevents.py +93 -0
- OpenGLContext/bin/lorentz.py +109 -0
- OpenGLContext/bin/physics_cook.py +81 -0
- OpenGLContext/bin/profile_view.py +38 -0
- OpenGLContext/bin/terrain_view.py +581 -0
- OpenGLContext/bin/tiles_view.py +39 -0
- OpenGLContext/bin/ui_demo.py +228 -0
- OpenGLContext/bin/view.py +341 -0
- OpenGLContext/bin/vrml_view.py +42 -0
- OpenGLContext/capture.py +125 -0
- OpenGLContext/context.py +1253 -0
- OpenGLContext/contextconfig.py +177 -0
- OpenGLContext/contextdefinition.py +275 -0
- OpenGLContext/debug/__init__.py +6 -0
- OpenGLContext/debug/bufferimage.py +80 -0
- OpenGLContext/debug/leaks.py +13 -0
- OpenGLContext/debug/logcontext.py +9 -0
- OpenGLContext/debug/logs.py +15 -0
- OpenGLContext/debug/state.py +329 -0
- OpenGLContext/displaylist.py +69 -0
- OpenGLContext/doinchildmatrix.py +34 -0
- OpenGLContext/drawcube.py +58 -0
- OpenGLContext/events/__init__.py +10 -0
- OpenGLContext/events/default_config.py +29 -0
- OpenGLContext/events/event.py +65 -0
- OpenGLContext/events/eventhandlermixin.py +214 -0
- OpenGLContext/events/eventmanager.py +269 -0
- OpenGLContext/events/fxevents.py +90 -0
- OpenGLContext/events/glfwevents.py +424 -0
- OpenGLContext/events/glutevents.py +184 -0
- OpenGLContext/events/inputstate.py +129 -0
- OpenGLContext/events/internaltime.py +161 -0
- OpenGLContext/events/keyboardevents.py +153 -0
- OpenGLContext/events/mouseevents.py +473 -0
- OpenGLContext/events/pygameevents.py +162 -0
- OpenGLContext/events/systemtime.py +12 -0
- OpenGLContext/events/timeeventgeneratormanager.py +40 -0
- OpenGLContext/events/timeevents.py +143 -0
- OpenGLContext/events/timer.py +170 -0
- OpenGLContext/events/tkevents.py +172 -0
- OpenGLContext/events/wxevents.py +185 -0
- OpenGLContext/extensionmanager.py +158 -0
- OpenGLContext/framecounter.py +74 -0
- OpenGLContext/frustum.py +135 -0
- OpenGLContext/glfwcontext.py +395 -0
- OpenGLContext/glfwinteractivecontext.py +34 -0
- OpenGLContext/glfwvrmlcontext.py +11 -0
- OpenGLContext/glutcontext.py +224 -0
- OpenGLContext/glutinteractivecontext.py +24 -0
- OpenGLContext/gluttestingcontext.py +11 -0
- OpenGLContext/glutvrmlcontext.py +25 -0
- OpenGLContext/glutvrmltestingcontext.py +48 -0
- OpenGLContext/hud.py +404 -0
- OpenGLContext/interactivecontext.py +29 -0
- OpenGLContext/loaders/__init__.py +1 -0
- OpenGLContext/loaders/base.py +84 -0
- OpenGLContext/loaders/cc0.py +137 -0
- OpenGLContext/loaders/gltf/__init__.py +71 -0
- OpenGLContext/loaders/gltf/accessors.py +255 -0
- OpenGLContext/loaders/gltf/animation.py +611 -0
- OpenGLContext/loaders/gltf/draco.py +166 -0
- OpenGLContext/loaders/gltf/environment_sky.py +416 -0
- OpenGLContext/loaders/gltf/loader.py +80 -0
- OpenGLContext/loaders/gltf/materials.py +298 -0
- OpenGLContext/loaders/gltf/meshes.py +292 -0
- OpenGLContext/loaders/gltf/samples.py +162 -0
- OpenGLContext/loaders/gltf/scene.py +673 -0
- OpenGLContext/loaders/gltf/specular_glossiness.py +154 -0
- OpenGLContext/loaders/gltf/textures.py +155 -0
- OpenGLContext/loaders/gltf/transforms.py +261 -0
- OpenGLContext/loaders/gltf_demos.py +511 -0
- OpenGLContext/loaders/hdr.py +228 -0
- OpenGLContext/loaders/hdri.py +83 -0
- OpenGLContext/loaders/loader.py +255 -0
- OpenGLContext/loaders/obj.py +299 -0
- OpenGLContext/loaders/resolver.py +536 -0
- OpenGLContext/loaders/tiles3d/__init__.py +9 -0
- OpenGLContext/loaders/tiles3d/boundingvolume.py +120 -0
- OpenGLContext/loaders/tiles3d/dem.py +71 -0
- OpenGLContext/loaders/tiles3d/fetch.py +102 -0
- OpenGLContext/loaders/tiles3d/foliage.py +786 -0
- OpenGLContext/loaders/tiles3d/frustum.py +70 -0
- OpenGLContext/loaders/tiles3d/geomorph.py +57 -0
- OpenGLContext/loaders/tiles3d/gltf_uploader.py +246 -0
- OpenGLContext/loaders/tiles3d/loadmanager.py +121 -0
- OpenGLContext/loaders/tiles3d/physics_colliders.py +78 -0
- OpenGLContext/loaders/tiles3d/procedural.py +355 -0
- OpenGLContext/loaders/tiles3d/residency.py +102 -0
- OpenGLContext/loaders/tiles3d/runtime.py +168 -0
- OpenGLContext/loaders/tiles3d/sample.py +212 -0
- OpenGLContext/loaders/tiles3d/scatter.py +77 -0
- OpenGLContext/loaders/tiles3d/screenspaceerror.py +31 -0
- OpenGLContext/loaders/tiles3d/tileset.py +390 -0
- OpenGLContext/loaders/tiles3d/traversal.py +108 -0
- OpenGLContext/loaders/tiles3d/vegetation.py +361 -0
- OpenGLContext/loaders/vrml97.py +133 -0
- OpenGLContext/looptrace.py +307 -0
- OpenGLContext/move/__init__.py +0 -0
- OpenGLContext/move/bindingstore.py +232 -0
- OpenGLContext/move/direct.py +156 -0
- OpenGLContext/move/dragwatcher.py +42 -0
- OpenGLContext/move/examinemanager.py +100 -0
- OpenGLContext/move/followcam.py +121 -0
- OpenGLContext/move/modes.py +522 -0
- OpenGLContext/move/movementmanager.py +74 -0
- OpenGLContext/move/navigation.py +137 -0
- OpenGLContext/move/physicsplatform.py +203 -0
- OpenGLContext/move/physicswalk.py +469 -0
- OpenGLContext/move/smooth.py +68 -0
- OpenGLContext/move/terrainwalk.py +451 -0
- OpenGLContext/move/trackball.py +92 -0
- OpenGLContext/move/viewplatform.py +283 -0
- OpenGLContext/move/viewplatformmixin.py +335 -0
- OpenGLContext/nav/__init__.py +13 -0
- OpenGLContext/nav/navmesh.py +476 -0
- OpenGLContext/passes/__init__.py +0 -0
- OpenGLContext/passes/_flat.py +1317 -0
- OpenGLContext/passes/asyncpick.py +216 -0
- OpenGLContext/passes/bloom.py +257 -0
- OpenGLContext/passes/flatcompat.py +246 -0
- OpenGLContext/passes/flatcore.py +198 -0
- OpenGLContext/passes/flateffects.py +372 -0
- OpenGLContext/passes/ibl.py +711 -0
- OpenGLContext/passes/instancing.py +775 -0
- OpenGLContext/passes/pbrpass.py +829 -0
- OpenGLContext/passes/renderpass.py +79 -0
- OpenGLContext/passes/renderstats.py +55 -0
- OpenGLContext/passes/rendervisitor.py +60 -0
- OpenGLContext/passes/selection.py +450 -0
- OpenGLContext/passes/selectionbuffers.py +442 -0
- OpenGLContext/passes/shaderpass.py +1018 -0
- OpenGLContext/passes/shaderpass_shadow.py +197 -0
- OpenGLContext/passes/shadersource.py +121 -0
- OpenGLContext/passes/shadowcaps.py +182 -0
- OpenGLContext/passes/shadowmap.py +330 -0
- OpenGLContext/passes/shadowmath.py +290 -0
- OpenGLContext/passes/shadowmixin.py +906 -0
- OpenGLContext/passes/shadowpool.py +186 -0
- OpenGLContext/passes/transmission.py +124 -0
- OpenGLContext/physics/__init__.py +16 -0
- OpenGLContext/physics/debugdraw.py +370 -0
- OpenGLContext/physics/demo.py +157 -0
- OpenGLContext/physics/gltf_world.py +185 -0
- OpenGLContext/physics/manager.py +84 -0
- OpenGLContext/physics/threaded.py +93 -0
- OpenGLContext/plugins.py +61 -0
- OpenGLContext/pygamecontext.py +178 -0
- OpenGLContext/pygameinteractivecontext.py +36 -0
- OpenGLContext/pygametestingcontext.py +10 -0
- OpenGLContext/pygamevrmlcontext.py +13 -0
- OpenGLContext/quaternion.py +190 -0
- OpenGLContext/renderoptions.py +280 -0
- OpenGLContext/resources/__init__.py +36 -0
- OpenGLContext/resources/available_contexts.txt +4 -0
- OpenGLContext/resources/available_contexts_txt.py +9 -0
- OpenGLContext/resources/context_icon_png.py +46 -0
- OpenGLContext/resources/context_icon_small_png.py +21 -0
- OpenGLContext/resources/disk_icon_hi_png.py +14 -0
- OpenGLContext/resources/disk_icon_png.py +15 -0
- OpenGLContext/resources/environment/pimbackground_BK.jpg +0 -0
- OpenGLContext/resources/environment/pimbackground_DN.jpg +0 -0
- OpenGLContext/resources/environment/pimbackground_FR.jpg +0 -0
- OpenGLContext/resources/environment/pimbackground_LF.jpg +0 -0
- OpenGLContext/resources/environment/pimbackground_RT.jpg +0 -0
- OpenGLContext/resources/environment/pimbackground_UP.jpg +0 -0
- OpenGLContext/resources/environment/studio_BK.jpg +0 -0
- OpenGLContext/resources/environment/studio_DN.jpg +0 -0
- OpenGLContext/resources/environment/studio_FR.jpg +0 -0
- OpenGLContext/resources/environment/studio_LF.jpg +0 -0
- OpenGLContext/resources/environment/studio_RT.jpg +0 -0
- OpenGLContext/resources/environment/studio_UP.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_BK.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_DN.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_FR.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_LF.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_RT.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_UP.jpg +0 -0
- OpenGLContext/resources/green_arrow_right_png.py +47 -0
- OpenGLContext/resources/legacy_lighting.vert.txt +37 -0
- OpenGLContext/resources/legacy_lighting_vert_txt.py +18 -0
- OpenGLContext/resources/lights.vert.txt +107 -0
- OpenGLContext/resources/lights_vert_txt.py +23 -0
- OpenGLContext/resources/phongprecalc_vert.py +30 -0
- OpenGLContext/resources/phongweights_frag.py +47 -0
- OpenGLContext/resources/pygame_icon_png.py +47 -0
- OpenGLContext/resources/red_arrow_right_png.py +50 -0
- OpenGLContext/resources/simpleshader.frag.txt +3 -0
- OpenGLContext/resources/simpleshader.vert.txt +3 -0
- OpenGLContext/resources/simpleshader_frag_txt.py +9 -0
- OpenGLContext/resources/simpleshader_vert_txt.py +10 -0
- OpenGLContext/scenegraph/__init__.py +19 -0
- OpenGLContext/scenegraph/appearance.py +107 -0
- OpenGLContext/scenegraph/arraygeometry.py +238 -0
- OpenGLContext/scenegraph/audio.py +632 -0
- OpenGLContext/scenegraph/background.py +108 -0
- OpenGLContext/scenegraph/basenodes.py +50 -0
- OpenGLContext/scenegraph/billboard.py +14 -0
- OpenGLContext/scenegraph/boundingvolume.py +494 -0
- OpenGLContext/scenegraph/box.py +180 -0
- OpenGLContext/scenegraph/collision.py +14 -0
- OpenGLContext/scenegraph/coordinate.py +20 -0
- OpenGLContext/scenegraph/coordinatebounded.py +18 -0
- OpenGLContext/scenegraph/cubebackground.py +207 -0
- OpenGLContext/scenegraph/extrusions.py +275 -0
- OpenGLContext/scenegraph/fog.py +123 -0
- OpenGLContext/scenegraph/gear.py +323 -0
- OpenGLContext/scenegraph/group.py +20 -0
- OpenGLContext/scenegraph/grouping.py +140 -0
- OpenGLContext/scenegraph/hdrbackground.py +384 -0
- OpenGLContext/scenegraph/ifscompiler.py +633 -0
- OpenGLContext/scenegraph/imagetexture.py +365 -0
- OpenGLContext/scenegraph/indexedfaceset.py +238 -0
- OpenGLContext/scenegraph/indexedlineset.py +418 -0
- OpenGLContext/scenegraph/indexedpolygons.py +422 -0
- OpenGLContext/scenegraph/inline.py +79 -0
- OpenGLContext/scenegraph/instancedgl.py +187 -0
- OpenGLContext/scenegraph/interpolators.py +122 -0
- OpenGLContext/scenegraph/light.py +213 -0
- OpenGLContext/scenegraph/lod.py +22 -0
- OpenGLContext/scenegraph/material.py +96 -0
- OpenGLContext/scenegraph/material_fields.py +50 -0
- OpenGLContext/scenegraph/mouseover.py +43 -0
- OpenGLContext/scenegraph/nodepath.py +52 -0
- OpenGLContext/scenegraph/nurbs.py +637 -0
- OpenGLContext/scenegraph/nurbssampling.py +101 -0
- OpenGLContext/scenegraph/nurbstess.py +316 -0
- OpenGLContext/scenegraph/nurbstrim.py +54 -0
- OpenGLContext/scenegraph/particles.py +786 -0
- OpenGLContext/scenegraph/pbrmaterial.py +229 -0
- OpenGLContext/scenegraph/pbrmesh.py +558 -0
- OpenGLContext/scenegraph/physicsbody.py +72 -0
- OpenGLContext/scenegraph/pointset.py +257 -0
- OpenGLContext/scenegraph/polygon.py +166 -0
- OpenGLContext/scenegraph/polygonsort.py +119 -0
- OpenGLContext/scenegraph/polygontessellator.py +213 -0
- OpenGLContext/scenegraph/quadrics.py +494 -0
- OpenGLContext/scenegraph/scenegraph.py +21 -0
- OpenGLContext/scenegraph/shadergeometry.py +403 -0
- OpenGLContext/scenegraph/shaders.py +812 -0
- OpenGLContext/scenegraph/shape.py +243 -0
- OpenGLContext/scenegraph/simplebackground.py +34 -0
- OpenGLContext/scenegraph/spherebackground.py +462 -0
- OpenGLContext/scenegraph/switch.py +75 -0
- OpenGLContext/scenegraph/teapot.py +439 -0
- OpenGLContext/scenegraph/teapot_nurbs.py +291 -0
- OpenGLContext/scenegraph/teapot_nurbs_data.py +384 -0
- OpenGLContext/scenegraph/terrain/__init__.py +12 -0
- OpenGLContext/scenegraph/terrain/heightfield.py +172 -0
- OpenGLContext/scenegraph/terrain/splat.py +224 -0
- OpenGLContext/scenegraph/tessellationlod.py +97 -0
- OpenGLContext/scenegraph/text/__init__.py +1 -0
- OpenGLContext/scenegraph/text/_toolsfont.py +200 -0
- OpenGLContext/scenegraph/text/font.py +452 -0
- OpenGLContext/scenegraph/text/fontprovider.py +193 -0
- OpenGLContext/scenegraph/text/fonts/__init__.py +75 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_10.py +133 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_12.py +158 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_14.py +176 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_16.py +204 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_18.py +222 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_20.py +244 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_24.py +294 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_28.py +339 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_32.py +390 -0
- OpenGLContext/scenegraph/text/fontstyle3d.py +62 -0
- OpenGLContext/scenegraph/text/glutfont.py +186 -0
- OpenGLContext/scenegraph/text/pygamefont.py +213 -0
- OpenGLContext/scenegraph/text/shaderfont.py +340 -0
- OpenGLContext/scenegraph/text/shadertext.py +433 -0
- OpenGLContext/scenegraph/text/text.py +75 -0
- OpenGLContext/scenegraph/text/toolsfont.py +819 -0
- OpenGLContext/scenegraph/text/ttfregistry.py +135 -0
- OpenGLContext/scenegraph/text/wglfont.py +228 -0
- OpenGLContext/scenegraph/text/wglfontprovider.py +37 -0
- OpenGLContext/scenegraph/text/wxfont.py +314 -0
- OpenGLContext/scenegraph/texturetransform.py +66 -0
- OpenGLContext/scenegraph/tilesterrain.py +95 -0
- OpenGLContext/scenegraph/timesensor.py +51 -0
- OpenGLContext/scenegraph/transform.py +180 -0
- OpenGLContext/scenegraph/vegetation/__init__.py +20 -0
- OpenGLContext/scenegraph/vegetation/base.py +96 -0
- OpenGLContext/scenegraph/vegetation/billboards.py +145 -0
- OpenGLContext/scenegraph/vegetation/clumps.py +260 -0
- OpenGLContext/scenegraph/vegetation/grid.py +112 -0
- OpenGLContext/scenegraph/vegetation/nearmesh.py +185 -0
- OpenGLContext/scenegraph/vertex.py +54 -0
- OpenGLContext/scenegraph/viewpoint.py +42 -0
- OpenGLContext/scenegraph/winding.py +49 -0
- OpenGLContext/shaders/_brdf_inc.glsl +124 -0
- OpenGLContext/shaders/_common_inc.glsl +24 -0
- OpenGLContext/shaders/_cubemap_inc.glsl +26 -0
- OpenGLContext/shaders/_lights_inc.glsl +32 -0
- OpenGLContext/shaders/_objectid_inc.glsl +14 -0
- OpenGLContext/shaders/_shadow_inc.glsl +254 -0
- OpenGLContext/shaders/_vrml97_lighting_inc.glsl +78 -0
- OpenGLContext/shaders/hdr_background.frag +32 -0
- OpenGLContext/shaders/hdr_background.vert +15 -0
- OpenGLContext/shaders/ibl_brdf.frag +78 -0
- OpenGLContext/shaders/ibl_env.frag +53 -0
- OpenGLContext/shaders/ibl_equirect.frag +19 -0
- OpenGLContext/shaders/ibl_fullscreen.vert +11 -0
- OpenGLContext/shaders/ibl_irradiance.frag +40 -0
- OpenGLContext/shaders/ibl_prefilter.frag +56 -0
- OpenGLContext/shaders/particle.frag +42 -0
- OpenGLContext/shaders/particle.vert +52 -0
- OpenGLContext/shaders/pbr.frag +906 -0
- OpenGLContext/shaders/pbr.vert +70 -0
- OpenGLContext/shaders/shadow_depth.frag +4 -0
- OpenGLContext/shaders/shadow_depth.vert +18 -0
- OpenGLContext/shaders/terrain_splat.frag +80 -0
- OpenGLContext/shaders/terrain_splat.vert +16 -0
- OpenGLContext/shaders/veg_billboard.frag +35 -0
- OpenGLContext/shaders/veg_billboard.vert +17 -0
- OpenGLContext/shaders/veg_clump.frag +27 -0
- OpenGLContext/shaders/veg_mesh.frag +26 -0
- OpenGLContext/shaders/veg_mesh.vert +17 -0
- OpenGLContext/shaders/vrml97_background.frag +17 -0
- OpenGLContext/shaders/vrml97_background.vert +24 -0
- OpenGLContext/shaders/vrml97_lighting.frag +111 -0
- OpenGLContext/shaders/vrml97_lighting.vert +50 -0
- OpenGLContext/shaders/vrml97_line.frag +23 -0
- OpenGLContext/shaders/vrml97_line.vert +24 -0
- OpenGLContext/shaders/vrml97_point.frag +36 -0
- OpenGLContext/shaders/vrml97_point.vert +21 -0
- OpenGLContext/shaders/vrml97_unlit.frag +59 -0
- OpenGLContext/shaders/vrml97_unlit.vert +18 -0
- OpenGLContext/shaders/vrml97_vertex_color.frag +85 -0
- OpenGLContext/shaders/vrml97_vertex_color.vert +34 -0
- OpenGLContext/stalltrace.py +637 -0
- OpenGLContext/testing/__init__.py +67 -0
- OpenGLContext/testing/display.py +30 -0
- OpenGLContext/testing/event_injector.py +564 -0
- OpenGLContext/testing/framebuffer_comparison.py +842 -0
- OpenGLContext/testing/gl_env.py +39 -0
- OpenGLContext/testing/paths.py +23 -0
- OpenGLContext/testing/process_exit.py +30 -0
- OpenGLContext/testing/report_generator.py +594 -0
- OpenGLContext/testing/subprocess_runner.py +411 -0
- OpenGLContext/testingcontext.py +36 -0
- OpenGLContext/tests/test_atlas.py +62 -0
- OpenGLContext/tests/test_configs.py +27 -0
- OpenGLContext/tests/test_polygonsort.py +45 -0
- OpenGLContext/tests/test_utilities.py +84 -0
- OpenGLContext/tests/test_viewplatform.py +39 -0
- OpenGLContext/texture.py +449 -0
- OpenGLContext/texturecache.py +37 -0
- OpenGLContext/triangleutilities.py +89 -0
- OpenGLContext/ui/__init__.py +39 -0
- OpenGLContext/ui/bindings.py +243 -0
- OpenGLContext/ui/console.py +339 -0
- OpenGLContext/ui/debugoverlay.py +519 -0
- OpenGLContext/ui/dialogs.py +124 -0
- OpenGLContext/ui/draw.py +617 -0
- OpenGLContext/ui/gallery.py +425 -0
- OpenGLContext/ui/generate.py +195 -0
- OpenGLContext/ui/geometry.py +88 -0
- OpenGLContext/ui/hudwidgets.py +1053 -0
- OpenGLContext/ui/layout.py +263 -0
- OpenGLContext/ui/metrics.py +218 -0
- OpenGLContext/ui/overlay.py +412 -0
- OpenGLContext/ui/panel.py +459 -0
- OpenGLContext/ui/pictures.py +261 -0
- OpenGLContext/ui/screen.py +177 -0
- OpenGLContext/ui/scroll.py +297 -0
- OpenGLContext/ui/session.py +329 -0
- OpenGLContext/ui/settings.py +273 -0
- OpenGLContext/ui/skin.py +330 -0
- OpenGLContext/ui/widgets.py +1199 -0
- OpenGLContext/userpaths.py +48 -0
- OpenGLContext/utilities.py +94 -0
- OpenGLContext/vectorutilities.py +101 -0
- OpenGLContext/viewer/__init__.py +60 -0
- OpenGLContext/viewer/adapters/__init__.py +150 -0
- OpenGLContext/viewer/adapters/base.py +157 -0
- OpenGLContext/viewer/adapters/gltf.py +31 -0
- OpenGLContext/viewer/adapters/obj.py +20 -0
- OpenGLContext/viewer/adapters/scenegraph.py +71 -0
- OpenGLContext/viewer/adapters/tiles.py +296 -0
- OpenGLContext/viewer/adapters/vrml.py +25 -0
- OpenGLContext/viewer/asyncscene.py +117 -0
- OpenGLContext/viewer/caption.py +126 -0
- OpenGLContext/viewer/capture.py +77 -0
- OpenGLContext/viewer/debug.py +78 -0
- OpenGLContext/viewer/environment.py +131 -0
- OpenGLContext/viewer/framing.py +111 -0
- OpenGLContext/viewer/library.py +235 -0
- OpenGLContext/viewer/menu.py +218 -0
- OpenGLContext/viewer/options.py +150 -0
- OpenGLContext/viewer/overlay.py +63 -0
- OpenGLContext/viewer/sceneviewer.py +1056 -0
- OpenGLContext/viewer/screens.py +172 -0
- OpenGLContext/viewer/source.py +56 -0
- OpenGLContext/visitor.py +68 -0
- OpenGLContext/vrmlcontext.py +72 -0
- OpenGLContext/wxcontext.py +424 -0
- OpenGLContext/wxinteractivecontext.py +25 -0
- OpenGLContext/wxtestingcontext.py +9 -0
- OpenGLContext/wxvrmlcontext.py +13 -0
- openglcontext-3.0.0a1.dist-info/METADATA +650 -0
- openglcontext-3.0.0a1.dist-info/RECORD +417 -0
- openglcontext-3.0.0a1.dist-info/WHEEL +5 -0
- openglcontext-3.0.0a1.dist-info/entry_points.txt +11 -0
- openglcontext-3.0.0a1.dist-info/licenses/license.txt +89 -0
- openglcontext-3.0.0a1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"""PyGame bitmap and texmap fonts"""
|
|
2
|
+
from OpenGLContext.scenegraph.text import fontprovider, font
|
|
3
|
+
from OpenGL.GL import *
|
|
4
|
+
from pygame import font as pygame_font
|
|
5
|
+
from pygame import image, surfarray, transform
|
|
6
|
+
import pygame, traceback, os
|
|
7
|
+
from OpenGLContext.arrays import transpose, shape, zeros, contiguous
|
|
8
|
+
import logging
|
|
9
|
+
log = logging.getLogger( __name__ )
|
|
10
|
+
|
|
11
|
+
pygame_font.init()
|
|
12
|
+
pygame.init()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PyGameBitmapFont( font.NoDepthBufferMixIn, font.BitmapFontMixIn, font.Font ):
|
|
16
|
+
"""A PyGame-provided Bitmap Font
|
|
17
|
+
"""
|
|
18
|
+
format = "bitmap"
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
fontStyle = None,
|
|
22
|
+
filename = None,
|
|
23
|
+
size = None,
|
|
24
|
+
):
|
|
25
|
+
self._displayLists = {}
|
|
26
|
+
self.fontStyle = fontStyle or None
|
|
27
|
+
if filename is None or size is None:
|
|
28
|
+
fontFile, weight, italics, size = PyGameFontProvider.match( fontStyle )
|
|
29
|
+
self.font = pygame_font.Font( fontFile, int(size))
|
|
30
|
+
self.filename = filename
|
|
31
|
+
self.size = size
|
|
32
|
+
if __debug__:
|
|
33
|
+
log.info( """Created font %s""", self)
|
|
34
|
+
|
|
35
|
+
def createChar( self, char, mode=None ):
|
|
36
|
+
"""Create the single-character display list
|
|
37
|
+
"""
|
|
38
|
+
dataArray, metrics = self.createCharTexture( char, mode=mode )
|
|
39
|
+
if dataArray is not None:
|
|
40
|
+
## XXX should store dataArray in global cache...
|
|
41
|
+
list = self.textureToList( dataArray, metrics, mode=mode )
|
|
42
|
+
## XXX list should be stored in a context-specific cache...
|
|
43
|
+
return list, metrics
|
|
44
|
+
return None, metrics
|
|
45
|
+
|
|
46
|
+
def textureToList( self, array, metrics, mode=None ):
|
|
47
|
+
"""Compile Numeric Python array to a display-list
|
|
48
|
+
|
|
49
|
+
XXX:
|
|
50
|
+
use a single texture and coordinates for texmap
|
|
51
|
+
version
|
|
52
|
+
|
|
53
|
+
special case ' ' so that it's not rendered as
|
|
54
|
+
an image...
|
|
55
|
+
"""
|
|
56
|
+
if shape(array)[-1] == 2:
|
|
57
|
+
mode = GL_LUMINANCE_ALPHA
|
|
58
|
+
elif shape(array)[-1] == 4:
|
|
59
|
+
mode = GL_RGBA
|
|
60
|
+
else:
|
|
61
|
+
raise ValueError( """Unsupported array dimension for textureToList, require 2 or 4 items/pixel, got %s"""%(shape(array)[-1],))
|
|
62
|
+
list = glGenLists (1)
|
|
63
|
+
glNewList( list, GL_COMPILE )
|
|
64
|
+
try:
|
|
65
|
+
try:
|
|
66
|
+
if metrics.char != ' ':
|
|
67
|
+
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
|
|
68
|
+
glPixelStorei(GL_PACK_ALIGNMENT, 1)
|
|
69
|
+
glDrawPixelsub(
|
|
70
|
+
mode,
|
|
71
|
+
array,
|
|
72
|
+
)
|
|
73
|
+
glBitmap( 0,0,0,0, metrics.width,0, None )
|
|
74
|
+
except Exception:
|
|
75
|
+
glDeleteLists( list, 1 )
|
|
76
|
+
raise
|
|
77
|
+
finally:
|
|
78
|
+
glEndList()
|
|
79
|
+
return list
|
|
80
|
+
|
|
81
|
+
def createCharTexture( self, char, mode=None ):
|
|
82
|
+
"""Create character's texture/bitmap as a Numeric array w/ width and height
|
|
83
|
+
|
|
84
|
+
This uses PyGame and Numeric to attempt to create
|
|
85
|
+
an anti-aliased luminance texture-map of the given
|
|
86
|
+
character and return it as (data, width, height).
|
|
87
|
+
"""
|
|
88
|
+
try:
|
|
89
|
+
letter_render = self.font.render(
|
|
90
|
+
char,
|
|
91
|
+
1,
|
|
92
|
+
(255,255,255)
|
|
93
|
+
)
|
|
94
|
+
except Exception:
|
|
95
|
+
traceback.print_exc()
|
|
96
|
+
return None, font.CharacterMetrics(char,0,0)
|
|
97
|
+
else:
|
|
98
|
+
# XXX Figure out why this rotate appears to be required :(
|
|
99
|
+
letter_render = transform.rotate( letter_render, -90.0)
|
|
100
|
+
colour = surfarray.array3d( letter_render )
|
|
101
|
+
alpha = surfarray.array_alpha( letter_render )
|
|
102
|
+
colour[:,:,1] = alpha
|
|
103
|
+
colour = colour[:,:,:2]
|
|
104
|
+
colour = contiguous( colour ).astype( 'B' )
|
|
105
|
+
# This produces what looks like garbage, but displays correctly
|
|
106
|
+
colour.shape = (colour.shape[1],colour.shape[0],)+colour.shape[2:]
|
|
107
|
+
return colour, font.CharacterMetrics(
|
|
108
|
+
char,
|
|
109
|
+
colour.shape[0],
|
|
110
|
+
colour.shape[1],
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
def lists( self, value, mode=None ):
|
|
114
|
+
"""Get a sequence of display-list integers for value
|
|
115
|
+
|
|
116
|
+
Basically, this does a bit of trickery to do
|
|
117
|
+
as-required compilation of display-lists, so
|
|
118
|
+
that only those characters actually required
|
|
119
|
+
by the displayed text are compiled.
|
|
120
|
+
|
|
121
|
+
NOTE: Must be called from within the rendering
|
|
122
|
+
thread and within the rendering pass!
|
|
123
|
+
"""
|
|
124
|
+
if __debug__:
|
|
125
|
+
log.info( """lists %s(%s)""", self, repr(value))
|
|
126
|
+
lists = []
|
|
127
|
+
font = self.font
|
|
128
|
+
for char in value:
|
|
129
|
+
list, metrics = self.getChar( char, mode=mode )
|
|
130
|
+
if list is not None:
|
|
131
|
+
lists.append( list )
|
|
132
|
+
if __debug__:
|
|
133
|
+
log.info( """lists %s(%s)->%s""", self, repr(value), lists)
|
|
134
|
+
return lists
|
|
135
|
+
def lineHeight(self, mode=None ):
|
|
136
|
+
"""Retrieve normal line-height for this font
|
|
137
|
+
"""
|
|
138
|
+
return self.font.get_linesize()
|
|
139
|
+
|
|
140
|
+
class _PyGameFontProvider (fontprovider.TTFFontProvider):
|
|
141
|
+
"""Singleton for creating new PyGameBitmapFonts
|
|
142
|
+
"""
|
|
143
|
+
format = "bitmap"
|
|
144
|
+
scale = 12
|
|
145
|
+
def __init__( self ):
|
|
146
|
+
super( _PyGameFontProvider, self).__init__()
|
|
147
|
+
self.nameToFile = {}
|
|
148
|
+
|
|
149
|
+
def create( self, fontStyle, mode=None ):
|
|
150
|
+
"""Create a new font for the given fontStyle and mode"""
|
|
151
|
+
fontFile, weight, italics, size = key = self.match(fontStyle, mode)
|
|
152
|
+
# do we already have this filename + size established?
|
|
153
|
+
if key in self.fonts:
|
|
154
|
+
return self.fonts.get( key )
|
|
155
|
+
bitmapFont = PyGameBitmapFont( fontStyle, filename = fontFile )
|
|
156
|
+
self.addFont( fontStyle, bitmapFont )
|
|
157
|
+
self.fonts[key] = bitmapFont
|
|
158
|
+
return bitmapFont
|
|
159
|
+
def key( self, fontStyle, mode=None ):
|
|
160
|
+
"""Calculate the key for the fontStyle"""
|
|
161
|
+
if not fontStyle:
|
|
162
|
+
return None
|
|
163
|
+
attributes = ('family','style','size',)
|
|
164
|
+
result = []
|
|
165
|
+
for a in attributes:
|
|
166
|
+
if hasattr( fontStyle, a):
|
|
167
|
+
item = getattr( fontStyle, a)
|
|
168
|
+
if isinstance( item, list ):
|
|
169
|
+
item = tuple( item )
|
|
170
|
+
result.append( item )
|
|
171
|
+
else:
|
|
172
|
+
result.append( None )
|
|
173
|
+
return tuple( result )
|
|
174
|
+
|
|
175
|
+
def match( self, fontStyle, mode=None ):
|
|
176
|
+
"""Attempt to find matching font-file for our fontstyle
|
|
177
|
+
|
|
178
|
+
Should match any name passed into addFontFile,
|
|
179
|
+
as well as the short filename for the font.
|
|
180
|
+
"""
|
|
181
|
+
registry = self.getTTFRegistry()
|
|
182
|
+
if registry:
|
|
183
|
+
fontName = registry.fontNameFromStyle( fontStyle, mode=mode )
|
|
184
|
+
weight, italics = registry.modifiersFromStyle( fontStyle, mode=mode )
|
|
185
|
+
specificFonts = registry.fontMembers( fontName, weight, italics )
|
|
186
|
+
if not specificFonts:
|
|
187
|
+
# broaden to any weight
|
|
188
|
+
specificFonts = registry.fontMembers( fontName, None, italics )
|
|
189
|
+
if not specificFonts:
|
|
190
|
+
# broaden to every sub-font...
|
|
191
|
+
specificFonts = registry.fontMembers( fontName )
|
|
192
|
+
if not specificFonts:
|
|
193
|
+
raise RuntimeError( """No concrete fonts found for general font %r (somehow)"""%( fontName, ))
|
|
194
|
+
# okay, just arbitrarily choose the first item, normally will only be one anyway
|
|
195
|
+
specificFont = specificFonts[0]
|
|
196
|
+
fontFile = registry.fontFile( specificFont )
|
|
197
|
+
size = self.scale
|
|
198
|
+
if fontStyle:
|
|
199
|
+
size = self.scale * fontStyle.size
|
|
200
|
+
return fontFile, weight, italics, size
|
|
201
|
+
|
|
202
|
+
def enumerate(self, mode = None):
|
|
203
|
+
"""Iterate through all available font-keys (whether instantiated or not)
|
|
204
|
+
|
|
205
|
+
This uses the wxFontEnumerator class to provide a list of
|
|
206
|
+
font names from the wxPython system, (with all names
|
|
207
|
+
lowercased).
|
|
208
|
+
"""
|
|
209
|
+
return self.nameToFile.keys()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
PyGameFontProvider = _PyGameFontProvider()
|
|
213
|
+
PyGameFontProvider.registerProvider( PyGameFontProvider )
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
"""Shader-based bitmap fonts using texture atlas.
|
|
2
|
+
|
|
3
|
+
This module provides a font provider that uses pre-rendered texture atlases
|
|
4
|
+
for text rendering, compatible with OpenGL core profile where GLUT bitmap
|
|
5
|
+
fonts and display lists are not available.
|
|
6
|
+
|
|
7
|
+
This serves as a fallback when glutfont is not available (non-GLUT contexts).
|
|
8
|
+
"""
|
|
9
|
+
from OpenGL.GL import *
|
|
10
|
+
from OpenGLContext.scenegraph.text import fontprovider, font
|
|
11
|
+
from OpenGLContext.arrays import array
|
|
12
|
+
import numpy as np
|
|
13
|
+
import logging
|
|
14
|
+
import io
|
|
15
|
+
|
|
16
|
+
log = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ShaderBitmapFont(font.NoDepthBufferMixIn, font.Font):
|
|
20
|
+
"""Shader-based bitmap font using texture atlas.
|
|
21
|
+
|
|
22
|
+
This font renders text using textured quads with a pre-rendered
|
|
23
|
+
font atlas, compatible with OpenGL core profile.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, fontStyle=None, size=16):
|
|
27
|
+
"""Initialize the shader bitmap font.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
fontStyle: VRML FontStyle node (optional)
|
|
31
|
+
size: Font size in pixels
|
|
32
|
+
"""
|
|
33
|
+
self.fontStyle = fontStyle
|
|
34
|
+
self._size = size
|
|
35
|
+
self._displayLists = {} # Cache for character metrics
|
|
36
|
+
self._initialized = False
|
|
37
|
+
self._texture = None
|
|
38
|
+
self._atlas_module = None
|
|
39
|
+
|
|
40
|
+
# Atlas parameters (will be set from module)
|
|
41
|
+
self._char_width = 0
|
|
42
|
+
self._char_height = 0
|
|
43
|
+
self._atlas_width = 0
|
|
44
|
+
self._atlas_height = 0
|
|
45
|
+
self._first_char = 32
|
|
46
|
+
self._last_char = 126
|
|
47
|
+
self._chars_per_row = 16
|
|
48
|
+
|
|
49
|
+
def _ensure_initialized(self):
|
|
50
|
+
"""Lazily initialize the font texture."""
|
|
51
|
+
if self._initialized:
|
|
52
|
+
return True
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
from OpenGLContext.scenegraph.text import fonts
|
|
56
|
+
actual_size, module = fonts.get_closest_atlas(self._size)
|
|
57
|
+
if module is None:
|
|
58
|
+
log.error("No font atlas available")
|
|
59
|
+
return False
|
|
60
|
+
|
|
61
|
+
self._atlas_module = module
|
|
62
|
+
self._char_width = module.char_width
|
|
63
|
+
self._char_height = module.char_height
|
|
64
|
+
self._atlas_width = module.atlas_width
|
|
65
|
+
self._atlas_height = module.atlas_height
|
|
66
|
+
self._first_char = module.first_char
|
|
67
|
+
self._last_char = module.last_char
|
|
68
|
+
self._chars_per_row = module.chars_per_row
|
|
69
|
+
|
|
70
|
+
# Create texture
|
|
71
|
+
png_data = module.get_png_data()
|
|
72
|
+
from PIL import Image
|
|
73
|
+
img = Image.open(io.BytesIO(png_data))
|
|
74
|
+
img = img.convert('RGBA')
|
|
75
|
+
texture_data = np.array(img, dtype=np.uint8)
|
|
76
|
+
|
|
77
|
+
self._texture = glGenTextures(1)
|
|
78
|
+
glBindTexture(GL_TEXTURE_2D, self._texture)
|
|
79
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
|
80
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
|
81
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
|
|
82
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
|
|
83
|
+
glTexImage2D(
|
|
84
|
+
GL_TEXTURE_2D, 0, GL_RGBA,
|
|
85
|
+
self._atlas_width, self._atlas_height, 0,
|
|
86
|
+
GL_RGBA, GL_UNSIGNED_BYTE,
|
|
87
|
+
texture_data.tobytes()
|
|
88
|
+
)
|
|
89
|
+
glBindTexture(GL_TEXTURE_2D, 0)
|
|
90
|
+
|
|
91
|
+
self._initialized = True
|
|
92
|
+
return True
|
|
93
|
+
except Exception as e:
|
|
94
|
+
log.error("Failed to initialize shader font: %s", e)
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
def createChar(self, char, mode=None):
|
|
98
|
+
"""Create metrics for a character.
|
|
99
|
+
|
|
100
|
+
Note: Unlike GLUT fonts, we don't use display lists.
|
|
101
|
+
We just store the metrics for width calculation.
|
|
102
|
+
"""
|
|
103
|
+
self._ensure_initialized()
|
|
104
|
+
metrics = font.CharacterMetrics(
|
|
105
|
+
char,
|
|
106
|
+
self._char_width,
|
|
107
|
+
self._char_height
|
|
108
|
+
)
|
|
109
|
+
# Return None for display list (we don't use them) and metrics
|
|
110
|
+
return None, metrics
|
|
111
|
+
|
|
112
|
+
def lists(self, value, mode=None):
|
|
113
|
+
"""Get display lists for value.
|
|
114
|
+
|
|
115
|
+
For shader fonts, we don't use display lists.
|
|
116
|
+
Return empty list - actual rendering is done differently.
|
|
117
|
+
"""
|
|
118
|
+
return []
|
|
119
|
+
|
|
120
|
+
def lineHeight(self, mode=None):
|
|
121
|
+
"""Get the line height for this font."""
|
|
122
|
+
self._ensure_initialized()
|
|
123
|
+
return int(self._char_height * 1.2)
|
|
124
|
+
|
|
125
|
+
def render(self, lines, fontStyle=None, mode=None):
|
|
126
|
+
"""Render text lines.
|
|
127
|
+
|
|
128
|
+
For shader-based rendering, we need to use the shader pipeline.
|
|
129
|
+
"""
|
|
130
|
+
if not self._ensure_initialized():
|
|
131
|
+
return
|
|
132
|
+
|
|
133
|
+
if isinstance(lines, (bytes, str)):
|
|
134
|
+
lines = self.toLines(lines, mode=mode)
|
|
135
|
+
|
|
136
|
+
if fontStyle is None:
|
|
137
|
+
fontStyle = self.fontStyle
|
|
138
|
+
|
|
139
|
+
# Check if we're in shader mode
|
|
140
|
+
shader_mode = getattr(mode, 'shader_mode', False)
|
|
141
|
+
shader_program = getattr(mode, 'shader_program', None)
|
|
142
|
+
|
|
143
|
+
if shader_mode and shader_program:
|
|
144
|
+
self._render_shader(lines, fontStyle, mode, shader_program)
|
|
145
|
+
else:
|
|
146
|
+
# Legacy fallback - try to use glRasterPos/glBitmap style
|
|
147
|
+
self._render_legacy(lines, fontStyle, mode)
|
|
148
|
+
|
|
149
|
+
def _render_shader(self, lines, fontStyle, mode, shader_program):
|
|
150
|
+
"""Render using shader pipeline."""
|
|
151
|
+
from OpenGLContext.scenegraph.text.shadertext import get_text_renderer
|
|
152
|
+
|
|
153
|
+
# Get viewport for coordinate conversion
|
|
154
|
+
viewport = getattr(mode, 'viewport', None)
|
|
155
|
+
if viewport is None:
|
|
156
|
+
return
|
|
157
|
+
|
|
158
|
+
viewport_width = viewport[2]
|
|
159
|
+
viewport_height = viewport[3]
|
|
160
|
+
|
|
161
|
+
# Calculate text position - we need to convert from model space
|
|
162
|
+
# For now, render at a fixed screen position
|
|
163
|
+
# TODO: proper model-to-screen coordinate conversion
|
|
164
|
+
|
|
165
|
+
text = '\n'.join(line.base for line in lines)
|
|
166
|
+
renderer = get_text_renderer(self._char_height)
|
|
167
|
+
|
|
168
|
+
# Render at bottom-left with some margin
|
|
169
|
+
renderer.render_text(
|
|
170
|
+
text, 10, 30, shader_program,
|
|
171
|
+
viewport_width, viewport_height,
|
|
172
|
+
color=(1.0, 1.0, 1.0, 1.0)
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
def _render_legacy(self, lines, fontStyle, mode):
|
|
176
|
+
"""Render using legacy OpenGL (compatibility mode).
|
|
177
|
+
|
|
178
|
+
This uses glRasterPos and textured quads for each character.
|
|
179
|
+
"""
|
|
180
|
+
if not self._texture:
|
|
181
|
+
return
|
|
182
|
+
|
|
183
|
+
glEnable(GL_BLEND)
|
|
184
|
+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
|
185
|
+
glEnable(GL_TEXTURE_2D)
|
|
186
|
+
glBindTexture(GL_TEXTURE_2D, self._texture)
|
|
187
|
+
# Modulate so the glyph alpha drives blending. Scene geometry (e.g.
|
|
188
|
+
# textured Shapes) may leave the env mode as GL_DECAL, which discards
|
|
189
|
+
# the texture alpha and renders solid opaque cells instead of glyphs.
|
|
190
|
+
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
spacing = self.getSpacing(fontStyle=fontStyle, mode=mode)
|
|
194
|
+
adjust = self.verticalAdjust(spacing, lines, fontStyle=fontStyle, mode=mode)
|
|
195
|
+
|
|
196
|
+
glPushMatrix()
|
|
197
|
+
glTranslatef(0, adjust, 0)
|
|
198
|
+
|
|
199
|
+
for line in lines:
|
|
200
|
+
height = line.height * spacing if fontStyle else line.height
|
|
201
|
+
|
|
202
|
+
glPushMatrix()
|
|
203
|
+
for char in line.base:
|
|
204
|
+
self._draw_char_quad(char)
|
|
205
|
+
glPopMatrix()
|
|
206
|
+
|
|
207
|
+
glTranslatef(0, -height, 0)
|
|
208
|
+
|
|
209
|
+
glPopMatrix()
|
|
210
|
+
finally:
|
|
211
|
+
glBindTexture(GL_TEXTURE_2D, 0)
|
|
212
|
+
glDisable(GL_TEXTURE_2D)
|
|
213
|
+
glDisable(GL_BLEND)
|
|
214
|
+
|
|
215
|
+
def _draw_char_quad(self, char):
|
|
216
|
+
"""Draw a single character as a textured quad."""
|
|
217
|
+
char_code = ord(char)
|
|
218
|
+
if char_code < self._first_char or char_code > self._last_char:
|
|
219
|
+
char_code = ord('?')
|
|
220
|
+
|
|
221
|
+
char_idx = char_code - self._first_char
|
|
222
|
+
col = char_idx % self._chars_per_row
|
|
223
|
+
row = char_idx // self._chars_per_row
|
|
224
|
+
|
|
225
|
+
# Texture coordinates
|
|
226
|
+
u0 = col * self._char_width / self._atlas_width
|
|
227
|
+
u1 = (col + 1) * self._char_width / self._atlas_width
|
|
228
|
+
v0 = row * self._char_height / self._atlas_height
|
|
229
|
+
v1 = (row + 1) * self._char_height / self._atlas_height
|
|
230
|
+
|
|
231
|
+
# Draw quad
|
|
232
|
+
w = self._char_width
|
|
233
|
+
h = self._char_height
|
|
234
|
+
|
|
235
|
+
glBegin(GL_QUADS)
|
|
236
|
+
glTexCoord2f(u0, v1); glVertex2f(0, 0)
|
|
237
|
+
glTexCoord2f(u1, v1); glVertex2f(w, 0)
|
|
238
|
+
glTexCoord2f(u1, v0); glVertex2f(w, h)
|
|
239
|
+
glTexCoord2f(u0, v0); glVertex2f(0, h)
|
|
240
|
+
glEnd()
|
|
241
|
+
|
|
242
|
+
glTranslatef(w, 0, 0)
|
|
243
|
+
|
|
244
|
+
def leftJustify(self, lines, fontStyle, mode=None):
|
|
245
|
+
"""Left-justify text."""
|
|
246
|
+
self.render(lines, fontStyle, mode)
|
|
247
|
+
|
|
248
|
+
def centerJustify(self, lines, fontStyle, mode=None):
|
|
249
|
+
"""Center-justify text."""
|
|
250
|
+
# TODO: proper center justification
|
|
251
|
+
self.render(lines, fontStyle, mode)
|
|
252
|
+
|
|
253
|
+
def rightJustify(self, lines, fontStyle, mode=None):
|
|
254
|
+
"""Right-justify text."""
|
|
255
|
+
# TODO: proper right justification
|
|
256
|
+
self.render(lines, fontStyle, mode)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
class _ShaderFontProvider(fontprovider.FontProvider):
|
|
260
|
+
"""Font provider using shader-based texture atlas fonts.
|
|
261
|
+
|
|
262
|
+
This provider creates ShaderBitmapFont instances as a fallback
|
|
263
|
+
when GLUT fonts are not available, and is required for core profile
|
|
264
|
+
contexts where legacy GL functions are not available.
|
|
265
|
+
"""
|
|
266
|
+
format = "bitmap"
|
|
267
|
+
shader_compatible = True # Mark as compatible with core profile/shader mode
|
|
268
|
+
scale = 12 # Points to pixels
|
|
269
|
+
|
|
270
|
+
# Available sizes from font atlas
|
|
271
|
+
available_sizes = [12, 16, 24, 32, 48]
|
|
272
|
+
|
|
273
|
+
def create(self, fontStyle, mode=None):
|
|
274
|
+
"""Create a new font for the given fontStyle and mode."""
|
|
275
|
+
size = self._get_size(fontStyle)
|
|
276
|
+
|
|
277
|
+
# Check for existing font
|
|
278
|
+
fontHash = ('shader', size)
|
|
279
|
+
if fontHash in self.fonts:
|
|
280
|
+
current = self.fonts.get(fontHash)
|
|
281
|
+
self.addFont(fontStyle, current)
|
|
282
|
+
return current
|
|
283
|
+
|
|
284
|
+
# Create new font
|
|
285
|
+
shaderFont = ShaderBitmapFont(fontStyle, size=size)
|
|
286
|
+
self.addFont(fontStyle, shaderFont)
|
|
287
|
+
self.fonts[fontHash] = shaderFont
|
|
288
|
+
return shaderFont
|
|
289
|
+
|
|
290
|
+
def _get_size(self, fontStyle):
|
|
291
|
+
"""Get appropriate font size for fontStyle."""
|
|
292
|
+
if fontStyle and hasattr(fontStyle, 'size'):
|
|
293
|
+
target = int(fontStyle.size * self.scale)
|
|
294
|
+
else:
|
|
295
|
+
target = 12
|
|
296
|
+
|
|
297
|
+
# Find closest available size
|
|
298
|
+
diffs = [abs(target - s) for s in self.available_sizes]
|
|
299
|
+
best_idx = diffs.index(min(diffs))
|
|
300
|
+
return self.available_sizes[best_idx]
|
|
301
|
+
|
|
302
|
+
def key(self, fontStyle=None):
|
|
303
|
+
"""Calculate font key for caching."""
|
|
304
|
+
if not fontStyle:
|
|
305
|
+
return None
|
|
306
|
+
return (
|
|
307
|
+
tuple(fontStyle.family) if fontStyle.family else (),
|
|
308
|
+
fontStyle.size,
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
def enumerate(self, mode=None):
|
|
312
|
+
"""Enumerate available fonts."""
|
|
313
|
+
return ['SANS', 'SERIF', 'TYPEWRITER']
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
# Create singleton provider
|
|
317
|
+
ShaderFontProvider = _ShaderFontProvider()
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def register():
|
|
321
|
+
"""Register the shader font provider.
|
|
322
|
+
|
|
323
|
+
Call this to make shader fonts available as a bitmap font provider.
|
|
324
|
+
"""
|
|
325
|
+
ShaderFontProvider.registerProvider(ShaderFontProvider)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def is_available():
|
|
329
|
+
"""Check if shader fonts are available (font atlas exists)."""
|
|
330
|
+
try:
|
|
331
|
+
from OpenGLContext.scenegraph.text import fonts
|
|
332
|
+
_, module = fonts.get_closest_atlas(16)
|
|
333
|
+
return module is not None
|
|
334
|
+
except ImportError:
|
|
335
|
+
return False
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
# Auto-register if font atlases are available
|
|
339
|
+
if is_available():
|
|
340
|
+
register()
|