diff --git a/direct/src/motiontrail/MotionTrail.py b/direct/src/motiontrail/MotionTrail.py index 531deef003..bf11cf5493 100644 --- a/direct/src/motiontrail/MotionTrail.py +++ b/direct/src/motiontrail/MotionTrail.py @@ -4,6 +4,7 @@ from panda3d.core import * from panda3d.direct import * from direct.task import Task from direct.showbase.DirectObject import DirectObject +from direct.directnotify.DirectNotifyGlobal import directNotify def remove_task ( ): diff --git a/direct/src/p3d/Packager.py b/direct/src/p3d/Packager.py index 791bad6b8e..f9ddab983f 100644 --- a/direct/src/p3d/Packager.py +++ b/direct/src/p3d/Packager.py @@ -3361,7 +3361,7 @@ class Packager: self.currentPackage.addExtensionModules() self.currentPackage.freezer.reset() - self.do_file('panda3d/_core.pyd', newDir='panda3d') + self.do_file('panda3d/core.pyd', newDir='panda3d') # This is the key Python module that is imported at runtime to # start an application running. diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index 3c8e8628c6..e0d1f71b82 100644 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -193,7 +193,7 @@ run_python() { return 1; } - // Set the __path__ such that it can find panda3d/_core.pyd, etc. + // Set the __path__ such that it can find panda3d/core.pyd, etc. Filename panda3d_dir(dir, "panda3d"); string dir_str = panda3d_dir.to_os_specific(); PyModule_AddObject(panda3d_module, "__path__", Py_BuildValue("[s#]", dir_str.data(), dir_str.length())); diff --git a/direct/src/showbase/VFSImporter.py b/direct/src/showbase/VFSImporter.py index e092775e6e..eb2b7bd7d4 100644 --- a/direct/src/showbase/VFSImporter.py +++ b/direct/src/showbase/VFSImporter.py @@ -1,7 +1,7 @@ __all__ = ['register', 'sharedPackages', 'reloadSharedPackage', 'reloadSharedPackages'] -from panda3d._core import Filename, VirtualFileSystem, VirtualFileMountSystem, OFileStream, copyStream +from panda3d.core import Filename, VirtualFileSystem, VirtualFileMountSystem, OFileStream, copyStream import sys import marshal import imp diff --git a/direct/src/stdpy/file.py b/direct/src/stdpy/file.py index 27257ad890..d6ef48cd9e 100644 --- a/direct/src/stdpy/file.py +++ b/direct/src/stdpy/file.py @@ -10,7 +10,7 @@ __all__ = [ 'execfile', ] -import panda3d._core as core +from panda3d import core import sys import os import io diff --git a/dtool/src/cppparser/cppMakeSeq.h b/dtool/src/cppparser/cppMakeSeq.h index 2c1192d278..e5eb414f11 100644 --- a/dtool/src/cppparser/cppMakeSeq.h +++ b/dtool/src/cppparser/cppMakeSeq.h @@ -19,6 +19,7 @@ #include "cppDeclaration.h" #include "cppIdentifier.h" +#include "cppFunctionGroup.h" /////////////////////////////////////////////////////////////////// // Class : CPPMakeSeq diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 3000aca8e1..cde94080cd 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -3008,15 +3008,8 @@ close_gsg() { // will be responsible for cleaning up anything we don't clean up // explicitly. We'll just let them drop. - // However, if any objects have recently been released, we have to - // ensure they are actually deleted properly. - Thread *current_thread = Thread::get_current_thread(); - _prepared_objects->begin_frame(this, current_thread); - _prepared_objects->end_frame(current_thread); - - // We have to clear the list of timer queries, though, otherwise - // their destructors will cause a crash when they try to access - // the GSG object. + // Make sure that all the contexts belonging to the GSG are deleted. + _prepared_objects.clear(); #ifdef DO_PSTATS _pending_timer_queries.clear(); #endif diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index dd9b1e1348..46ac9a7ba6 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -409,20 +409,19 @@ rebuild_bitplanes() { // Now create the FBO's. _have_any_color = false; - _fbo.reserve(num_fbos); - for (int layer = 0; layer < num_fbos; ++layer) { - if (layer >= _fbo.size()) { - _fbo.push_back(0); - } + if (num_fbos > _fbo.size()) { + // Generate more FBO handles. + int start = _fbo.size(); + _fbo.resize(num_fbos, 0); + glgsg->_glGenFramebuffers(num_fbos - start, &_fbo[start]); + } + + for (int layer = 0; layer < num_fbos; ++layer) { // Bind the FBO if (_fbo[layer] == 0) { - glgsg->_glGenFramebuffers(1, &_fbo[layer]); - - if (_fbo[layer] == 0) { - report_my_gl_errors(); - return; - } + report_my_gl_errors(); + return; } glgsg->bind_fbo(_fbo[layer]); @@ -1118,11 +1117,7 @@ generate_mipmaps() { CLP(TextureContext) *gtc = *it; if (gtc->_generate_mipmaps) { - glgsg->_state_texture = 0; - glgsg->update_texture(gtc, true); - glgsg->apply_texture(gtc); - glgsg->_glGenerateMipmap(gtc->_target); - glBindTexture(gtc->_target, 0); + glgsg->generate_mipmaps(gtc); } } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 422cfe6390..bd797c249f 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -284,12 +284,14 @@ fix_component_ordering(PTA_uchar &new_image, case GL_RGB: switch (tex->get_component_type()) { case Texture::T_unsigned_byte: + case Texture::T_byte: new_image = PTA_uchar::empty_array(orig_image_size); uchar_bgr_to_rgb(new_image, orig_image, orig_image_size / 3); result = new_image; break; case Texture::T_unsigned_short: + case Texture::T_short: new_image = PTA_uchar::empty_array(orig_image_size); ushort_bgr_to_rgb((unsigned short *)new_image.p(), (const unsigned short *)orig_image, @@ -305,12 +307,14 @@ fix_component_ordering(PTA_uchar &new_image, case GL_RGBA: switch (tex->get_component_type()) { case Texture::T_unsigned_byte: + case Texture::T_byte: new_image = PTA_uchar::empty_array(orig_image_size); uchar_bgra_to_rgba(new_image, orig_image, orig_image_size / 4); result = new_image; break; case Texture::T_unsigned_short: + case Texture::T_short: new_image = PTA_uchar::empty_array(orig_image_size); ushort_bgra_to_rgba((unsigned short *)new_image.p(), (const unsigned short *)orig_image, @@ -1873,6 +1877,15 @@ reset() { #endif // OPENGLES #endif +#ifndef OPENGLES + if (is_at_least_gl_version(4, 5) || has_extension("GL_ARB_direct_state_access")) { + _glGenerateTextureMipmap = (PFNGLGENERATETEXTUREMIPMAPPROC) + get_extension_func("glGenerateTextureMipmap"); + } else { + _glGenerateTextureMipmap = NULL; + } +#endif + _supports_framebuffer_multisample = false; if ( has_extension("GL_EXT_framebuffer_multisample") ) { _supports_framebuffer_multisample = true; @@ -4685,6 +4698,13 @@ void CLP(GraphicsStateGuardian):: release_texture(TextureContext *tc) { CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); +#ifndef OPENGLES + _textures_needing_fetch_barrier.erase(gtc); + _textures_needing_image_access_barrier.erase(gtc); + _textures_needing_update_barrier.erase(gtc); + _textures_needing_framebuffer_barrier.erase(gtc); +#endif + glDeleteTextures(1, >c->_index); if (gtc->_buffer != 0) { @@ -7808,6 +7828,10 @@ get_component_type(Texture::ComponentType component_type) { #ifndef OPENGLES_1 return GL_INT; #endif + case Texture::T_byte: + return GL_BYTE; + case Texture::T_short: + return GL_SHORT; default: GLCAT.error() << "Invalid Texture::Type value!\n"; return GL_UNSIGNED_BYTE; @@ -8432,6 +8456,10 @@ get_internal_image_format(Texture *tex, bool force_sized) const { #ifndef OPENGLES if (tex->get_component_type() == Texture::T_unsigned_short) { return GL_RGBA16; + } else if (tex->get_component_type() == Texture::T_short) { + return GL_RGBA16_SNORM; + } else if (tex->get_component_type() == Texture::T_byte) { + return GL_RGBA8_SNORM; } else #endif { @@ -8448,27 +8476,32 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return force_sized ? GL_RGBA8 : GL_RGBA; #else case Texture::F_rgba8: - return GL_RGBA8; + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_RGBA8; + } else { + return GL_RGBA8_SNORM; + } + case Texture::F_r8i: - if (tex->get_component_type() == Texture::T_unsigned_byte) { + if (Texture::is_unsigned(tex->get_component_type())) { return GL_R8UI; } else { return GL_R8I; } case Texture::F_rg8i: - if (tex->get_component_type() == Texture::T_unsigned_byte) { + if (Texture::is_unsigned(tex->get_component_type())) { return GL_RG8UI; } else { return GL_RG8I; } case Texture::F_rgb8i: - if (tex->get_component_type() == Texture::T_unsigned_byte) { + if (Texture::is_unsigned(tex->get_component_type())) { return GL_RGB8UI; } else { return GL_RGB8I; } case Texture::F_rgba8i: - if (tex->get_component_type() == Texture::T_unsigned_byte) { + if (Texture::is_unsigned(tex->get_component_type())) { return GL_RGBA8UI; } else { return GL_RGBA8I; @@ -8480,17 +8513,24 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_rgba16: if (tex->get_component_type() == Texture::T_float) { return GL_RGBA16F; - } else { + } else if (Texture::is_unsigned(tex->get_component_type())) { return GL_RGBA16; + } else { + return GL_RGBA16_SNORM; } case Texture::F_rgba32: return GL_RGBA32F; #endif // OPENGLES case Texture::F_rgb: - if (tex->get_component_type() == Texture::T_float) { - return GL_RGB16F; - } else { + switch (tex->get_component_type()) { + case Texture::T_float: return GL_RGB16F; +#ifndef OPENGLES + case Texture::T_unsigned_short: return GL_RGB16; + case Texture::T_short: return GL_RGB16_SNORM; + case Texture::T_byte: return GL_RGB8_SNORM; +#endif + default: return force_sized ? GL_RGB8 : GL_RGB; } @@ -8513,14 +8553,20 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return GL_RGB16F; #else case Texture::F_rgb8: - return GL_RGB8; + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_RGB8; + } else { + return GL_RGB8_SNORM; + } case Texture::F_rgb12: return GL_RGB12; case Texture::F_rgb16: if (tex->get_component_type() == Texture::T_float) { return GL_RGB16F; - } else { + } else if (Texture::is_unsigned(tex->get_component_type())) { return GL_RGB16; + } else { + return GL_RGB16_SNORM; } #endif // OPENGLES case Texture::F_rgb32: @@ -8540,14 +8586,18 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_r16: if (tex->get_component_type() == Texture::T_float) { return GL_R16F; - } else { + } else if (Texture::is_unsigned(tex->get_component_type())) { return GL_R16; + } else { + return GL_R16_SNORM; } case Texture::F_rg16: if (tex->get_component_type() == Texture::T_float) { return GL_RG16F; - } else { + } else if (Texture::is_unsigned(tex->get_component_type())) { return GL_RG16; + } else { + return GL_RG16_SNORM; } #endif @@ -8560,7 +8610,14 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_red: case Texture::F_green: case Texture::F_blue: - return force_sized ? GL_R8 : GL_RED; +#ifndef OPENGLES + if (!Texture::is_unsigned(tex->get_component_type())) { + return GL_R8_SNORM; + } else +#endif + { + return force_sized ? GL_R8 : GL_RED; + } #endif case Texture::F_alpha: @@ -8574,6 +8631,8 @@ get_internal_image_format(Texture *tex, bool force_sized) const { #ifndef OPENGLES if (tex->get_component_type() == Texture::T_float) { return GL_LUMINANCE16F_ARB; + } else if (tex->get_component_type() == Texture::T_short) { + return GL_LUMINANCE16_SNORM; } else if (tex->get_component_type() == Texture::T_unsigned_short) { return GL_LUMINANCE16; } else @@ -11710,6 +11769,31 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, return true; } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::generate_mipmaps +// Access: Protected +// Description: Causes mipmaps to be generated for an uploaded +// texture. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +generate_mipmaps(CLP(TextureContext) *gtc) { +#ifndef OPENGLES + if (_glGenerateTextureMipmap != NULL) { + // OpenGL 4.5 offers an easy way to do this without binding. + _glGenerateTextureMipmap(gtc->_index); + return; + } +#endif + + if (_glGenerateMipmap != NULL) { + _state_texture = 0; + update_texture(gtc, true); + apply_texture(gtc); + _glGenerateMipmap(gtc->_target); + glBindTexture(gtc->_target, 0); + } +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::upload_simple_texture // Access: Protected @@ -12117,15 +12201,19 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { break; case GL_R8I: + type = Texture::T_byte; format = Texture::F_r8i; break; case GL_RG8I: + type = Texture::T_byte; format = Texture::F_rg8i; break; case GL_RGB8I: + type = Texture::T_byte; format = Texture::F_rgb8i; break; case GL_RGBA8I: + type = Texture::T_byte; format = Texture::F_rgba8i; break; @@ -12195,6 +12283,19 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { type = Texture::T_unsigned_short; format = Texture::F_r16; break; + + case GL_RGB16_SNORM: + type = Texture::T_short; + format = Texture::F_rgb16; + break; + case GL_RG16_SNORM: + type = Texture::T_short; + format = Texture::F_rg16; + break; + case GL_R16_SNORM: + type = Texture::T_short; + format = Texture::F_r16; + break; #endif #ifndef OPENGLES diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 62df6fe84c..7d5f796140 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -546,6 +546,7 @@ protected: GLenum component_type, bool one_page_only, int z, Texture::CompressionMode image_compression); + void generate_mipmaps(CLP(TextureContext) *gtc); bool upload_simple_texture(CLP(TextureContext) *gtc); size_t get_texture_memory_size(CLP(TextureContext) *gtc); @@ -794,6 +795,10 @@ public: PFNGLGENERATEMIPMAPEXTPROC _glGenerateMipmap; PFNGLBINDPROGRAMARBPROC _glBindProgram; +#ifndef OPENGLES + PFNGLGENERATETEXTUREMIPMAPPROC _glGenerateTextureMipmap; +#endif + bool _supports_framebuffer_multisample; bool _supports_framebuffer_multisample_coverage_nv; INLINE bool get_supports_framebuffer_multisample(); diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index f355f2ffda..08ef11b2a5 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -2479,6 +2479,15 @@ glsl_report_program_errors(GLuint program, bool fatal) { //////////////////////////////////////////////////////////////////// bool CLP(ShaderContext):: glsl_compile_shader(Shader::ShaderType type) { + static const char *types[] = {"", "vertex ", "fragment ", "geometry ", + "tessellation control ", "tessellation evaluation ", "compute ", ""}; + + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Compiling GLSL " << types[type] << "shader " + << _shader->get_filename(type) << "\n"; + } + GLuint handle = 0; switch (type) { case Shader::ST_vertex: @@ -2514,7 +2523,7 @@ glsl_compile_shader(Shader::ShaderType type) { } if (!handle) { GLCAT.error() - << "Could not create a GLSL shader of the requested type.\n"; + << "Could not create a GLSL " << types[type] << "shader.\n"; _glgsg->report_my_gl_errors(); return false; } @@ -2533,8 +2542,8 @@ glsl_compile_shader(Shader::ShaderType type) { if (status != GL_TRUE) { GLCAT.error() - << "An error occurred while compiling GLSL shader " - << _shader->get_filename(type) << ":\n"; + << "An error occurred while compiling GLSL " << types[type] + << "shader " << _shader->get_filename(type) << ":\n"; glsl_report_shader_errors(handle, type, true); _glgsg->_glDeleteShader(handle); _glgsg->report_my_gl_errors(); @@ -2629,12 +2638,18 @@ glsl_compile_and_link() { } #endif + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Linking GLSL shader " << _shader->get_filename() << "\n"; + } + _glgsg->_glLinkProgram(_glsl_program); GLint status; _glgsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status); if (status != GL_TRUE) { - GLCAT.error() << "An error occurred while linking GLSL shader program!\n"; + GLCAT.error() << "An error occurred while linking GLSL shader " + << _shader->get_filename() << "\n"; glsl_report_program_errors(_glsl_program, true); return false; } diff --git a/panda/src/glstuff/glTextureContext_src.cxx b/panda/src/glstuff/glTextureContext_src.cxx index 470692d6bb..3238ae5a30 100644 --- a/panda/src/glstuff/glTextureContext_src.cxx +++ b/panda/src/glstuff/glTextureContext_src.cxx @@ -23,15 +23,6 @@ TypeHandle CLP(TextureContext)::_type_handle; //////////////////////////////////////////////////////////////////// CLP(TextureContext):: ~CLP(TextureContext)() { -#ifndef OPENGLES - if (gl_enable_memory_barriers) { - _glgsg->_textures_needing_fetch_barrier.erase(this); - _glgsg->_textures_needing_image_access_barrier.erase(this); - _glgsg->_textures_needing_update_barrier.erase(this); - _glgsg->_textures_needing_framebuffer_barrier.erase(this); - } -#endif - // Don't call glDeleteTextures; we may not have an active context. } diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 5f54059fbb..b26c4ebca9 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -1552,10 +1552,12 @@ write(ostream &out, int indent_level) const { switch (cdata->_component_type) { case T_unsigned_byte: + case T_byte: out << " bytes"; break; case T_unsigned_short: + case T_short: out << " shorts"; break; @@ -2001,6 +2003,10 @@ format_component_type(ComponentType ct) { return "unsigned_int_24_8"; case T_int: return "int"; + case T_byte: + return "unsigned_byte"; + case T_short: + return "short"; } return "**invalid**"; @@ -2024,6 +2030,10 @@ string_component_type(const string &str) { return T_unsigned_int_24_8; } else if (cmp_nocase(str, "int") == 0) { return T_int; + } else if (cmp_nocase(str, "byte") == 0) { + return T_byte; + } else if (cmp_nocase(str, "short") == 0) { + return T_short; } gobj_cat->error() @@ -2411,6 +2421,19 @@ make_texture() { return new Texture; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::is_unsigned +// Access: Public, Static +// Description: Returns true if the indicated component type is +// unsigned, false otherwise. +//////////////////////////////////////////////////////////////////// +bool Texture:: +is_unsigned(Texture::ComponentType ctype) { + return (ctype == T_unsigned_byte || + ctype == T_unsigned_short || + ctype == T_unsigned_int_24_8); +} + //////////////////////////////////////////////////////////////////// // Function: Texture::is_specific // Access: Public, Static @@ -4525,6 +4548,48 @@ do_get_clear_data(const CData *cdata, unsigned char *into) const { } break; } + + case T_byte: + { + LColor scaled = cdata->_clear_color.fmin(LColor(1)).fmax(LColor(-1)); + scaled *= 127; + switch (cdata->_num_components) { + case 2: + into[1] = (char)scaled[1]; + case 1: + into[0] = (char)scaled[0]; + break; + case 4: + into[3] = (char)scaled[3]; + case 3: // BGR <-> RGB + into[0] = (char)scaled[2]; + into[1] = (char)scaled[1]; + into[2] = (char)scaled[0]; + break; + } + break; + } + + case T_short: + { + LColor scaled = cdata->_clear_color.fmin(LColor(1)).fmax(LColor(-1)); + scaled *= 32767; + switch (cdata->_num_components) { + case 2: + ((short *)into)[1] = (short)scaled[1]; + case 1: + ((short *)into)[0] = (short)scaled[0]; + break; + case 4: + ((short *)into)[3] = (short)scaled[3]; + case 3: // BGR <-> RGB + ((short *)into)[0] = (short)scaled[2]; + ((short *)into)[1] = (short)scaled[1]; + ((short *)into)[2] = (short)scaled[0]; + break; + } + break; + } } return cdata->_num_components * cdata->_component_width; @@ -5222,10 +5287,12 @@ do_set_component_type(CData *cdata, Texture::ComponentType component_type) { switch (component_type) { case T_unsigned_byte: + case T_byte: cdata->_component_width = 1; break; case T_unsigned_short: + case T_short: cdata->_component_width = 2; break; diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index fff5770693..3ab9d33f02 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -93,6 +93,8 @@ PUBLISHED: T_float, T_unsigned_int_24_8, // Packed T_int, + T_byte, + T_short, }; enum Format { @@ -527,6 +529,7 @@ public: static PT(Texture) make_texture(); public: + static bool is_unsigned(ComponentType ctype); static bool is_specific(CompressionMode compression); static bool has_alpha(Format format); static bool has_binary_alpha(Format format); diff --git a/panda/src/text/textAssembler.cxx b/panda/src/text/textAssembler.cxx index 609ea8c676..99db6b28b4 100644 --- a/panda/src/text/textAssembler.cxx +++ b/panda/src/text/textAssembler.cxx @@ -587,33 +587,16 @@ assemble_text() { if (placement->_properties != properties) { // Get a new set of properties for future glyphs. properties = placement->_properties; - text_state = RenderState::make_empty(); - shadow_state = RenderState::make_empty(); + text_state = properties->get_text_state(); shadow_xform = LMatrix4::ident_mat(); - if (properties->has_text_color()) { - text_state = text_state->add_attrib(ColorAttrib::make_flat(properties->get_text_color())); - if (properties->get_text_color()[3] != 1.0) { - text_state = text_state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha)); - } - } - - if (properties->has_bin()) { - text_state = text_state->add_attrib(CullBinAttrib::make(properties->get_bin(), properties->get_draw_order() + 2)); - } - if (properties->has_shadow()) { - shadow_state = shadow_state->add_attrib(ColorAttrib::make_flat(properties->get_shadow_color())); - if (properties->get_shadow_color()[3] != 1.0) { - shadow_state = shadow_state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha)); - } - - if (properties->has_bin()) { - shadow_state = shadow_state->add_attrib(CullBinAttrib::make(properties->get_bin(), properties->get_draw_order() + 1)); - } + shadow_state = properties->get_shadow_state(); LVector2 offset = properties->get_shadow(); shadow_xform = LMatrix4::translate_mat(offset[0], 0.0f, -offset[1]); + } else { + shadow_state.clear(); } } diff --git a/panda/src/text/textProperties.I b/panda/src/text/textProperties.I index 05c3521b05..0adeb553b0 100644 --- a/panda/src/text/textProperties.I +++ b/panda/src/text/textProperties.I @@ -550,6 +550,7 @@ INLINE void TextProperties:: set_text_color(const LColor &text_color) { _text_color = text_color; _specified |= F_has_text_color; + _text_state.clear(); } //////////////////////////////////////////////////////////////////// @@ -562,6 +563,7 @@ INLINE void TextProperties:: clear_text_color() { _text_color.set(1.0f, 1.0f, 1.0f, 1.0f); _specified &= ~F_has_text_color; + _text_state.clear(); } //////////////////////////////////////////////////////////////////// @@ -603,6 +605,7 @@ INLINE void TextProperties:: set_shadow_color(const LColor &shadow_color) { _shadow_color = shadow_color; _specified |= F_has_shadow_color; + _shadow_state.clear(); } //////////////////////////////////////////////////////////////////// @@ -614,6 +617,7 @@ INLINE void TextProperties:: clear_shadow_color() { _shadow_color.set(0.0f, 0.0f, 0.0f, 1.0f); _specified &= ~F_has_shadow_color; + _shadow_state.clear(); } //////////////////////////////////////////////////////////////////// @@ -711,6 +715,8 @@ INLINE void TextProperties:: set_bin(const string &bin) { _bin = bin; _specified |= F_has_bin; + _text_state.clear(); + _shadow_state.clear(); } //////////////////////////////////////////////////////////////////// @@ -725,6 +731,8 @@ INLINE void TextProperties:: clear_bin() { _bin = string(); _specified &= ~F_has_bin; + _text_state.clear(); + _shadow_state.clear(); } //////////////////////////////////////////////////////////////////// @@ -768,6 +776,8 @@ INLINE int TextProperties:: set_draw_order(int draw_order) { _draw_order = draw_order; _specified |= F_has_draw_order; + _text_state.clear(); + _shadow_state.clear(); return _draw_order + 3; } @@ -780,6 +790,8 @@ INLINE void TextProperties:: clear_draw_order() { _draw_order = 1; _specified &= ~F_has_draw_order; + _text_state.clear(); + _shadow_state.clear(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/text/textProperties.cxx b/panda/src/text/textProperties.cxx index ae764288dd..116a4309aa 100644 --- a/panda/src/text/textProperties.cxx +++ b/panda/src/text/textProperties.cxx @@ -19,6 +19,9 @@ #include "staticTextFont.h" #include "bamFile.h" #include "fontPool.h" +#include "colorAttrib.h" +#include "cullBinAttrib.h" +#include "transparencyAttrib.h" PT(TextFont) TextProperties::_default_font; bool TextProperties::_loaded_default_font = false; @@ -61,6 +64,8 @@ TextProperties() { TextProperties:: TextProperties(const TextProperties ©) { (*this) = copy; + _text_state = copy._text_state; + _shadow_state = copy._shadow_state; } //////////////////////////////////////////////////////////////////// @@ -91,6 +96,9 @@ operator = (const TextProperties ©) { _glyph_scale = copy._glyph_scale; _glyph_shift = copy._glyph_shift; _text_scale = copy._text_scale; + + _text_state.clear(); + _shadow_state.clear(); } //////////////////////////////////////////////////////////////////// @@ -372,6 +380,62 @@ write(ostream &out, int indent_level) const { } } +//////////////////////////////////////////////////////////////////// +// Function: TextProperties::get_text_state +// Access: Public +// Description: Returns a RenderState object suitable for rendering +// text with these properties. +//////////////////////////////////////////////////////////////////// +const RenderState *TextProperties:: +get_text_state() const { + if (!_text_state.is_null()) { + return _text_state; + } + + CPT(RenderState) state = RenderState::make_empty(); + + if (has_text_color()) { + state = state->add_attrib(ColorAttrib::make_flat(get_text_color())); + if (get_text_color()[3] != 1.0) { + state = state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha)); + } + } + + if (has_bin()) { + state = state->add_attrib(CullBinAttrib::make(get_bin(), get_draw_order() + 2)); + } + + swap(_text_state, state); + return _text_state; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextProperties::get_shadow_state +// Access: Public +// Description: Returns a RenderState object suitable for rendering +// the shadow of this text with these properties. +//////////////////////////////////////////////////////////////////// +const RenderState *TextProperties:: +get_shadow_state() const { + if (!_shadow_state.is_null()) { + return _shadow_state; + } + + CPT(RenderState) state = RenderState::make_empty(); + + state = state->add_attrib(ColorAttrib::make_flat(get_shadow_color())); + if (get_shadow_color()[3] != 1.0) { + state = state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha)); + } + + if (has_bin()) { + state = state->add_attrib(CullBinAttrib::make(get_bin(), get_draw_order() + 1)); + } + + swap(_shadow_state, state); + return _shadow_state; +} + //////////////////////////////////////////////////////////////////// // Function: TextProperties::load_default_font // Access: Private, Static diff --git a/panda/src/text/textProperties.h b/panda/src/text/textProperties.h index 68710bbbba..e3478d41fa 100644 --- a/panda/src/text/textProperties.h +++ b/panda/src/text/textProperties.h @@ -21,6 +21,7 @@ #include "luse.h" #include "textFont.h" #include "pointerTo.h" +#include "renderState.h" //////////////////////////////////////////////////////////////////// // Class : TextProperties @@ -169,6 +170,10 @@ PUBLISHED: void write(ostream &out, int indent_level = 0) const; +public: + const RenderState *get_text_state() const; + const RenderState *get_shadow_state() const; + private: static void load_default_font(); @@ -216,6 +221,9 @@ private: PN_stdfloat _glyph_shift; PN_stdfloat _text_scale; + mutable CPT(RenderState) _text_state; + mutable CPT(RenderState) _shadow_state; + static PT(TextFont) _default_font; static bool _loaded_default_font;