Merge branch 'master' into cmake

This commit is contained in:
Sam Edwards 2014-09-22 21:13:05 -07:00
commit 57fb97053b
159 changed files with 6654 additions and 5201 deletions

View File

@ -29,13 +29,7 @@
// on the mesh.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAAI AINode {
PUBLISHED:
// This variable specifies whether the node is an obtacle or not.
// Used for dynamic obstacle addition to the environment.
// obstacle = false
// navigational = true
bool _type;
public:
// This variable specifies the node status whether open, close
// or neutral.
// open = belongs to _open_list.
@ -48,6 +42,12 @@ PUBLISHED:
};
Status _status;
// This variable specifies whether the node is an obtacle or not.
// Used for dynamic obstacle addition to the environment.
// obstacle = false
// navigational = true
bool _type;
// The score is used to compute the traversal expense to nodes
// when using A*.
// _score = _cost + heuristic
@ -76,6 +76,7 @@ PUBLISHED:
// is written into navmesh.csv file.
AINode *_next;
PUBLISHED:
AINode(int grid_x, int grid_y, LVecBase3f pos, float w, float l, float h);
~AINode();

View File

@ -176,7 +176,7 @@ QT_AUTOBRIEF = YES
# The new default is to treat a multi-line C++ comment block as a detailed
# description. Set this tag to YES if you prefer the old behaviour instead.
MULTILINE_CPP_IS_BRIEF = NO
MULTILINE_CPP_IS_BRIEF = YES
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
@ -612,8 +612,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = pandadoc.hpp \
direct
INPUT = pandadoc.hpp built/direct
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@ -644,7 +643,15 @@ RECURSIVE = YES
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE = direct/src/test
EXCLUDE = built/direct/test \
built/direct/plugin \
built/direct/plugin_npapi \
built/direct/plugin_activex \
built/direct/plugin_installer \
built/direct/plugin_standalone \
built/direct/extensions \
built/direct/extensions_native \
built/direct/directscripts
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded

View File

@ -17,15 +17,34 @@ 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.\"""".split("\n")
libraries = {}
for m, lib in panda3d.modules.items():
if not isinstance(lib, str):
for l in lib:
libraries[l.replace("lib", "")] = m
else:
libraries[lib.replace("lib", "")] = m
def comment(code):
if not code:
return ""
comment = ''
empty_line = False
for line in code.splitlines(False):
line = line.strip('\t\n /')
if line:
if empty_line:
# New paragraph.
comment += '\n\n'
elif comment:
comment += '\n'
comment += '/// ' + line
else:
empty_line = True
if comment:
return comment
else:
return ''
def block_comment(code):
if not code:
return ""
lines = code.split("\n")
newlines = []
indent = 0
@ -38,18 +57,18 @@ def comment(code):
line = line.rstrip()
strline = line.lstrip('/ \t')
if reading_desc:
newlines.append(line[min(indent, len(line) - len(strline)):])
newlines.append('/// ' + line[min(indent, len(line) - len(strline)):])
else:
# A "Description:" text starts the description.
if strline.startswith("Description"):
strline = strline[11:].lstrip(': \t')
indent = len(line) - len(strline)
reading_desc = True
newlines.append(strline)
newlines.append('/// ' + strline)
newcode = "\n".join(newlines)
newcode = '\n'.join(newlines)
if len(newcode) > 0:
return "/** " + newcode + " */"
return newcode
else:
return ""
@ -67,6 +86,11 @@ def translateFunctionName(name):
return new
def translated_type_name(type):
if interrogate_type_is_atomic(type):
token = interrogate_type_atomic_token(type)
if token == 7:
return 'str'
typename = interrogate_type_name(type)
typename = typename.replace("< ", "").replace(" >", "")
return typename
@ -76,13 +100,24 @@ def translateTypeSpec(name):
name = name.replace("BitMask< unsigned int, 32 >", "BitMask32")
name = name.replace("atomic ", "")
name = name.replace("< ", "").replace(" >", "")
if name == '_object':
name = 'object'
elif name == '_typeobject':
name = 'type'
return name
def processElement(handle, element):
if interrogate_element_has_comment(element):
print >>handle, comment(interrogate_element_comment(element))
print >>handle, translateTypeSpec(translated_type_name(interrogate_element_type(element))),
print >>handle, interrogate_element_name(element) + ';'
def processFunction(handle, function, isConstructor = False):
for i_wrapper in xrange(interrogate_function_number_of_python_wrappers(function)):
wrapper = interrogate_function_python_wrapper(function, i_wrapper)
if interrogate_wrapper_has_comment(wrapper):
print >>handle, comment(interrogate_wrapper_comment(wrapper))
print >>handle, block_comment(interrogate_wrapper_comment(wrapper))
if not isConstructor:
if not interrogate_wrapper_number_of_parameters(wrapper) > 0 or not interrogate_wrapper_parameter_is_this(wrapper, 0):
@ -114,11 +149,14 @@ def processType(handle, type):
derivations = [ translated_type_name(interrogate_type_get_derivation(type, n)) for n in range(interrogate_type_number_of_derivations(type)) ]
if interrogate_type_has_comment(type):
print >>handle, comment(interrogate_type_comment(type))
print >>handle, block_comment(interrogate_type_comment(type))
if interrogate_type_is_enum(type):
print >>handle, "enum %s {" % typename
for i_value in range(interrogate_type_number_of_enum_values(type)):
docstring = comment(interrogate_type_enum_value_comment(type, i_value))
if docstring:
print >>handle, docstring
print >>handle, translateFunctionName(interrogate_type_enum_value_name(type, i_value)), "=", interrogate_type_enum_value(type, i_value), ","
else:
if interrogate_type_is_struct(type):
@ -148,6 +186,9 @@ def processType(handle, type):
for i_method in xrange(interrogate_type_number_of_make_seqs(type)):
print >>handle, "list", translateFunctionName(interrogate_make_seq_seq_name(interrogate_type_get_make_seq(type, i_method))), "();"
for i_element in xrange(interrogate_type_number_of_elements(type)):
processElement(handle, interrogate_type_get_element(type, i_element))
print >>handle, "};"
@ -161,20 +202,22 @@ if __name__ == "__main__":
interrogate_add_search_directory(os.path.join(os.path.dirname(pandac.__file__), "..", "..", "etc"))
interrogate_add_search_directory(os.path.join(os.path.dirname(pandac.__file__), "input"))
try:
panda3d.__load__()
except ImportError, msg:
print msg
import panda3d.core
for lib in os.listdir(os.path.dirname(panda3d.__file__)):
if lib.endswith(('.pyd', '.so')) and not lib.startswith('core.'):
__import__('panda3d.' + os.path.splitext(lib)[0])
lastpkg = None
for i_type in xrange(interrogate_number_of_global_types()):
type = interrogate_get_global_type(i_type)
if interrogate_type_has_module_name(type):
package = libraries[interrogate_type_module_name(type)]
package = interrogate_type_module_name(type)
if lastpkg != package:
print >>handle, "}"
print >>handle, "namespace panda3d.%s {" % package
if lastpkg is not None:
print >>handle, "}"
print >>handle, "namespace %s {" % package
lastpkg = package
processType(handle, type)
@ -184,4 +227,3 @@ if __name__ == "__main__":
if lastpkg is not None:
print >>handle, "}"
handle.close()

View File

@ -39,6 +39,60 @@ float cartoon_thresh = saturate(dot(cartoon_mx - cartoon_mn, float4(3,3,0,0)) -
o_color = lerp(o_color, k_cartooncolor, cartoon_thresh);
"""
# Some GPUs do not support variable-length loops.
#
# We fill in the actual value of numsamples in the loop limit
# when the shader is configured.
#
SSAO_BODY="""//Cg
void vshader(float4 vtx_position : POSITION,
out float4 l_position : POSITION,
out float2 l_texcoord : TEXCOORD0,
out float2 l_texcoordD : TEXCOORD1,
out float2 l_texcoordN : TEXCOORD2,
uniform float4 texpad_depth,
uniform float4 texpad_normal,
uniform float4x4 mat_modelproj)
{
l_position = mul(mat_modelproj, vtx_position);
l_texcoord = vtx_position.xz;
l_texcoordD = (vtx_position.xz * texpad_depth.xy) + texpad_depth.xy;
l_texcoordN = (vtx_position.xz * texpad_normal.xy) + texpad_normal.xy;
}
float3 sphere[16] = float3[](float3(0.53812504, 0.18565957, -0.43192),float3(0.13790712, 0.24864247, 0.44301823),float3(0.33715037, 0.56794053, -0.005789503),float3(-0.6999805, -0.04511441, -0.0019965635),float3(0.06896307, -0.15983082, -0.85477847),float3(0.056099437, 0.006954967, -0.1843352),float3(-0.014653638, 0.14027752, 0.0762037),float3(0.010019933, -0.1924225, -0.034443386),float3(-0.35775623, -0.5301969, -0.43581226),float3(-0.3169221, 0.106360726, 0.015860917),float3(0.010350345, -0.58698344, 0.0046293875),float3(-0.08972908, -0.49408212, 0.3287904),float3(0.7119986, -0.0154690035, -0.09183723),float3(-0.053382345, 0.059675813, -0.5411899),float3(0.035267662, -0.063188605, 0.54602677),float3(-0.47761092, 0.2847911, -0.0271716));
void fshader(out float4 o_color : COLOR,
uniform float4 k_params1,
uniform float4 k_params2,
float2 l_texcoord : TEXCOORD0,
float2 l_texcoordD : TEXCOORD1,
float2 l_texcoordN : TEXCOORD2,
uniform sampler2D k_random : TEXUNIT0,
uniform sampler2D k_depth : TEXUNIT1,
uniform sampler2D k_normal : TEXUNIT2)
{
float pixel_depth = tex2D(k_depth, l_texcoordD).a;
float3 pixel_normal = (tex2D(k_normal, l_texcoordN).xyz * 2.0 - 1.0);
float3 random_vector = normalize((tex2D(k_random, l_texcoord * 18.0 + pixel_depth + pixel_normal.xy).xyz * 2.0) - float3(1.0)).xyz;
float occlusion = 0.0;
float radius = k_params1.z / pixel_depth;
float depth_difference;
float3 sample_normal;
float3 ray;
for(int i = 0; i < %d; ++i) {
ray = radius * reflect(sphere[i], random_vector);
sample_normal = (tex2D(k_normal, l_texcoordN + ray.xy).xyz * 2.0 - 1.0);
depth_difference = (pixel_depth - tex2D(k_depth,l_texcoordD + ray.xy).r);
occlusion += step(k_params2.y, depth_difference) * (1.0 - dot(sample_normal.xyz, pixel_normal)) * (1.0 - smoothstep(k_params2.y, k_params2.x, depth_difference));
}
o_color.rgb = 1.0 + (occlusion * k_params1.y);
o_color.a = 1.0;
}
"""
class FilterConfig:
pass
@ -140,7 +194,7 @@ class CommonFilters:
self.ssao[0].setShaderInput("depth", self.textures["depth"])
self.ssao[0].setShaderInput("normal", self.textures["aux"])
self.ssao[0].setShaderInput("random", loader.loadTexture("maps/random.rgb"))
self.ssao[0].setShader(self.loadShader("filter-ssao.sha"))
self.ssao[0].setShader(Shader.make(SSAO_BODY % configuration["AmbientOcclusion"].numsamples))
self.ssao[1].setShaderInput("src", ssao0)
self.ssao[1].setShader(self.loadShader("filter-blurx.sha"))
self.ssao[2].setShaderInput("src", ssao1)
@ -431,6 +485,10 @@ class CommonFilters:
def setAmbientOcclusion(self, numsamples = 16, radius = 0.05, amount = 2.0, strength = 0.01, falloff = 0.000002):
fullrebuild = (("AmbientOcclusion" in self.configuration) == False)
if (not fullrebuild):
fullrebuild = (numsamples != self.configuration["AmbientOcclusion"].numsamples)
newconfig = FilterConfig()
newconfig.numsamples = numsamples
newconfig.radius = radius

View File

@ -42,18 +42,18 @@ class FilterManager(DirectObject):
# Create the notify category
if (FilterManager.notify == None):
if FilterManager.notify is None:
FilterManager.notify = directNotify.newCategory("FilterManager")
# Find the appropriate display region.
region = None
for i in range(win.getNumDisplayRegions()):
dr = win.getDisplayRegion(i)
for dr in win.getDisplayRegions():
drcam = dr.getCamera()
if (drcam == cam): region=dr
if drcam == cam:
region = dr
if (region == None):
if region is None:
self.notify.error('Could not find appropriate DisplayRegion to filter')
return False
@ -218,16 +218,18 @@ class FilterManager(DirectObject):
self.region.setCamera(quadcam)
dr = buffer.getDisplayRegion(0)
self.setStackedClears(dr, self.rclears, self.wclears)
self.setStackedClears(buffer, self.rclears, self.wclears)
if (auxtex0):
dr.setClearActive(GraphicsOutput.RTPAuxRgba0, 1)
dr.setClearValue(GraphicsOutput.RTPAuxRgba0, Vec4(0.5, 0.5, 1.0, 0.0))
buffer.setClearActive(GraphicsOutput.RTPAuxRgba0, 1)
buffer.setClearValue(GraphicsOutput.RTPAuxRgba0, Vec4(0.5, 0.5, 1.0, 0.0))
if (auxtex1):
dr.setClearActive(GraphicsOutput.RTPAuxRgba1, 1)
buffer.setClearActive(GraphicsOutput.RTPAuxRgba1, 1)
self.region.disableClears()
if (self.isFullscreen()):
self.win.disableClears()
dr = buffer.makeDisplayRegion()
dr.disableClears()
dr.setCamera(self.camera)
dr.setActive(1)
@ -249,7 +251,7 @@ class FilterManager(DirectObject):
winx, winy = self.getScaledSize(mul, div, align)
depthbits = bool(depthtex != None)
buffer = self.createBuffer("filter-stage", winx, winy, texgroup, depthbits)
if (buffer == None):
@ -269,9 +271,18 @@ class FilterManager(DirectObject):
lens.setNearFar(-1000, 1000)
quadcamnode.setLens(lens)
quadcam = quad.attachNewNode(quadcamnode)
buffer.getDisplayRegion(0).setCamera(quadcam)
buffer.getDisplayRegion(0).setActive(1)
dr = buffer.makeDisplayRegion((0, 1, 0, 1))
dr.disableClears()
dr.setCamera(quadcam)
dr.setActive(True)
dr.setScissorEnabled(False)
# This clear stage is important if the buffer is padded, so that
# any pixels accidentally sampled in the padded region won't
# be reading from unititialised memory.
buffer.setClearColor((0, 0, 0, 1))
buffer.setClearColorActive(True)
self.buffers.append(buffer)
self.sizes.append((mul, div, align))
@ -283,7 +294,8 @@ class FilterManager(DirectObject):
winprops = WindowProperties()
winprops.setSize(xsize, ysize)
props = FrameBufferProperties()
props = FrameBufferProperties(self.win.getFbProperties())
props.setBackBuffers(0)
props.setRgbColor(1)
props.setDepthBits(depthbits)
depthtex, colortex, auxtex0, auxtex1 = texgroup
@ -307,7 +319,6 @@ class FilterManager(DirectObject):
buffer.addRenderTexture(auxtex1, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPAuxRgba1)
buffer.setSort(self.nextsort)
buffer.disableClears()
buffer.getDisplayRegion(0).disableClears()
self.nextsort += 1
return buffer
@ -339,4 +350,3 @@ class FilterManager(DirectObject):
self.nextsort = self.win.getSort() - 1000
self.basex = 0
self.basey = 0

View File

@ -1,48 +0,0 @@
//Cg
void vshader(float4 vtx_position : POSITION,
out float4 l_position : POSITION,
out float2 l_texcoord : TEXCOORD0,
out float2 l_texcoordD : TEXCOORD1,
out float2 l_texcoordN : TEXCOORD2,
uniform float4 texpad_depth,
uniform float4 texpad_normal,
uniform float4x4 mat_modelproj)
{
l_position = mul(mat_modelproj, vtx_position);
l_texcoord = vtx_position.xz;
l_texcoordD = (vtx_position.xz * texpad_depth.xy) + texpad_depth.xy;
l_texcoordN = (vtx_position.xz * texpad_normal.xy) + texpad_normal.xy;
}
float3 sphere[16] = float3[](float3(0.53812504, 0.18565957, -0.43192),float3(0.13790712, 0.24864247, 0.44301823),float3(0.33715037, 0.56794053, -0.005789503),float3(-0.6999805, -0.04511441, -0.0019965635),float3(0.06896307, -0.15983082, -0.85477847),float3(0.056099437, 0.006954967, -0.1843352),float3(-0.014653638, 0.14027752, 0.0762037),float3(0.010019933, -0.1924225, -0.034443386),float3(-0.35775623, -0.5301969, -0.43581226),float3(-0.3169221, 0.106360726, 0.015860917),float3(0.010350345, -0.58698344, 0.0046293875),float3(-0.08972908, -0.49408212, 0.3287904),float3(0.7119986, -0.0154690035, -0.09183723),float3(-0.053382345, 0.059675813, -0.5411899),float3(0.035267662, -0.063188605, 0.54602677),float3(-0.47761092, 0.2847911, -0.0271716));
void fshader(out float4 o_color : COLOR,
uniform float4 k_params1,
uniform float4 k_params2,
float2 l_texcoord : TEXCOORD0,
float2 l_texcoordD : TEXCOORD1,
float2 l_texcoordN : TEXCOORD2,
uniform sampler2D k_random : TEXUNIT0,
uniform sampler2D k_depth : TEXUNIT1,
uniform sampler2D k_normal : TEXUNIT2)
{
float pixel_depth = tex2D(k_depth, l_texcoordD).a;
float3 pixel_normal = (tex2D(k_normal, l_texcoordN).xyz * 2.0 - 1.0);
float3 random_vector = normalize((tex2D(k_random, l_texcoord * 18.0 + pixel_depth + pixel_normal.xy).xyz * 2.0) - float3(1.0)).xyz;
float occlusion = 0.0;
float radius = k_params1.z / pixel_depth;
float depth_difference;
float3 sample_normal;
float3 ray;
for(int i = 0; i < k_params1.x; ++i) {
ray = radius * reflect(sphere[i], random_vector);
sample_normal = (tex2D(k_normal, l_texcoordN + ray.xy).xyz * 2.0 - 1.0);
depth_difference = (pixel_depth - tex2D(k_depth,l_texcoordD + ray.xy).r);
occlusion += step(k_params2.y, depth_difference) * (1.0 - dot(sample_normal.xyz, pixel_normal)) * (1.0 - smoothstep(k_params2.y, k_params2.x, depth_difference));
}
o_color.rgb = 1.0 + (occlusion * k_params1.y);
o_color.a = 1.0;
}

View File

@ -114,7 +114,7 @@ enable (bool enable) {
// Description: Set the GeomNode.
////////////////////////////////////////////////////////////////////
void CMotionTrail::
set_geom_node (PT(GeomNode) geom_node) {
set_geom_node (GeomNode *geom_node) {
_geom_node = geom_node;
}

View File

@ -24,7 +24,7 @@
#include "luse.h"
#include "nurbsCurveEvaluator.h"
#include "plist.h"
#include "pvector.h"
#include "epvector.h"
class CMotionTrailVertex {
public:
@ -32,7 +32,7 @@ public:
LVecBase4 _start_color;
LVecBase4 _end_color;
PN_stdfloat _v;
PT(NurbsCurveEvaluator) _nurbs_curve_evaluator;
};
@ -44,71 +44,68 @@ public:
////////////////////////////////////////////////////////////////////
// Class : CMotionTrail
// Description : The method used in creating the motion trail is
// based on taking samples of time and transformations
// Description : The method used in creating the motion trail is
// based on taking samples of time and transformations
// (the position and orientation matrix) in real-time.
// The method also requires a number of vertices
// (positions) that determines "shape" of the motion
// trail (i.e. the edge of a blade). A start color
// and end color is also required for each vertex.
// The method also requires a number of vertices
// (positions) that determines "shape" of the motion
// trail (i.e. the edge of a blade). A start color
// and end color is also required for each vertex.
// The color is interpolated as function of time.
// The colors are typically used to fade the motion
// trail so the end color is typically black.
//
// The vertices are submitted via the "add_vertex"
// function. For each frame, a sample is submited via
// the "update_motion_trail" function. During the
// "update_motion_trail" function, the motion trail
// geometry is created dynamically from the sample
// history and the vertices.
// The vertices are submitted via the "add_vertex"
// function. For each frame, a sample is submited via
// the "update_motion_trail" function. During the
// "update_motion_trail" function, the motion trail
// geometry is created dynamically from the sample
// history and the vertices.
//
// The user must specifiy a GeomNode via
// The user must specifiy a GeomNode via
// "set_geom_node".
//
// The duration of the sample history is specified by
// a time window. A larger time window creates longer
// motion trails (given constant speed). Samples that
// are no longer within the time window are
// The duration of the sample history is specified by
// a time window. A larger time window creates longer
// motion trails (given constant speed). Samples that
// are no longer within the time window are
// automatically discarded.
//
// The nurbs option can be used to create smooth
// interpolated curves from the samples. The nurbs
// option is useful for animations that lack sampling
// to begin with, animations that move very quickly,
// The nurbs option can be used to create smooth
// interpolated curves from the samples. The nurbs
// option is useful for animations that lack sampling
// to begin with, animations that move very quickly,
// or low frame rates.
//
// The texture option be used to create variation to
// the motion trail. The u coordinate of the texture
// corresponds to time and the v coordinate
// The texture option be used to create variation to
// the motion trail. The u coordinate of the texture
// corresponds to time and the v coordinate
// corresponds to the "shape" of the motion trail.
////////////////////////////////////////////////////////////////////
class EXPCL_DIRECT CMotionTrail : public TypedReferenceCount {
PUBLISHED:
CMotionTrail();
~CMotionTrail();
CMotionTrail ( );
~CMotionTrail ( );
void reset();
void reset_vertex_list();
void reset ( );
void reset_vertex_list ( );
void enable(bool enable);
void enable (bool enable);
void set_geom_node(GeomNode *geom_node);
void add_vertex(LVector4 *vertex, LVector4 *start_color, LVector4 *end_color, PN_stdfloat v);
void set_geom_node (PT(GeomNode) geom_node);
void add_vertex (LVector4 *vertex, LVector4 *start_color, LVector4 *end_color, PN_stdfloat v);
void set_parameters(PN_stdfloat sampling_time, PN_stdfloat time_window, bool use_texture, bool calculate_relative_matrix, bool use_nurbs, PN_stdfloat resolution_distance);
void set_parameters (PN_stdfloat sampling_time, PN_stdfloat time_window, bool use_texture, bool calculate_relative_matrix, bool use_nurbs, PN_stdfloat resolution_distance);
int check_for_update (PN_stdfloat current_time);
void update_motion_trail (PN_stdfloat current_time, LMatrix4 *transform);
int check_for_update(PN_stdfloat current_time);
void update_motion_trail(PN_stdfloat current_time, LMatrix4 *transform);
public:
void begin_geometry ( );
void add_geometry_quad (LVector3 &v0, LVector3 &v1, LVector3 &v2, LVector3 &v3, LVector4 &c0, LVector4 &c1, LVector4 &c2, LVector4 &c3, LVector2 &t0, LVector2 &t1, LVector2 &t2, LVector2 &t3);
void add_geometry_quad (LVector4 &v0, LVector4 &v1, LVector4 &v2, LVector4 &v3, LVector4 &c0, LVector4 &c1, LVector4 &c2, LVector4 &c3, LVector2 &t0, LVector2 &t1, LVector2 &t2, LVector2 &t3);
void end_geometry ( );
void begin_geometry();
void add_geometry_quad(LVector3 &v0, LVector3 &v1, LVector3 &v2, LVector3 &v3, LVector4 &c0, LVector4 &c1, LVector4 &c2, LVector4 &c3, LVector2 &t0, LVector2 &t1, LVector2 &t2, LVector2 &t3);
void add_geometry_quad(LVector4 &v0, LVector4 &v1, LVector4 &v2, LVector4 &v3, LVector4 &c0, LVector4 &c1, LVector4 &c2, LVector4 &c3, LVector2 &t0, LVector2 &t1, LVector2 &t2, LVector2 &t3);
void end_geometry();
int _active;
int _enable;
@ -143,14 +140,14 @@ public:
// geom
PT(GeomNode) _geom_node;
// real-time data
int _vertex_index;
PT(GeomVertexData) _vertex_data;
GeomVertexWriter _vertex_writer;
GeomVertexWriter _color_writer;
GeomVertexWriter _texture_writer;
PT(GeomTriangles) _triangles;
PT(GeomTriangles) _triangles;
CMotionTrailVertex *_vertex_array;

View File

@ -1,21 +0,0 @@
from pandac.PandaModules import HashVal
class FileSpec:
""" Used by make_package and make_contents. Represents a single
file in the directory, and its associated timestamp, size, and md5
hash. """
def __init__(self, filename, pathname):
self.filename = filename
self.pathname = pathname
self.size = pathname.getFileSize()
self.timestamp = pathname.getTimestamp()
hv = HashVal()
hv.hashFile(pathname)
self.hash = hv.asHex()
def getParams(self):
return 'filename="%s" size="%s" timestamp="%s" hash="%s"' % (
self.filename, self.size, self.timestamp, self.hash)

View File

@ -35,10 +35,6 @@
#include <afxcmn.h> // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
// Delete the two includes below if you do not wish to use the MFC
// database classes
#include <afxdb.h> // MFC database classes
#include <afxdao.h> // MFC DAO database classes
#include <afxwin.h>
#include <dispex.h>

View File

@ -441,7 +441,7 @@ def makeInstaller():
if not os.path.exists(dst_panda3dapp): os.makedirs(os.path.dirname(dst_panda3dapp))
shutil.copytree(pluginFiles[npapi], dst_npapi)
shutil.copyfile(pluginFiles[panda3d], dst_panda3d)
os.chmod(dst_panda3d, 0o755)
os.chmod(dst_panda3d, 493) # 0o755
shutil.copytree(pluginFiles[panda3dapp], dst_panda3dapp)
tmpresdir = tempfile.mktemp('', 'p3d-resources')

View File

@ -136,6 +136,7 @@ class TaskManager:
def destroy(self):
# This should be safe to call multiple times.
self.running = False
self.notify.info("TaskManager.destroy()")
self.destroyed = True
self._frameProfileQueue.clear()

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
cppExpressionParser.h cppExtensionType.h cppFile.h \
cppFunctionGroup.h cppFunctionType.h cppGlobals.h \
cppIdentifier.h cppInstance.h cppInstanceIdentifier.h \
cppMakeSeq.h cppManifest.h \
cppMakeProperty.h cppMakeSeq.h cppManifest.h \
cppNameComponent.h cppNamespace.h \
cppParameterList.h cppParser.h cppPointerType.h \
cppPreprocessor.h cppReferenceType.h cppScope.h \
@ -31,7 +31,7 @@
cppExtensionType.cxx cppFile.cxx cppFunctionGroup.cxx \
cppFunctionType.cxx cppGlobals.cxx cppIdentifier.cxx \
cppInstance.cxx cppInstanceIdentifier.cxx \
cppMakeSeq.cxx cppManifest.cxx \
cppMakeProperty.cxx cppMakeSeq.cxx cppManifest.cxx \
cppNameComponent.cxx cppNamespace.cxx cppParameterList.cxx \
cppParser.cxx cppPointerType.cxx cppPreprocessor.cxx \
cppReferenceType.cxx cppScope.cxx cppSimpleType.cxx \

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,8 @@
/* A Bison parser, made by GNU Bison 2.7. */
/* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton interface for Bison's Yacc-like parsers in C
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -32,6 +30,15 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
# define YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
/* Enabling traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
#if YYDEBUG
extern int cppyydebug;
#endif
/* Tokens. */
#ifndef YYTOKENTYPE
@ -79,35 +86,35 @@
XOREQUAL = 295,
LSHIFTEQUAL = 296,
RSHIFTEQUAL = 297,
TOKENPASTE = 298,
KW_BEGIN_PUBLISH = 299,
KW_BLOCKING = 300,
KW_BOOL = 301,
KW_CATCH = 302,
KW_CHAR = 303,
KW_WCHAR_T = 304,
KW_CLASS = 305,
KW_CONST = 306,
KW_DELETE = 307,
KW_DOUBLE = 308,
KW_DYNAMIC_CAST = 309,
KW_ELSE = 310,
KW_END_PUBLISH = 311,
KW_ENUM = 312,
KW_EXTENSION = 313,
KW_EXTERN = 314,
KW_EXPLICIT = 315,
KW_PUBLISHED = 316,
KW_FALSE = 317,
KW_FLOAT = 318,
KW_FRIEND = 319,
KW_FOR = 320,
KW_GOTO = 321,
KW_IF = 322,
KW_INLINE = 323,
KW_INT = 324,
KW_LONG = 325,
KW_LONGLONG = 326,
KW_BEGIN_PUBLISH = 298,
KW_BLOCKING = 299,
KW_BOOL = 300,
KW_CATCH = 301,
KW_CHAR = 302,
KW_WCHAR_T = 303,
KW_CLASS = 304,
KW_CONST = 305,
KW_DELETE = 306,
KW_DOUBLE = 307,
KW_DYNAMIC_CAST = 308,
KW_ELSE = 309,
KW_END_PUBLISH = 310,
KW_ENUM = 311,
KW_EXTENSION = 312,
KW_EXTERN = 313,
KW_EXPLICIT = 314,
KW_PUBLISHED = 315,
KW_FALSE = 316,
KW_FLOAT = 317,
KW_FRIEND = 318,
KW_FOR = 319,
KW_GOTO = 320,
KW_IF = 321,
KW_INLINE = 322,
KW_INT = 323,
KW_LONG = 324,
KW_LONGLONG = 325,
KW_MAKE_PROPERTY = 326,
KW_MAKE_SEQ = 327,
KW_MUTABLE = 328,
KW_NAMESPACE = 329,
@ -183,35 +190,35 @@
#define XOREQUAL 295
#define LSHIFTEQUAL 296
#define RSHIFTEQUAL 297
#define TOKENPASTE 298
#define KW_BEGIN_PUBLISH 299
#define KW_BLOCKING 300
#define KW_BOOL 301
#define KW_CATCH 302
#define KW_CHAR 303
#define KW_WCHAR_T 304
#define KW_CLASS 305
#define KW_CONST 306
#define KW_DELETE 307
#define KW_DOUBLE 308
#define KW_DYNAMIC_CAST 309
#define KW_ELSE 310
#define KW_END_PUBLISH 311
#define KW_ENUM 312
#define KW_EXTENSION 313
#define KW_EXTERN 314
#define KW_EXPLICIT 315
#define KW_PUBLISHED 316
#define KW_FALSE 317
#define KW_FLOAT 318
#define KW_FRIEND 319
#define KW_FOR 320
#define KW_GOTO 321
#define KW_IF 322
#define KW_INLINE 323
#define KW_INT 324
#define KW_LONG 325
#define KW_LONGLONG 326
#define KW_BEGIN_PUBLISH 298
#define KW_BLOCKING 299
#define KW_BOOL 300
#define KW_CATCH 301
#define KW_CHAR 302
#define KW_WCHAR_T 303
#define KW_CLASS 304
#define KW_CONST 305
#define KW_DELETE 306
#define KW_DOUBLE 307
#define KW_DYNAMIC_CAST 308
#define KW_ELSE 309
#define KW_END_PUBLISH 310
#define KW_ENUM 311
#define KW_EXTENSION 312
#define KW_EXTERN 313
#define KW_EXPLICIT 314
#define KW_PUBLISHED 315
#define KW_FALSE 316
#define KW_FLOAT 317
#define KW_FRIEND 318
#define KW_FOR 319
#define KW_GOTO 320
#define KW_IF 321
#define KW_INLINE 322
#define KW_INT 323
#define KW_LONG 324
#define KW_LONGLONG 325
#define KW_MAKE_PROPERTY 326
#define KW_MAKE_SEQ 327
#define KW_MUTABLE 328
#define KW_NAMESPACE 329
@ -247,15 +254,12 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
typedef struct YYLTYPE
{
@ -270,4 +274,18 @@ typedef struct YYLTYPE
#endif
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int cppyyparse (void *YYPARSE_PARAM);
#else
int cppyyparse ();
#endif
#else /* ! YYPARSE_PARAM */
#if defined __STDC__ || defined __cplusplus
int cppyyparse (void);
#else
int cppyyparse ();
#endif
#endif /* ! YYPARSE_PARAM */
#endif /* !YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED */

View File

@ -14,6 +14,7 @@
#include "cppEnumType.h"
#include "cppFunctionType.h"
#include "cppTBDType.h"
#include "cppMakeProperty.h"
#include "cppMakeSeq.h"
#include "cppParameterList.h"
#include "cppInstance.h"
@ -234,7 +235,6 @@ pop_struct() {
%token XOREQUAL
%token LSHIFTEQUAL
%token RSHIFTEQUAL
%token TOKENPASTE
%token KW_BEGIN_PUBLISH
%token KW_BLOCKING
@ -264,6 +264,7 @@ pop_struct() {
%token KW_INT
%token KW_LONG
%token KW_LONGLONG
%token KW_MAKE_PROPERTY
%token KW_MAKE_SEQ
%token KW_MUTABLE
%token KW_NAMESPACE
@ -475,7 +476,35 @@ declaration:
{
current_scope->set_current_vis(V_private);
}
| KW_MAKE_SEQ '(' name ',' name ',' name ')' ';'
| KW_MAKE_PROPERTY '(' IDENTIFIER ',' IDENTIFIER ')' ';'
{
CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @1);
}
CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(), NULL, current_scope, @1.file);
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
}
| KW_MAKE_PROPERTY '(' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
{
CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @1);
}
CPPDeclaration *setter = $7->find_symbol(current_scope, global_scope, current_lexer);
if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
yyerror("Reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @1);
}
CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(),
setter->as_function_group(),
current_scope, @1.file);
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
}
| KW_MAKE_SEQ '(' name ',' name ',' name ')' ';'
{
CPPMakeSeq *make_seq = new CPPMakeSeq($3->get_simple_name(), $5->get_simple_name(), $7->get_simple_name(), @1.file);
current_scope->add_declaration(make_seq, global_scope, current_lexer, @1);
@ -1828,32 +1857,34 @@ named_enum:
}
;
enum_body:
enum_body_trailing_comma:
empty
| enum_body_no_trailing_comma
| enum_body_no_trailing_comma ','
;
| enum_body_trailing_comma name ','
{
assert(current_enum != NULL);
CPPInstance *inst = current_enum->add_element($2->get_simple_name());
current_scope->add_enum_value(inst, current_lexer, @2);
}
| enum_body_trailing_comma name '=' const_expr ','
{
assert(current_enum != NULL);
CPPInstance *inst = current_enum->add_element($2->get_simple_name(), $4);
current_scope->add_enum_value(inst, current_lexer, @2);
};
enum_body_no_trailing_comma:
name
enum_body:
enum_body_trailing_comma
| enum_body_trailing_comma name
{
assert(current_enum != NULL);
current_enum->add_element($1->get_simple_name(), current_scope);
CPPInstance *inst = current_enum->add_element($2->get_simple_name());
current_scope->add_enum_value(inst, current_lexer, @2);
}
| name '=' const_expr
| enum_body_trailing_comma name '=' const_expr
{
assert(current_enum != NULL);
current_enum->add_element($1->get_simple_name(), current_scope, $3);
}
| enum_body_no_trailing_comma ',' name
{
assert(current_enum != NULL);
current_enum->add_element($3->get_simple_name(), current_scope);
}
| enum_body_no_trailing_comma ',' name '=' const_expr
{
assert(current_enum != NULL);
current_enum->add_element($3->get_simple_name(), current_scope, $5);
CPPInstance *inst = current_enum->add_element($2->get_simple_name(), $4);
current_scope->add_enum_value(inst, current_lexer, @2);
}
;
@ -2086,7 +2117,7 @@ element:
| KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC | KW_STATIC_CAST
| KW_STRUCT | KW_THROW | KW_TRUE | KW_TRY | KW_TYPEDEF | KW_TYPENAME
| KW_UNION | KW_UNSIGNED | KW_VIRTUAL | KW_VOID | KW_VOLATILE
| KW_WHILE | TOKENPASTE
| KW_WHILE
| KW_OPERATOR
{
}

View File

@ -356,6 +356,16 @@ as_type_proxy() {
return (CPPTypeProxy *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CPPDeclaration::as_make_property
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CPPMakeProperty *CPPDeclaration::
as_make_property() {
return (CPPMakeProperty *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CPPDeclaration::as_make_seq
// Access: Public, Virtual
@ -366,7 +376,6 @@ as_make_seq() {
return (CPPMakeSeq *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CPPDeclaration::is_equal
// Access: Protected, Virtual

View File

@ -47,6 +47,7 @@ class CPPExtensionType;
class CPPStructType;
class CPPEnumType;
class CPPTypeProxy;
class CPPMakeProperty;
class CPPMakeSeq;
class CPPClassTemplateParameter;
class CPPTBDType;
@ -69,6 +70,7 @@ public:
ST_type,
ST_namespace,
ST_using,
ST_make_property,
ST_make_seq,
// Subtypes of CPPType
@ -136,6 +138,7 @@ public:
virtual CPPEnumType *as_enum_type();
virtual CPPTBDType *as_tbd_type();
virtual CPPTypeProxy *as_type_proxy();
virtual CPPMakeProperty *as_make_property();
virtual CPPMakeSeq *as_make_seq();
CPPVisibility _vis;
@ -154,8 +157,4 @@ operator << (ostream &out, const CPPDeclaration &decl) {
return out;
}
#endif

View File

@ -38,8 +38,8 @@ CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope,
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void CPPEnumType::
add_element(const string &name, CPPScope *scope, CPPExpression *value) {
CPPInstance *CPPEnumType::
add_element(const string &name, CPPExpression *value) {
CPPType *type =
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
CPPSimpleType::F_unsigned));
@ -47,7 +47,7 @@ add_element(const string &name, CPPScope *scope, CPPExpression *value) {
CPPInstance *inst = new CPPInstance(type, ident);
inst->_initializer = value;
_elements.push_back(inst);
scope->add_enum_value(inst);
return inst;
}
////////////////////////////////////////////////////////////////////

View File

@ -35,8 +35,8 @@ public:
CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope,
const CPPFile &file);
void add_element(const string &name, CPPScope *scope,
CPPExpression *value = (CPPExpression *)NULL);
CPPInstance *add_element(const string &name,
CPPExpression *value = (CPPExpression *)NULL);
virtual bool is_incomplete() const;

View File

@ -132,10 +132,10 @@ void *CPPExpression::Result::
as_pointer() const {
switch (_type) {
case RT_integer:
return (void *)_u._integer;
return reinterpret_cast<void*>((long)_u._integer);
case RT_real:
return (void *)(int)_u._real;
return reinterpret_cast<void*>((long)_u._real);
case RT_pointer:
return _u._pointer;
@ -400,6 +400,16 @@ evaluate() const {
return Result();
case T_variable:
if (_u._variable->_type != NULL &&
_u._variable->_initializer != NULL) {
// A const variable. Fetch its assigned value.
CPPConstType *const_type = _u._variable->_type->as_const_type();
if (const_type != NULL) {
return _u._variable->_initializer->evaluate();
}
}
return Result();
case T_function:
return Result();
@ -889,6 +899,14 @@ bool CPPExpression::
is_tbd() const {
switch (_type) {
case T_variable:
if (_u._variable->_type != NULL &&
_u._variable->_initializer != NULL) {
CPPConstType *const_type = _u._variable->_type->as_const_type();
if (const_type != NULL) {
return false;
}
}
return true;
case T_typecast:
@ -978,6 +996,15 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
break;
case T_variable:
if (_u._variable->_type != NULL &&
_u._variable->_initializer != NULL) {
// A const variable. Fetch its assigned value.
CPPConstType *const_type = _u._variable->_type->as_const_type();
if (const_type != NULL) {
_u._variable->_initializer->output(out, indent_level, scope, false);
break;
}
}
_u._variable->_ident->output(out, scope);
break;

View File

@ -0,0 +1,99 @@
// Filename: cppMakeProperty.cxx
// Created by: rdb (18Sep14)
//
////////////////////////////////////////////////////////////////////
//
// 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."
//
////////////////////////////////////////////////////////////////////
#include "cppMakeProperty.h"
#include "cppFunctionGroup.h"
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
CPPMakeProperty::
CPPMakeProperty(CPPIdentifier *ident,
CPPFunctionGroup *getter, CPPFunctionGroup *setter,
CPPScope *current_scope, const CPPFile &file) :
CPPDeclaration(file),
_ident(ident),
_getter(getter),
_setter(setter)
{
_ident->_native_scope = current_scope;
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::get_simple_name
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
string CPPMakeProperty::
get_simple_name() const {
return _ident->get_simple_name();
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::get_local_name
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
string CPPMakeProperty::
get_local_name(CPPScope *scope) const {
return _ident->get_local_name(scope);
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::get_fully_scoped_name
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
string CPPMakeProperty::
get_fully_scoped_name() const {
return _ident->get_fully_scoped_name();
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void CPPMakeProperty::
output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
out << "__make_property(" << _ident->get_local_name(scope)
<< ", " << _getter->_name;
if (_setter != NULL) {
out << ", " << _setter->_name;
}
out << ");";
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::get_subtype
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CPPDeclaration::SubType CPPMakeProperty::
get_subtype() const {
return ST_make_property;
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::as_make_property
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CPPMakeProperty *CPPMakeProperty::
as_make_property() {
return this;
}

View File

@ -0,0 +1,51 @@
// Filename: cppMakeProperty.h
// Created by: rdb (18Sep14)
//
////////////////////////////////////////////////////////////////////
//
// 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."
//
////////////////////////////////////////////////////////////////////
#ifndef CPPMAKEPROPERTY_H
#define CPPMAKEPROPERTY_H
#include "dtoolbase.h"
#include "cppDeclaration.h"
///////////////////////////////////////////////////////////////////
// Class : CPPMakeProperty
// Description : This is a MAKE_PROPERTY() declaration appearing
// within a class body. It means to generate a property
// within Python, replacing (for instance)
// get_something()/set_something() with a synthetic
// 'something' attribute.
////////////////////////////////////////////////////////////////////
class CPPMakeProperty : public CPPDeclaration {
public:
CPPMakeProperty(CPPIdentifier *ident,
CPPFunctionGroup *getter, CPPFunctionGroup *setter,
CPPScope *current_scope, const CPPFile &file);
virtual string get_simple_name() const;
virtual string get_local_name(CPPScope *scope = NULL) const;
virtual string get_fully_scoped_name() const;
virtual void output(ostream &out, int indent_level, CPPScope *scope,
bool complete) const;
virtual SubType get_subtype() const;
virtual CPPMakeProperty *as_make_property();
CPPIdentifier *_ident;
CPPFunctionGroup *_getter;
CPPFunctionGroup *_setter;
};
#endif

View File

@ -24,8 +24,8 @@
// Description:
////////////////////////////////////////////////////////////////////
CPPManifest::ExpansionNode::
ExpansionNode(int parm_number) :
_parm_number(parm_number)
ExpansionNode(int parm_number, bool stringify, bool paste) :
_parm_number(parm_number), _stringify(stringify), _paste(paste)
{
}
@ -35,8 +35,8 @@ ExpansionNode(int parm_number) :
// Description:
////////////////////////////////////////////////////////////////////
CPPManifest::ExpansionNode::
ExpansionNode(const string &str) :
_parm_number(-1), _str(str)
ExpansionNode(const string &str, bool paste) :
_parm_number(-1), _stringify(false), _paste(paste), _str(str)
{
}
@ -46,7 +46,11 @@ ExpansionNode(const string &str) :
// Description:
////////////////////////////////////////////////////////////////////
CPPManifest::
CPPManifest(const string &args, const CPPFile &file) : _file(file) {
CPPManifest(const string &args, const CPPFile &file) :
_file(file),
_variadic_param(-1),
_expr((CPPExpression *)NULL)
{
assert(!args.empty());
assert(!isspace(args[0]));
@ -69,6 +73,7 @@ CPPManifest(const string &args, const CPPFile &file) : _file(file) {
_has_parameters = true;
parse_parameters(args, p, parameter_names);
_num_parameters = parameter_names.size();
p++;
} else {
_has_parameters = false;
@ -83,7 +88,6 @@ CPPManifest(const string &args, const CPPFile &file) : _file(file) {
save_expansion(args.substr(p), parameter_names);
}
////////////////////////////////////////////////////////////////////
// Function: CPPManifest::Destructor
// Access: Public
@ -96,7 +100,58 @@ CPPManifest::
}
}
////////////////////////////////////////////////////////////////////
// Function: CPPManifest::stringify
// Access: Public, Static
// Description: This implements the stringification operator, #.
////////////////////////////////////////////////////////////////////
string CPPManifest::
stringify(const string &source) {
string result("\"");
enum {
S_escaped = 0x01,
S_single_quoted = 0x02,
S_double_quoted = 0x04,
S_quoted = 0x06,
};
int state = 0;
string::const_iterator it;
for (it = source.begin(); it != source.end(); ++it) {
char c = *it;
if ((state & S_escaped) == 0) {
switch (c) {
case '\\':
if (state & S_quoted) {
state |= S_escaped;
result += '\\';
}
break;
case '\'':
state ^= S_single_quoted;
break;
case '"':
state ^= S_double_quoted;
result += '\\';
break;
}
} else {
if (c == '\\' || c == '"') {
result += '\\';
}
state &= ~S_escaped;
}
result += c;
}
result += '"';
return result;
}
////////////////////////////////////////////////////////////////////
// Function: CPPManifest::expand
@ -111,14 +166,45 @@ expand(const vector_string &args) const {
for (ei = _expansion.begin(); ei != _expansion.end(); ++ei) {
if ((*ei)._parm_number >= 0) {
int i = (*ei)._parm_number;
string subst;
if (i < (int)args.size()) {
result += " " + args[i] + " ";
} else {
result += " ";
subst = args[i];
if (i == _variadic_param) {
for (++i; i < (int)args.size(); ++i) {
subst += ", " + args[i];
}
}
if ((*ei)._stringify) {
subst = stringify(subst);
}
} else if (i == _variadic_param && (*ei)._paste) {
// Special case GCC behavior: if __VA_ARGS__ is pasted
// to a comma and no arguments are passed, the comma
// is removed. MSVC does this automatically. Not sure
// if we should allow MSVC behavior as well.
if (*result.rbegin() == ',') {
result.resize(result.size() - 1);
}
}
if (!subst.empty()) {
if (result.empty() || (*ei)._paste) {
result += subst;
} else {
result += ' ';
result += subst;
}
}
}
if (!(*ei)._str.empty()) {
result += (*ei)._str;
if (result.empty() || (*ei)._paste) {
result += (*ei)._str;
} else {
result += ' ';
result += (*ei)._str;
}
}
}
@ -151,20 +237,40 @@ output(ostream &out) const {
if (_has_parameters) {
out << "(";
if (_num_parameters > 0) {
out << "$1";
if (_variadic_param == 0) {
out << "...";
} else {
out << "$1";
}
for (int i = 1; i < _num_parameters; ++i) {
out << ", $" << i + 1;
if (_variadic_param == i) {
out << ", ...";
} else {
out << ", $" << i + 1;
}
}
}
out << ")";
}
out << " ";
Expansion::const_iterator ei;
for (ei = _expansion.begin(); ei != _expansion.end(); ++ei) {
if ((*ei)._paste) {
out << " ## ";
} else {
out << " ";
}
if ((*ei)._parm_number >= 0) {
out << " $" << (*ei)._parm_number + 1 << " ";
if (stringify) {
out << "#";
}
if ((*ei)._parm_number == _variadic_param) {
out << "__VA_ARGS__";
} else {
out << "$" << (*ei)._parm_number + 1;
}
}
if (!(*ei)._str.empty()) {
out << (*ei)._str;
@ -172,8 +278,6 @@ output(ostream &out) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: CPPManifest::parse_parameters
// Access: Private
@ -197,7 +301,16 @@ parse_parameters(const string &args, size_t &p,
args[p] != ')' && args[p] != ',') {
p++;
}
parameter_names.push_back(args.substr(q, p - q));
// Check if it's a variadic parameter by checking if it ends
// with "...". This picks up both C99-style variadic macros
// and GCC-style variadic macros.
if (p - q >= 3 && args.compare(p - 3, 3, "...") == 0) {
_variadic_param = parameter_names.size();
parameter_names.push_back(args.substr(q, p - q - 3));
} else {
parameter_names.push_back(args.substr(q, p - q));
}
// Skip whitespace after the parameter name.
while (p < args.size() && isspace(args[p])) {
@ -221,16 +334,12 @@ parse_parameters(const string &args, size_t &p,
////////////////////////////////////////////////////////////////////
void CPPManifest::
save_expansion(const string &exp, const vector_string &parameter_names) {
if (parameter_names.empty()) {
// No parameters; this is an easy case.
_expansion.push_back(ExpansionNode(exp));
return;
}
// Walk through the expansion string. For each substring that is an
// identifier, check it against parameter_names.
size_t p = 0;
size_t last = 0;
bool stringify = false;
bool paste = false;
while (p < exp.size()) {
if (isalpha(exp[p]) || exp[p] == '_') {
// Here's the start of an identifier. Find the end of it.
@ -244,26 +353,67 @@ save_expansion(const string &exp, const vector_string &parameter_names) {
// Is this identifier one of our parameters?
int pnum = -1;
for (int i = 0; pnum == -1 && i < (int)parameter_names.size(); ++i) {
if (parameter_names[i] == ident) {
pnum = i;
bool va_args = false;
if (ident == "__VA_ARGS__") {
va_args = true;
// C99-style variadics, ie. #define macro(...) __VA_ARGS__
pnum = _variadic_param;
} else {
for (int i = 0; pnum == -1 && i < (int)parameter_names.size(); ++i) {
const string &pname = parameter_names[i];
if (pname == ident) {
pnum = i;
}
}
}
if (pnum != -1) {
// Yep!
if (last != q) {
_expansion.push_back(ExpansionNode(exp.substr(last, q - last)));
_expansion.push_back(ExpansionNode(exp.substr(last, q - last), paste));
paste = false;
}
_expansion.push_back(pnum);
_expansion.push_back(ExpansionNode(pnum, stringify, paste));
stringify = false;
paste = false;
last = p;
}
} else if (exp[p] == '#') {
// This may be a stringification operator.
if (last != p) {
_expansion.push_back(ExpansionNode(exp.substr(last, p - last), paste));
paste = false;
}
++p;
if (p < exp.size() && exp[p] == '#') {
// Woah, this is a token-pasting operator.
paste = true;
++p;
} else {
// Mark that the next argument should be stringified.
stringify = true;
}
last = p;
} else if (isspace(exp[p])) {
if (last != p) {
_expansion.push_back(ExpansionNode(exp.substr(last, p - last), paste));
paste = false;
}
++p;
last = p;
} else {
p++;
++p;
}
}
if (last != p) {
_expansion.push_back(exp.substr(last, p - last));
_expansion.push_back(ExpansionNode(exp.substr(last, p - last), paste));
}
}

View File

@ -33,6 +33,8 @@ class CPPManifest {
public:
CPPManifest(const string &args, const CPPFile &file = CPPFile());
~CPPManifest();
static string stringify(const string &source);
string expand(const vector_string &args = vector_string()) const;
CPPType *determine_type() const;
@ -42,6 +44,7 @@ public:
string _name;
bool _has_parameters;
int _num_parameters;
int _variadic_param;
CPPFile _file;
CPPExpression *_expr;
@ -59,9 +62,11 @@ private:
class ExpansionNode {
public:
ExpansionNode(int parm_number);
ExpansionNode(const string &str);
ExpansionNode(int parm_number, bool stringify, bool paste);
ExpansionNode(const string &str, bool paste = false);
int _parm_number;
bool _stringify;
bool _paste;
string _str;
};
typedef vector<ExpansionNode> Expansion;

View File

@ -315,23 +315,6 @@ get_next_token0() {
int first_col = token._lloc.first_column;
CPPFile first_file = token._lloc.file;
if (token._token == '#') {
// Stringify.
token = internal_get_next_token();
if (token._token == SIMPLE_IDENTIFIER ||
token._token == INTEGER ||
token._token == REAL ||
token._token == STRING) {
token._token = STRING;
} else {
// Stringify nothing.
_saved_tokens.push_back(token);
token._token = STRING;
token._lval.str = "";
}
}
if (_resolve_identifiers &&
(token._token == SIMPLE_IDENTIFIER || token._token == SCOPE)) {
// We will be returning a scoped identifier, or a scoping. Keep
@ -366,59 +349,41 @@ get_next_token0() {
}
}
while (token._token == SCOPE || token._token == TOKENPASTE) {
if (token._token == TOKENPASTE) {
// The token-pasting operator creates one continuous
// identifier across whitespace.
token = internal_get_next_token();
if (token._token == SIMPLE_IDENTIFIER ||
token._token == INTEGER ||
token._token == REAL) {
name += token._lval.str;
ident->_names.back().append_name(token._lval.str);
token = internal_get_next_token();
} else {
// Token-paste with nothing.
}
} else { // token._token == SCOPE
name += "::";
token = internal_get_next_token();
string token_prefix;
if (token._token == '~') {
// A scoping operator followed by a tilde can only be the
// start of a scoped destructor name. Make the tilde be part
// of the name.
name += "~";
token_prefix = "~";
token = internal_get_next_token();
}
if (token._token != SIMPLE_IDENTIFIER) {
// The last useful token was a SCOPE, thus this is a scoping
// token.
if (token._token == KW_OPERATOR) {
// Unless the last token we came across was the "operator"
// keyword. We make a special case for this, because it's
// occasionally scoped in normal use.
token._lval = result;
return token;
}
_saved_tokens.push_back(token);
return CPPToken(SCOPING, first_line, first_col, first_file,
name, result);
}
name += token._lval.str;
ident->_names.push_back(token_prefix + token._lval.str);
while (token._token == SCOPE) {
name += "::";
token = internal_get_next_token();
string token_prefix;
if (token._token == '~') {
// A scoping operator followed by a tilde can only be the
// start of a scoped destructor name. Make the tilde be part
// of the name.
name += "~";
token_prefix = "~";
token = internal_get_next_token();
}
if (token._token != SIMPLE_IDENTIFIER) {
// The last useful token was a SCOPE, thus this is a scoping
// token.
if (token._token == KW_OPERATOR) {
// Unless the last token we came across was the "operator"
// keyword. We make a special case for this, because it's
// occasionally scoped in normal use.
token._lval = result;
return token;
}
_saved_tokens.push_back(token);
return CPPToken(SCOPING, first_line, first_col, first_file,
name, result);
}
name += token._lval.str;
ident->_names.push_back(token_prefix + token._lval.str);
token = internal_get_next_token();
if (token._token == '<') {
// If the next token is an angle bracket and the current
// indentifier wants template instantiation, assume the angle
@ -563,6 +528,34 @@ get_comment_before(int line, CPPFile file) {
return (CPPCommentBlock *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CPPPreprocessor::get_comment_on
// Access: Public
// Description: Returns the CPPCommentBlock that starts on the
// indicated line, if any. If there is no such
// comment, returns NULL.
////////////////////////////////////////////////////////////////////
CPPCommentBlock *CPPPreprocessor::
get_comment_on(int line, CPPFile file) {
CPPComments::reverse_iterator ci;
ci = _comments.rbegin();
while (ci != _comments.rend()) {
CPPCommentBlock *comment = (*ci);
if (comment->_file == file) {
if (comment->_line_number == line) {
return comment;
} else if (comment->_line_number < line) {
return (CPPCommentBlock *)NULL;
}
}
++ci;
}
return (CPPCommentBlock *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CPPPreprocessor::init_cpp
// Access: Protected
@ -887,11 +880,6 @@ internal_get_next_token() {
case '%':
if (next_c == '=') return CPPToken(MODEQUAL, first_line, first_col, first_file);
break;
// These are actually preprocessor operators, but it's useful to
// treat them as tokens.
case '#':
if (next_c == '#') return CPPToken(TOKENPASTE, first_line, first_col, first_file);
}
// It wasn't any of the two- or three-character tokens, so put back
@ -931,6 +919,10 @@ internal_get_next_token() {
}
}
// We skip whitespace here again, so that we can read any comments
// after this point before we parse this line.
_last_c = skip_whitespace(_last_c);
return CPPToken(c, first_line, first_col, first_file);
}
@ -945,11 +937,13 @@ skip_whitespace(int c) {
c = skip_comment(c);
if (c == '\\') {
// A backslash character is an unusual thing to encounter in the
// middle of unquoted C++ code. But it seems to be legal, and
// it seems to mean the same thing it does within quotes: to
// escape the following character. We simply ignore it.
// This does not usually occur in the middle of unquoted C++
// code, except before a newline character.
c = get();
if (c != '\n') {
unget(c);
return '\\';
}
}
if (!isspace(c)) {
@ -1057,11 +1051,19 @@ skip_cpp_comment(int c) {
if (_save_comments) {
CPPCommentBlock *comment;
if (_last_cpp_comment) {
int line_number = get_line_number();
if (c == '\n') {
// We have to subtract one from the line number as we just
// fetched a newline.
--line_number;
}
if (_last_cpp_comment && !_comments.empty() &&
_comments.back()->_last_line >= line_number - 1) {
// If the last non-whitespace character read was also part of a
// C++ comment, then this is just a continuation of that comment
// block.
assert(!_comments.empty());
// block. However, if there was a line without comment in between,
// it starts a new block anyway.
comment = _comments.back();
assert(!comment->_c_style);
comment->_comment += "//";
@ -1071,8 +1073,8 @@ skip_cpp_comment(int c) {
comment = new CPPCommentBlock;
comment->_file = get_file();
comment->_line_number = get_line_number();
comment->_last_line = get_line_number();
comment->_line_number = line_number;
comment->_last_line = line_number;
comment->_col_number = get_col_number() - 2;
comment->_c_style = false;
comment->_comment = "//";
@ -1086,7 +1088,7 @@ skip_cpp_comment(int c) {
}
comment->_comment += '\n';
comment->_last_line = get_line_number();
comment->_last_line = line_number;
_last_cpp_comment = true;
@ -1633,7 +1635,8 @@ expand_manifest(const CPPManifest *manifest) {
if (manifest->_has_parameters) {
// Hmm, we're expecting arguments.
extract_manifest_args(manifest->_name, manifest->_num_parameters, args);
extract_manifest_args(manifest->_name, manifest->_num_parameters,
manifest->_variadic_param, args);
}
string expanded = " " + manifest->expand(args) + " ";
@ -1659,7 +1662,7 @@ expand_manifest(const CPPManifest *manifest) {
// Description:
////////////////////////////////////////////////////////////////////
void CPPPreprocessor::
extract_manifest_args(const string &name, int num_args,
extract_manifest_args(const string &name, int num_args, int va_arg,
vector_string &args) {
CPPFile first_file = get_file();
int first_line = get_line_number();
@ -1683,12 +1686,14 @@ extract_manifest_args(const string &name, int num_args,
} else {
// Skip paren.
c = get();
c = skip_whitespace(get());
int paren_level = 1;
string arg;
while (c != EOF && c != ')') {
if (c == ',') {
while (c != EOF) {
if (c == ',' && paren_level == 1) {
args.push_back(arg);
arg = "";
c = get();
} else if (c == '"' || c == '\'') {
// Quoted string or character.
@ -1706,35 +1711,55 @@ extract_manifest_args(const string &name, int num_args,
}
}
arg += c;
c = get();
} else if (c == '(') {
// Nested parens.
int paren_level = 1;
while (c != EOF && paren_level > 0) {
arg += c;
c = get();
if (c == '(') {
paren_level++;
} else if (c == ')') {
paren_level--;
}
arg += '(';
++paren_level;
c = get();
} else if (c == ')') {
--paren_level;
if (paren_level == 0) {
break;
}
if (c != EOF) {
arg += c;
arg += ')';
c = get();
} else if (isspace(c)) {
// Skip extra whitespace.
c = skip_whitespace(c);
if (!arg.empty()) {
arg += ' ';
}
} else if (c == '\\') {
// It could be a slash before a newline.
// If so, that's whitespace as well.
c = get();
if (c != '\n') {
arg += '\\';
} else if (!arg.empty()) {
arg += ' ';
c = skip_whitespace(get());
}
} else {
arg += c;
c = get();
}
c = get();
}
if (num_args != 0 || !arg.empty()) {
args.push_back(arg);
}
}
if ((int)args.size() != num_args) {
warning("Wrong number of arguments for manifest " + name,
if ((int)args.size() < num_args) {
warning("Not enough arguments for manifest " + name,
first_line, first_col, first_file);
} else if (va_arg < 0 && (int)args.size() > num_args) {
warning("Too many arguments for manifest " + name,
first_line, first_col, first_file);
}
}
@ -1742,14 +1767,15 @@ extract_manifest_args(const string &name, int num_args,
////////////////////////////////////////////////////////////////////
// Function: CPPPreprocessor::expand_defined_function
// Access: Private
// Description:
// Description: Expands the defined(manifest) function to either
// 1 or 0, depending on whether the manifest exists.
////////////////////////////////////////////////////////////////////
void CPPPreprocessor::
expand_defined_function(string &expr, size_t q, size_t &p) {
string result;
vector_string args;
extract_manifest_args_inline("defined", 1, args, expr, p);
extract_manifest_args_inline("defined", 1, -1, args, expr, p);
if (args.size() >= 1) {
const string &manifest_name = args[0];
Manifests::const_iterator mi = _manifests.find(manifest_name);
@ -1777,7 +1803,7 @@ expand_manifest_inline(string &expr, size_t q, size_t &p,
vector_string args;
if (manifest->_has_parameters) {
extract_manifest_args_inline(manifest->_name, manifest->_num_parameters,
args, expr, p);
manifest->_variadic_param, args, expr, p);
}
string result = manifest->expand(args);
@ -1792,7 +1818,7 @@ expand_manifest_inline(string &expr, size_t q, size_t &p,
////////////////////////////////////////////////////////////////////
void CPPPreprocessor::
extract_manifest_args_inline(const string &name, int num_args,
vector_string &args,
int va_arg, vector_string &args,
const string &expr, size_t &p) {
// Skip whitespace till paren.
while (p < expr.size() && isspace(expr[p])) {
@ -1819,7 +1845,7 @@ extract_manifest_args_inline(const string &name, int num_args,
}
}
p++;
} else {
// Skip paren.
p++;
@ -1850,8 +1876,11 @@ extract_manifest_args_inline(const string &name, int num_args,
}
}
if ((int)args.size() != num_args) {
warning("Wrong number of arguments for manifest " + name);
if ((int)args.size() < num_args) {
warning("Not enough arguments for manifest " + name);
} else if (va_arg < 0 && (int)args.size() > num_args) {
warning("Too many arguments for manifest " + name);
}
}
@ -1998,6 +2027,7 @@ check_keyword(const string &name) {
if (name == "inline") return KW_INLINE;
if (name == "int") return KW_INT;
if (name == "long") return KW_LONG;
if (name == "__make_property") return KW_MAKE_PROPERTY;
if (name == "__make_seq") return KW_MAKE_SEQ;
if (name == "mutable") return KW_MUTABLE;
if (name == "namespace") return KW_NAMESPACE;
@ -2035,6 +2065,90 @@ check_keyword(const string &name) {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: CPPPreprocessor::scan_escape_sequence
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
int CPPPreprocessor::
scan_escape_sequence(int c) {
if (c != '\\') {
return c;
}
c = get();
switch (c) {
case 'a':
return '\a';
case 'b':
return '\b';
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case 'e':
// \e is non-standard, buT GCC supports it.
return '\x1B';
case 'x':
// hex character.
c = get();
if (isxdigit(c)) {
int val = hex_val(c);
c = get();
if (isxdigit(c)) {
val = (val << 4) | hex_val(c);
} else {
unget(c);
}
return val;
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
// Octal character.
{
int val = (c - '0');
c = get();
if (c >= '0' && c <= '7') {
val = (val << 3) | (c - '0');
c = get();
if (c >= '0' && c <= '7') {
val = (val << 3) | (c - '0');
} else {
unget(c);
}
} else {
unget(c);
}
return val;
}
}
// Simply output the following character.
return c;
}
////////////////////////////////////////////////////////////////////
// Function: CPPPreprocessor::scan_quoted
// Access: Private
@ -2049,62 +2163,7 @@ scan_quoted(int c) {
while (c != EOF && c != '\n' && c != quote_mark) {
if (c == '\\') {
// Backslash means a special character follows.
c = get();
switch (c) {
case 'n':
c = '\n';
break;
case 't':
c = '\t';
break;
case 'r':
c = '\r';
break;
case 'x':
// hex character.
c = get();
if (isxdigit(c)) {
int val = hex_val(c);
c = get();
if (isxdigit(c)) {
val = (val << 4) | hex_val(c);
} else {
unget(c);
}
c = val;
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
// Octal character.
{
int val = (c - '0');
c = get();
if (c >= '0' && c <= '7') {
val = (val << 3) | (c - '0');
c = get();
if (c >= '0' && c <= '7') {
val = (val << 3) | (c - '0');
} else {
unget(c);
}
} else {
unget(c);
}
c = val;
}
break;
}
c = scan_escape_sequence(c);
}
str += c;

View File

@ -64,6 +64,7 @@ public:
CPPFile file = CPPFile());
CPPCommentBlock *get_comment_before(int line, CPPFile file);
CPPCommentBlock *get_comment_on(int line, CPPFile file);
int get_warning_count() const;
int get_error_count() const;
@ -75,7 +76,7 @@ public:
DSearchPath _quote_include_path;
DSearchPath _angle_include_path;
bool _noangles;
CPPComments _comments;
typedef set<CPPFile> ParsedFiles;
@ -142,16 +143,17 @@ private:
CPPToken get_identifier(int c);
CPPToken expand_manifest(const CPPManifest *manifest);
void extract_manifest_args(const string &name, int num_args,
vector_string &args);
int va_arg, vector_string &args);
void expand_defined_function(string &expr, size_t q, size_t &p);
void expand_manifest_inline(string &expr, size_t q, size_t &p,
const CPPManifest *manifest);
void extract_manifest_args_inline(const string &name, int num_args,
vector_string &args,
int va_arg, vector_string &args,
const string &expr, size_t &p);
CPPToken get_number(int c, int c2 = 0);
static int check_keyword(const string &name);
int scan_escape_sequence(int c);
string scan_quoted(int c);
bool should_ignore_manifest(const CPPManifest *manifest) const;

View File

@ -145,9 +145,34 @@ add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
// Description:
////////////////////////////////////////////////////////////////////
void CPPScope::
add_enum_value(CPPInstance *inst) {
add_enum_value(CPPInstance *inst, CPPPreprocessor *preprocessor,
const cppyyltype &pos) {
inst->_vis = _current_vis;
if (inst->_leading_comment == (CPPCommentBlock *)NULL) {
// Same-line comment?
CPPCommentBlock *comment =
preprocessor->get_comment_on(pos.first_line, pos.file);
if (comment == (CPPCommentBlock *)NULL) {
// Nope. Check for a comment before this line.
comment =
preprocessor->get_comment_before(pos.first_line, pos.file);
if (comment != NULL) {
// This is a bit of a hack, but it prevents us from picking
// up a same-line comment from the previous line.
if (comment->_line_number != pos.first_line - 1 ||
comment->_col_number <= pos.first_column) {
inst->_leading_comment = comment;
}
}
} else {
inst->_leading_comment = comment;
}
}
string name = inst->get_simple_name();
if (!name.empty()) {
_enum_values[name] = inst;

View File

@ -63,7 +63,9 @@ public:
virtual void add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
CPPPreprocessor *preprocessor,
const cppyyltype &pos);
virtual void add_enum_value(CPPInstance *inst);
virtual void add_enum_value(CPPInstance *inst,
CPPPreprocessor *preprocessor,
const cppyyltype &pos);
virtual void define_extension_type(CPPExtensionType *type);
virtual void define_namespace(CPPNamespace *scope);
virtual void add_using(CPPUsing *using_decl, CPPScope *global_scope,

View File

@ -51,10 +51,11 @@ add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
// Description:
////////////////////////////////////////////////////////////////////
void CPPTemplateScope::
add_enum_value(CPPInstance *inst) {
add_enum_value(CPPInstance *inst, CPPPreprocessor *preprocessor,
const cppyyltype &pos) {
inst->_template_scope = this;
assert(_parent_scope != NULL);
_parent_scope->add_enum_value(inst);
_parent_scope->add_enum_value(inst, preprocessor, pos);
}
////////////////////////////////////////////////////////////////////

View File

@ -36,7 +36,9 @@ public:
virtual void add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
CPPPreprocessor *preprocessor,
const cppyyltype &pos);
virtual void add_enum_value(CPPInstance *inst);
virtual void add_enum_value(CPPInstance *inst,
CPPPreprocessor *preprocessor,
const cppyyltype &pos);
virtual void define_extension_type(CPPExtensionType *type);
virtual void define_namespace(CPPNamespace *scope);
virtual void add_using(CPPUsing *using_decl, CPPScope *global_scope,

View File

@ -247,10 +247,6 @@ output(ostream &out) const {
out << "RSHIFTEQUAL";
break;
case TOKENPASTE:
out << "TOKENPASTE";
break;
case KW_BOOL:
out << "KW_BOOL";
break;

View File

@ -4,6 +4,7 @@
#include "cppCommentBlock.cxx"
#include "cppConstType.cxx"
#include "cppDeclaration.cxx"
#include "cppMakeProperty.cxx"
#include "cppMakeSeq.cxx"
#include "cppParameterList.cxx"
#include "cppParser.cxx"

View File

@ -39,7 +39,8 @@
typeRegistryNode.I typeRegistryNode.h \
typedObject.I typedObject.h \
pallocator.T pallocator.h \
pdeque.h plist.h pmap.h pset.h pvector.h \
pdeque.h plist.h pmap.h pset.h \
pvector.h epvector.h \
lookup3.h lookup3.c \
dlmalloc_src.cxx ptmalloc2_smp_src.cxx
@ -97,7 +98,8 @@
typeRegistryNode.I typeRegistryNode.h \
typedObject.I typedObject.h \
pallocator.T pallocator.h \
pdeque.h plist.h pmap.h pset.h pvector.h \
pdeque.h plist.h pmap.h pset.h \
pvector.h epvector.h \
lookup3.h
#end lib_target

View File

@ -16,11 +16,11 @@
// see float.h
#define FPU_CONTROLWORD_WRITEMASK 0xFFFFF // if you look at defn of _CW_DEFAULT, all settings fall within 0xFFFFF
#define FPU_CONTROLWORD_NEW_SETTING _CW_DEFAULT
#endif
#endif
////////////////////////////////////////////////////////////////////
// Function: csqrt
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
csqrt(float v) {
@ -29,7 +29,7 @@ csqrt(float v) {
////////////////////////////////////////////////////////////////////
// Function: csin
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
csin(float v) {
@ -38,7 +38,7 @@ csin(float v) {
////////////////////////////////////////////////////////////////////
// Function: ccos
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
ccos(float v) {
@ -47,7 +47,7 @@ ccos(float v) {
////////////////////////////////////////////////////////////////////
// Function: ctan
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float ctan(float v) {
return tanf(v);
@ -55,7 +55,7 @@ INLINE float ctan(float v) {
////////////////////////////////////////////////////////////////////
// Function: csincos
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void
csincos(float v, float *sin_result, float *cos_result) {
@ -80,7 +80,7 @@ csincos(float v, float *sin_result, float *cos_result) {
// Function: csin_over_x
// Description: Computes sin(x) / x, well-behaved as x approaches 0.
////////////////////////////////////////////////////////////////////
INLINE float
INLINE float
csin_over_x(float v) {
if (1.0f + v * v == 1.0f) {
return 1.0f;
@ -91,7 +91,7 @@ csin_over_x(float v) {
////////////////////////////////////////////////////////////////////
// Function: cabs
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
cabs(float v) {
@ -100,7 +100,7 @@ cabs(float v) {
////////////////////////////////////////////////////////////////////
// Function: catan
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
catan(float v) {
@ -109,7 +109,7 @@ catan(float v) {
////////////////////////////////////////////////////////////////////
// Function: catan2
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
catan2(float y, float x) {
@ -118,7 +118,7 @@ catan2(float y, float x) {
////////////////////////////////////////////////////////////////////
// Function: casin
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
casin(float v) {
@ -127,7 +127,7 @@ casin(float v) {
////////////////////////////////////////////////////////////////////
// Function: cacos
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
cacos(float v) {
@ -147,7 +147,7 @@ cmod(float x, float y) {
////////////////////////////////////////////////////////////////////
// Function: cpow
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
cpow(float x, float y) {
@ -157,7 +157,7 @@ cpow(float x, float y) {
////////////////////////////////////////////////////////////////////
// Function: cfloor
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
cfloor(double f) {
@ -169,13 +169,13 @@ cfloor(double f) {
_controlfp(saved_fpu_control_word,FPU_CONTROLWORD_WRITEMASK);
return retval;
#else
return floor(f);
return floor(f);
#endif
}
////////////////////////////////////////////////////////////////////
// Function: cceil
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
cceil(double f) {
@ -187,7 +187,7 @@ cceil(double f) {
_controlfp(saved_fpu_control_word,FPU_CONTROLWORD_WRITEMASK);
return retval;
#else
return ceil(f);
return ceil(f);
#endif
}
@ -202,7 +202,7 @@ cfrac(double f) {
////////////////////////////////////////////////////////////////////
// Function: csqrt
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
csqrt(double v) {
@ -211,7 +211,7 @@ csqrt(double v) {
////////////////////////////////////////////////////////////////////
// Function: csin
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
csin(double v) {
@ -220,7 +220,7 @@ csin(double v) {
////////////////////////////////////////////////////////////////////
// Function: ccos
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
ccos(double v) {
@ -229,7 +229,7 @@ ccos(double v) {
////////////////////////////////////////////////////////////////////
// Function: ctan
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
ctan(double v) {
@ -238,7 +238,7 @@ ctan(double v) {
////////////////////////////////////////////////////////////////////
// Function: csincos
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE void
csincos(double v, double *sin_result, double *cos_result) {
@ -262,7 +262,7 @@ csincos(double v, double *sin_result, double *cos_result) {
// Function: csin_over_x
// Description: Computes sin(x) / x, well-behaved as x approaches 0.
////////////////////////////////////////////////////////////////////
INLINE double
INLINE double
csin_over_x(double v) {
if (1.0 + v * v == 1.0) {
return 1.0;
@ -273,7 +273,7 @@ csin_over_x(double v) {
////////////////////////////////////////////////////////////////////
// Function: cabs
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
cabs(double v) {
@ -282,7 +282,7 @@ cabs(double v) {
////////////////////////////////////////////////////////////////////
// Function: catan
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
catan(double v) {
@ -291,7 +291,7 @@ catan(double v) {
////////////////////////////////////////////////////////////////////
// Function: catan2
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
catan2(double y, double x) {
@ -300,7 +300,7 @@ catan2(double y, double x) {
////////////////////////////////////////////////////////////////////
// Function: casin
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
casin(double v) {
@ -309,7 +309,7 @@ casin(double v) {
////////////////////////////////////////////////////////////////////
// Function: cacos
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
cacos(double v) {
@ -329,7 +329,7 @@ cmod(double x, double y) {
////////////////////////////////////////////////////////////////////
// Function: cpow
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
cpow(double x, double y) {
@ -338,7 +338,7 @@ cpow(double x, double y) {
////////////////////////////////////////////////////////////////////
// Function: cpow
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE int
cpow(int x, int y) {
@ -360,43 +360,73 @@ cpow(int x, int y) {
////////////////////////////////////////////////////////////////////
// Function: cnan
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool
cnan(double v) {
#ifndef _WIN32
return (std::isnan(v) != 0);
return std::isnan(v);
#else
return (_isnan(v) != 0);
#endif
}
////////////////////////////////////////////////////////////////////
// Function: cinf
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool
cinf(double v) {
#ifndef _WIN32
return std::isinf(v);
#else
return (_isnan(v) == 0 && _finite(v) == 0);
#endif
}
////////////////////////////////////////////////////////////////////
// Function: make_nan
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
make_nan(float) {
#ifndef _WIN32
return nanf("");
#else
return numeric_limits<float>::quiet_NaN();
return std::numeric_limits<float>::quiet_NaN();
#endif
}
////////////////////////////////////////////////////////////////////
// Function: make_nan
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
INLINE double
make_nan(double) {
#ifndef _WIN32
return nan("");
#else
return numeric_limits<double>::quiet_NaN();
return std::numeric_limits<double>::quiet_NaN();
#endif
}
////////////////////////////////////////////////////////////////////
// Function: make_inf
// Description:
////////////////////////////////////////////////////////////////////
INLINE float
make_inf(float) {
return std::numeric_limits<float>::infinity();
}
////////////////////////////////////////////////////////////////////
// Function: make_inf
// Description:
////////////////////////////////////////////////////////////////////
INLINE double
make_inf(double) {
return std::numeric_limits<double>::infinity();
}
////////////////////////////////////////////////////////////////////
// Function: cmod

View File

@ -24,13 +24,8 @@
#include "dtoolbase.h"
#include <cmath>
// Windows defines isnan() in a different place and with a different
// name than everyone else. Sheesh.
#ifdef _WIN32
#include <float.h>
#include <cfloat>
#include <limits>
#endif
INLINE float csqrt(float v);
INLINE float csin(float v);
@ -68,13 +63,17 @@ INLINE int cpow(int x, int y);
// or infinity.
INLINE bool cnan(double v);
// Returns NaN.
// Returns true if the number is infinity.
INLINE bool cinf(double v);
// Return NaN and infinity, respectively.
INLINE float make_nan(float);
INLINE double make_nan(double);
INLINE float make_inf(float);
INLINE double make_inf(double);
INLINE int cmod(int x, int y);
#include "cmath.I"
#endif

View File

@ -409,17 +409,16 @@
#define BEGIN_PUBLISH __begin_publish
#define END_PUBLISH __end_publish
#define BLOCKING __blocking
#define MAKE_PROPERTY(property_name, ...) __make_property(property_name, __VA_ARGS__)
#define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
#undef USE_STL_ALLOCATOR /* Don't try to parse these template classes in interrogate. */
#define EXTENSION(x) __extension x
#define EXTEND __extension
#define EXT_FUNC(func) ::func()
#define EXT_FUNC_ARGS(func, ...) ::func(__VA_ARGS__)
#define CALL_EXT_FUNC(func, ...) ::func (__VA_ARGS__)
#else
#define BEGIN_PUBLISH
#define END_PUBLISH
#define BLOCKING
#define MAKE_PROPERTY(property_name, ...)
#define MAKE_SEQ(seq_name, num_name, element_name)
#define EXTENSION(x)
#define EXTEND

View File

@ -0,0 +1,61 @@
// Filename: epvector.h
// Created by: drose (19Dec11)
//
////////////////////////////////////////////////////////////////////
//
// 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."
//
////////////////////////////////////////////////////////////////////
#ifndef EPVECTOR_H
#define EPVECTOR_H
#include "pvector.h"
#if defined(HAVE_EIGEN) && defined(_WIN32) && !defined(CPPPARSER)
#include <Eigen/StdVector>
////////////////////////////////////////////////////////////////////
// Class : epvector
// Description : Unfortunately, on Windows, std::vector can't be used
// for classes with explicitly alignment requirements,
// due to a minor mistake in the template definition
// (one of the vector methods receives a concrete
// object, which the compiler flags as an error, even if
// the method is never called).
//
// As a workaround, Eigen provides their own
// specialization of vector, using their own aligned
// allocator. We define that here as epvector, which is
// meant to be a drop-in replacement for pvector for
// classes that include a linmath object that requires
// alignment. Unfortunately, this means we can't use
// the Panda allocator, so memory allocated for this
// vector class won't be tracked as part of Panda's
// memory tracking system. Them's the breaks, kids.
////////////////////////////////////////////////////////////////////
template<class Type>
class epvector : public vector<Type, Eigen::aligned_allocator<Type> > {
public:
typedef Eigen::aligned_allocator<Type> allocator;
typedef vector<Type, allocator> base_class;
typedef TYPENAME base_class::size_type size_type;
epvector(TypeHandle type_handle = pvector_type_handle) : base_class(allocator()) { }
epvector(const epvector<Type> &copy) : base_class(copy) { }
epvector(size_type n, TypeHandle type_handle = pvector_type_handle) : base_class(n, Type(), allocator()) { }
epvector(size_type n, const Type &value, TypeHandle type_handle = pvector_type_handle) : base_class(n, value, allocator()) { }
epvector(const Type *begin, const Type *end, TypeHandle type_handle = pvector_type_handle) : base_class(begin, end, allocator()) { }
};
#else // HAVE_EIGEN
#define epvector pvector
#endif // HAVE_EIGEN
#endif

View File

@ -16,7 +16,11 @@
#include <ctype.h>
#include <math.h>
#include <limits>
#ifdef _WIN32
#define strncasecmp _strnicmp
#endif
////////////////////////////////////////////////////////////////////
// Function: pstrtod
@ -45,67 +49,100 @@ pstrtod(const char *nptr, char **endptr) {
double value = 0.0;
if (isalpha(*p)) {
// For special cases like "inf" and "nan", pass these up to the
// system implementation of strtod.
return strtod(nptr, endptr);
}
// Windows' implementation of strtod doesn't support "inf" or
// "nan", so check for those here.
if (strncasecmp(p, "inf", 3) == 0) {
p += 3;
if (strncasecmp(p, "inity", 5) == 0) {
p += 5;
}
value = std::numeric_limits<double>::infinity();
} else if (strncasecmp(p, "nan", 3) == 0) {
p += 3;
if (*p == 's' || *p == 'S') {
value = std::numeric_limits<double>::signaling_NaN();
++p;
} else {
if (*p == 'q' || *p == 'Q') {
++p;
}
value = std::numeric_limits<double>::quiet_NaN();
}
// It is optionally possible to include a character sequence
// between parentheses after "nan", to be passed to the new
// nan() function. Since it isn't supported universally, we
// will only accept a pair of empty parentheses.
if (strncmp(p, "()", 2) == 0) {
p += 2;
}
// Start reading decimal digits to the left of the decimal point.
bool found_digits = false;
while (isdigit(*p)) {
value = (value * 10.0) + (*p - '0');
found_digits = true;
++p;
}
if (*p == '.') {
++p;
// Read decimal digits to the right of the decimal point.
double multiplicand = 0.1;
while (isdigit(*p)) {
value += (*p - '0') * multiplicand;
++p;
found_digits = true;
multiplicand *= 0.1;
}
}
if (!found_digits) {
// Not a valid float.
if (endptr != NULL) {
*endptr = (char *)nptr;
}
return 0.0;
}
if (tolower(*p) == 'e') {
// There's an exponent.
++p;
char esign = '+';
if (*p == '+' || *p == '-') {
esign = *p;
++p;
}
// Start reading decimal digits to the left of the decimal point.
double evalue = 0.0;
while (isdigit(*p)) {
evalue = (evalue * 10.0) + (*p - '0');
++p;
}
if (esign == '-') {
value /= pow(evalue, 10.0);
} else {
value *= pow(evalue, 10.0);
// Pass it up to the system implementation of strtod;
// perhaps it knows how to deal with this string.
return strtod(nptr, endptr);
}
}
} else {
// Start reading decimal digits to the left of the decimal point.
bool found_digits = false;
while (isdigit(*p)) {
value = (value * 10.0) + (*p - '0');
found_digits = true;
++p;
}
if (*p == '.') {
++p;
// Read decimal digits to the right of the decimal point.
double multiplicand = 0.1;
while (isdigit(*p)) {
value += (*p - '0') * multiplicand;
++p;
found_digits = true;
multiplicand *= 0.1;
}
}
if (!found_digits) {
// Not a valid float.
if (endptr != NULL) {
*endptr = (char *)nptr;
}
return 0.0;
}
if (tolower(*p) == 'e') {
// There's an exponent.
++p;
char esign = '+';
if (*p == '+' || *p == '-') {
esign = *p;
++p;
}
// Start reading decimal digits to the left of the decimal point.
double evalue = 0.0;
while (isdigit(*p)) {
evalue = (evalue * 10.0) + (*p - '0');
++p;
}
if (esign == '-') {
value /= pow(evalue, 10.0);
} else {
value *= pow(evalue, 10.0);
}
}
}
if (sign == '-') {
value = -value;
}
if (endptr != NULL) {
*endptr = (char *)p;
}

View File

@ -51,46 +51,4 @@ public:
#endif // USE_STL_ALLOCATOR
#if defined(HAVE_EIGEN) && defined(_WIN32) && !defined(CPPPARSER)
#include <Eigen/StdVector>
////////////////////////////////////////////////////////////////////
// Class : epvector
// Description : Unfortunately, on Windows, std::vector can't be used
// for classes with explicitly alignment requirements,
// due to a minor mistake in the template definition
// (one of the vector methods receives a concrete
// object, which the compiler flags as an error, even if
// the method is never called).
//
// As a workaround, Eigen provides their own
// specialization of vector, using their own aligned
// allocator. We define that here as epvector, which is
// meant to be a drop-in replacement for pvector for
// classes that include a linmath object that requires
// alignment. Unfortunately, this means we can't use
// the Panda allocator, so memory allocated for this
// vector class won't be tracked as part of Panda's
// memory tracking system. Them's the breaks, kids.
////////////////////////////////////////////////////////////////////
template<class Type>
class epvector : public vector<Type, Eigen::aligned_allocator<Type> > {
public:
typedef Eigen::aligned_allocator<Type> allocator;
typedef vector<Type, allocator> base_class;
typedef TYPENAME base_class::size_type size_type;
epvector(TypeHandle type_handle = pvector_type_handle) : base_class(allocator()) { }
epvector(const epvector<Type> &copy) : base_class(copy) { }
epvector(size_type n, TypeHandle type_handle = pvector_type_handle) : base_class(n, Type(), allocator()) { }
epvector(size_type n, const Type &value, TypeHandle type_handle = pvector_type_handle) : base_class(n, value, allocator()) { }
epvector(const Type *begin, const Type *end, TypeHandle type_handle = pvector_type_handle) : base_class(begin, end, allocator()) { }
};
#else // HAVE_EIGEN
#define epvector pvector
#endif // HAVE_EIGEN
#endif

View File

@ -275,6 +275,17 @@ none() {
return _none;
}
////////////////////////////////////////////////////////////////////
// Function: TypeHandle::operator bool
// Access: Published
// Description: TypeHandle::none() evaluates to false, everything
// else evaluates to true.
////////////////////////////////////////////////////////////////////
INLINE TypeHandle::
operator bool () const {
return (_index != 0);
}
////////////////////////////////////////////////////////////////////
// Function: get_best_parent_from_Set
// Access: Published
@ -295,4 +306,3 @@ INLINE int TypeHandle::get_best_parent_from_Set(const std::set< int > &legal_va
}
return -1;
}

View File

@ -146,6 +146,7 @@ PUBLISHED:
INLINE int get_index() const;
INLINE void output(ostream &out) const;
INLINE static TypeHandle none();
INLINE operator bool () const;
private:
int _index;

View File

@ -24,6 +24,7 @@
panda_getopt.h panda_getopt_long.h panda_getopt_impl.h \
pfstream.h pfstream.I pfstreamBuf.h \
preprocess_argv.h \
string_utils.h string_utils.I \
stringDecoder.h stringDecoder.I \
textEncoder.h textEncoder.I \
unicodeLatinMap.h \
@ -43,6 +44,7 @@
panda_getopt_impl.cxx \
pfstreamBuf.cxx pfstream.cxx \
preprocess_argv.cxx \
string_utils.cxx \
stringDecoder.cxx \
textEncoder.cxx \
unicodeLatinMap.cxx \
@ -63,6 +65,7 @@
panda_getopt.h panda_getopt_long.h panda_getopt_impl.h \
pfstream.h pfstream.I pfstreamBuf.h \
preprocess_argv.h \
string_utils.h string_utils.I \
stringDecoder.h stringDecoder.I \
textEncoder.h textEncoder.I \
unicodeLatinMap.h \

View File

@ -4,6 +4,7 @@
#include "pfstream.cxx"
#include "pfstreamBuf.cxx"
#include "preprocess_argv.cxx"
#include "string_utils.cxx"
#include "stringDecoder.cxx"
#include "textEncoder.cxx"
#include "unicodeLatinMap.cxx"

View File

@ -15,51 +15,51 @@
#ifndef STRING_UTILS_H
#define STRING_UTILS_H
#include "pandabase.h"
#include "dtoolbase.h"
#include <string>
#include "vector_string.h"
// Case-insensitive string comparison, from Stroustrup's C++ third edition.
// Works like strcmp().
EXPCL_PANDA_PUTIL int cmp_nocase(const string &s, const string &s2);
EXPCL_DTOOL int cmp_nocase(const string &s, const string &s2);
// Similar, except it also accepts hyphen and underscore as equivalent.
EXPCL_PANDA_PUTIL int cmp_nocase_uh(const string &s, const string &s2);
EXPCL_DTOOL int cmp_nocase_uh(const string &s, const string &s2);
// Returns the string converted to lowercase.
EXPCL_PANDA_PUTIL string downcase(const string &s);
EXPCL_DTOOL string downcase(const string &s);
// Returns the string converted to uppercase.
EXPCL_PANDA_PUTIL string upcase(const string &s);
EXPCL_DTOOL string upcase(const string &s);
// Separates the string into words according to whitespace.
EXPCL_PANDA_PUTIL int extract_words(const string &str, vector_string &words);
EXPCL_PANDA_PUTIL int extract_words(const wstring &str, pvector<wstring> &words);
EXPCL_DTOOL int extract_words(const string &str, vector_string &words);
EXPCL_DTOOL int extract_words(const wstring &str, pvector<wstring> &words);
// Separates the string into words according to the indicated delimiters.
EXPCL_PANDA_PUTIL void tokenize(const string &str, vector_string &words,
EXPCL_DTOOL void tokenize(const string &str, vector_string &words,
const string &delimiters,
bool discard_repeated_delimiters = false);
EXPCL_PANDA_PUTIL void tokenize(const wstring &str, pvector<wstring> &words,
EXPCL_DTOOL void tokenize(const wstring &str, pvector<wstring> &words,
const wstring &delimiters,
bool discard_repeated_delimiters = false);
// Trims leading and/or trailing whitespace from the string.
EXPCL_PANDA_PUTIL string trim_left(const string &str);
EXPCL_PANDA_PUTIL wstring trim_left(const wstring &str);
EXPCL_PANDA_PUTIL string trim_right(const string &str);
EXPCL_PANDA_PUTIL wstring trim_right(const wstring &str);
EXPCL_PANDA_PUTIL string trim(const string &str);
EXPCL_PANDA_PUTIL wstring trim(const wstring &str);
EXPCL_DTOOL string trim_left(const string &str);
EXPCL_DTOOL wstring trim_left(const wstring &str);
EXPCL_DTOOL string trim_right(const string &str);
EXPCL_DTOOL wstring trim_right(const wstring &str);
EXPCL_DTOOL string trim(const string &str);
EXPCL_DTOOL wstring trim(const wstring &str);
// Functions to parse numeric values out of a string.
EXPCL_PANDA_PUTIL int string_to_int(const string &str, string &tail);
EXPCL_PANDA_PUTIL bool string_to_int(const string &str, int &result);
EXPCL_PANDA_PUTIL double string_to_double(const string &str, string &tail);
EXPCL_PANDA_PUTIL bool string_to_double(const string &str, double &result);
EXPCL_PANDA_PUTIL bool string_to_float(const string &str, float &result);
EXPCL_PANDA_PUTIL bool string_to_stdfloat(const string &str, PN_stdfloat &result);
EXPCL_DTOOL int string_to_int(const string &str, string &tail);
EXPCL_DTOOL bool string_to_int(const string &str, int &result);
EXPCL_DTOOL double string_to_double(const string &str, string &tail);
EXPCL_DTOOL bool string_to_double(const string &str, double &result);
EXPCL_DTOOL bool string_to_float(const string &str, float &result);
EXPCL_DTOOL bool string_to_stdfloat(const string &str, PN_stdfloat &result);
// Convenience function to make a string from anything that has an
// ostream operator.

View File

@ -102,7 +102,8 @@ get_parameter_name(int n) const {
// are returning a value, or the empty string if we
// return nothing.
////////////////////////////////////////////////////////////////////
string FunctionRemap::call_function(ostream &out, int indent_level, bool convert_result,
string FunctionRemap::
call_function(ostream &out, int indent_level, bool convert_result,
const string &container, const vector_string &pexprs) const {
string return_expr;
@ -117,11 +118,11 @@ string FunctionRemap::call_function(ostream &out, int indent_level, bool convert
InterfaceMaker::indent(out, indent_level)
<< "unref_delete(" << container << ");\n";
} else {
if (inside_python_native) {
InterfaceMaker::indent(out, indent_level) << "Dtool_Py_Delete(self); \n";
} else {
InterfaceMaker::indent(out, indent_level) << " delete " << container << ";\n";
}
if (inside_python_native) {
InterfaceMaker::indent(out, indent_level) << "Dtool_Py_Delete(self);\n";
} else {
InterfaceMaker::indent(out, indent_level) << "delete " << container << ";\n";
}
}
} else if (_type == T_typecast_method) {
@ -370,7 +371,8 @@ get_call_str(const string &container, const vector_string &pexprs) const {
}
call << " = ";
_parameters[0]._remap->pass_parameter(call, get_parameter_expr(_first_true_parameter, pexprs));
_parameters[_first_true_parameter]._remap->pass_parameter(call,
get_parameter_expr(_first_true_parameter, pexprs));
} else {
const char *separator = "";

View File

@ -87,6 +87,19 @@ MakeSeq(const string &name, CPPMakeSeq *cpp_make_seq) :
{
}
////////////////////////////////////////////////////////////////////
// Function: InterfaceMaker::Property::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
InterfaceMaker::Property::
Property(const InterrogateElement &ielement) :
_ielement(ielement),
_getter(NULL),
_setter(NULL)
{
}
////////////////////////////////////////////////////////////////////
// Function: InterfaceMaker::Object::Constructor
// Access: Public
@ -156,6 +169,8 @@ check_protocols() {
_protocol_types |= PT_iter;
}
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
// Now are there any make_seq requests within this class?
if (_itype._cpptype != NULL) {
CPPStructType *stype = _itype._cpptype->as_struct_type();
@ -230,9 +245,9 @@ InterfaceMaker::
Object *object = (*oi).second;
delete object;
}
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
delete (*fi);
delete (*fi).second;
}
}
@ -501,9 +516,9 @@ wrap_global_functions() {
////////////////////////////////////////////////////////////////////
void InterfaceMaker::
get_function_remaps(vector<FunctionRemap *> &remaps) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
Function::Remaps::const_iterator ri;
for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
FunctionRemap *remap = (*ri);
@ -617,12 +632,17 @@ get_unique_prefix() {
////////////////////////////////////////////////////////////////////
InterfaceMaker::Function *InterfaceMaker::
record_function(const InterrogateType &itype, FunctionIndex func_index) {
if (_functions.count(func_index)) {
// Already exists.
return _functions[func_index];
}
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
const InterrogateFunction &ifunc = idb->get_function(func_index);
string wrapper_name = get_wrapper_name(itype, ifunc, func_index);
Function *func = new Function(wrapper_name, itype, ifunc);
_functions.push_back(func);
_functions[func_index] = func;
// printf(" Function Name = %s\n", ifunc.get_name().c_str());
@ -837,6 +857,27 @@ manage_return_value(ostream &out, int indent_level,
return return_expr;
}
////////////////////////////////////////////////////////////////////
// Function: InterfaceMaker::delete_return_value
// Access: Protected
// Description: Cleans up the given return value by deleting it or
// decrementing its reference count or whatever is
// appropriate.
////////////////////////////////////////////////////////////////////
void InterfaceMaker::
delete_return_value(ostream &out, int indent_level,
FunctionRemap *remap, const string &return_expr) const {
if (remap->_manage_reference_count) {
// If we're managing reference counts, and we're about to return a
// reference countable object, then decrement its count.
output_unref(out, indent_level, remap, return_expr);
} else if (remap->_return_value_needs_management) {
// We should just delete it directly.
indent(out, indent_level) << "delete " << return_expr << ";\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: InterfaceMaker::output_ref
// Access: Protected
@ -859,7 +900,7 @@ output_ref(ostream &out, int indent_level, FunctionRemap *remap,
indent(out, indent_level)
<< "if (" << varname << " != ("
<< remap->_return_type->get_new_type()->get_local_name(&parser) << ")0) {\n";
<< remap->_return_type->get_new_type()->get_local_name(&parser) << ")NULL) {\n";
indent(out, indent_level + 2)
<< varname << "->ref();\n";
indent(out, indent_level)
@ -867,6 +908,36 @@ output_ref(ostream &out, int indent_level, FunctionRemap *remap,
}
}
////////////////////////////////////////////////////////////////////
// Function: InterfaceMaker::output_unref
// Access: Protected
// Description: Outputs the code to decrement the reference count for
// the indicated variable name.
////////////////////////////////////////////////////////////////////
void InterfaceMaker::
output_unref(ostream &out, int indent_level, FunctionRemap *remap,
const string &varname) const {
if (remap->_type == FunctionRemap::T_constructor ||
remap->_type == FunctionRemap::T_typecast) {
// In either of these cases, we can safely assume the pointer will
// never be NULL.
indent(out, indent_level)
<< "unref_delete(" << varname << ");\n";
} else {
// However, in the general case, we have to check for that before
// we attempt to ref it.
indent(out, indent_level)
<< "if (" << varname << " != ("
<< remap->_return_type->get_new_type()->get_local_name(&parser) << ")NULL) {\n";
indent(out, indent_level + 2)
<< "unref_delete(" << varname << ");\n";
indent(out, indent_level)
<< "}\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: InterfaceMaker::hash_function_signature
// Access: Protected

View File

@ -31,8 +31,9 @@ class ParameterRemap;
class CPPType;
class CPPInstance;
class InterrogateBuilder;
class InterrogateType;
class InterrogateElement;
class InterrogateFunction;
class InterrogateType;
////////////////////////////////////////////////////////////////////
// Class : InterfaceMaker
@ -109,8 +110,9 @@ public:
int _flags;
ArgsType _args_type;
};
typedef map<FunctionIndex, Function *> FunctionsByIndex;
typedef vector<Function *> Functions;
Functions _functions;
FunctionsByIndex _functions;
class MakeSeq {
public:
@ -123,6 +125,16 @@ public:
};
typedef vector<MakeSeq *> MakeSeqs;
class Property {
public:
Property(const InterrogateElement &ielement);
const InterrogateElement &_ielement;
Function *_getter;
Function *_setter;
};
typedef vector<Property *> Properties;
class Object {
public:
Object(const InterrogateType &itype);
@ -135,6 +147,7 @@ public:
Functions _constructors;
Functions _methods;
MakeSeqs _make_seqs;
Properties _properties;
enum ProtocolTypes {
PT_sequence = 0x0001,
@ -179,8 +192,14 @@ public:
manage_return_value(ostream &out, int indent_level,
FunctionRemap *remap, const string &return_expr) const;
void
delete_return_value(ostream &out, int indent_level,
FunctionRemap *remap, const string &return_expr) const;
void output_ref(ostream &out, int indent_level, FunctionRemap *remap,
const string &varname) const;
void output_unref(ostream &out, int indent_level, FunctionRemap *remap,
const string &varname) const;
void write_spam_message(ostream &out, FunctionRemap *remap) const;
protected:

View File

@ -53,9 +53,9 @@ InterfaceMakerC::
////////////////////////////////////////////////////////////////////
void InterfaceMakerC::
write_prototypes(ostream &out,ostream *out_h) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_prototype_for(out, func);
}
@ -72,9 +72,9 @@ write_prototypes(ostream &out,ostream *out_h) {
////////////////////////////////////////////////////////////////////
void InterfaceMakerC::
write_functions(ostream &out) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_function_for(out, func);
}

View File

@ -36,7 +36,8 @@ InterfaceMakerPython(InterrogateModuleDef *def) :
void InterfaceMakerPython::
write_includes(ostream &out) {
InterfaceMaker::write_includes(out);
out << "#undef _POSIX_C_SOURCE\n\n"
out << "#undef _POSIX_C_SOURCE\n"
<< "#define PY_SSIZE_T_CLEAN 1\n\n"
<< "#if PYTHON_FRAMEWORK\n"
<< " #include \"Python/Python.h\"\n"
<< "#else\n"

View File

@ -818,9 +818,9 @@ write_functions(ostream &out) {
out << "//********************************************************************\n";
out << "//*** Functions for .. Global\n" ;
out << "//********************************************************************\n";
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
if (!func->_itype.is_global() && is_function_legal(func)) {
write_function_for_top(out, NULL, func);
}
@ -877,6 +877,23 @@ write_class_details(ostream &out, Object *obj) {
}
}
Properties::const_iterator pit;
for (pit = obj->_properties.begin(); pit != obj->_properties.end(); ++pit) {
Property *property = (*pit);
const InterrogateElement &ielem = property->_ielement;
bool coercion_attempted = false;
if (property->_getter != NULL) {
std::string fname = "PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *)";
write_function_for_name(out, obj, property->_getter, fname, true, coercion_attempted, AT_no_args, false, false);
}
if (property->_setter != NULL) {
std::string fname = "int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter(PyObject *self, PyObject *arg, void *)";
write_function_for_name(out, obj, property->_setter, fname, true, coercion_attempted, AT_single_arg, true, false);
}
}
if (obj->_constructors.size() == 0) {
out << "int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds) {\n"
<< " PyErr_SetString(PyExc_TypeError, \"cannot init constant class (" << cClassName << ")\");\n"
@ -894,7 +911,7 @@ write_class_details(ostream &out, Object *obj) {
Function *func = (*fi);
std::string fname = "int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)";
write_function_for_name(out, obj, func, fname, true, coercion_attempted, AT_keyword_args, true);
write_function_for_name(out, obj, func, fname, true, coercion_attempted, AT_keyword_args, true, false);
}
if (coercion_attempted) {
// If a coercion attempt was written into the above constructor,
@ -904,7 +921,7 @@ write_class_details(ostream &out, Object *obj) {
Function *func = (*fi);
std::string fname = "int Dtool_InitNoCoerce_" + ClassName + "(PyObject *self, PyObject *args)";
write_function_for_name(out, obj, func, fname, false, coercion_attempted, AT_varargs, true);
write_function_for_name(out, obj, func, fname, false, coercion_attempted, AT_varargs, true, false);
}
} else {
// Otherwise, since the above constructor didn't involve any
@ -1115,9 +1132,9 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
bool force_base_functions = true;
out << "static PyMethodDef python_simple_funcs[] = {\n";
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
if (!func->_itype.is_global() && is_function_legal(func)) {
string name1 = methodNameFromCppName(func, "", false);
string name2 = methodNameFromCppName(func, "", true);
@ -1515,7 +1532,7 @@ write_module_class(ostream &out, Object *obj) {
// *need* to raise IndexError if we're out of bounds. We have to
// assume the bounds are 0 .. this->size() (this is the same
// assumption that Python makes).
out << " if (index < 0 || index >= local_this->size()) {\n";
out << " if (index < 0 || index >= (Py_ssize_t) local_this->size()) {\n";
out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << " index out of range\");\n";
out << " return NULL;\n";
out << " }\n";
@ -1555,7 +1572,7 @@ write_module_class(ostream &out, Object *obj) {
out << " return -1;\n";
out << " }\n\n";
out << " if (index < 0 || index >= local_this->size()) {\n";
out << " if (index < 0 || index >= (Py_ssize_t) local_this->size()) {\n";
out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << " index out of range\");\n";
out << " return -1;\n";
out << " }\n";
@ -2079,6 +2096,44 @@ write_module_class(ostream &out, Object *obj) {
out << "}\n\n";
}
if (obj->_properties.size() > 0) {
// Write out the array of properties, telling Python which getter and setter
// to call when they are assigned or queried in Python code.
out << "PyGetSetDef Dtool_Properties_" << ClassName << "[] = {\n";
Properties::const_iterator pit;
for (pit = obj->_properties.begin(); pit != obj->_properties.end(); ++pit) {
Property *property = (*pit);
const InterrogateElement &ielem = property->_ielement;
if (property->_getter == NULL || !is_function_legal(property->_getter)) {
continue;
}
out << " {(char *)\"" << ielem.get_name() << "\","
<< " &Dtool_" << ClassName << "_" << ielem.get_name() << "_Getter,";
if (property->_setter == NULL || !is_function_legal(property->_setter)) {
out << " NULL,";
} else {
out << " &Dtool_" << ClassName << "_" << ielem.get_name() << "_Setter,";
}
if (ielem.has_comment()) {
out << "(char *)\n";
output_quoted(out, 4, ielem.get_comment());
out << ",\n ";
} else {
out << " NULL, ";
}
// Extra void* argument; we don't make use of it.
out << "NULL},\n";
}
out << " {NULL},\n";
out << "};\n\n";
}
out << "void Dtool_PyModuleClassInit_" << ClassName << "(PyObject *module) {\n";
out << " static bool initdone = false;\n";
out << " if (!initdone) {\n";
@ -2191,6 +2246,11 @@ write_module_class(ostream &out, Object *obj) {
out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_str = &Dtool_Repr_" << ClassName << ";\n";
}
if (obj->_properties.size() > 0) {
// GetSet descriptor slots.
out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_getset = Dtool_Properties_" << ClassName << ";\n";
}
int num_nested = obj->_itype.number_of_nested_types();
for (int ni = 0; ni < num_nested; ni++) {
TypeIndex nested_index = obj->_itype.get_nested_type(ni);
@ -2396,7 +2456,7 @@ write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker
fname += ")";
bool coercion_attempted = false;
write_function_for_name(out, obj, func, fname, true, coercion_attempted, func->_args_type, false);
write_function_for_name(out, obj, func, fname, true, coercion_attempted, func->_args_type, false, true);
}
////////////////////////////////////////////////////////////////////
@ -2408,7 +2468,7 @@ void InterfaceMakerPythonNative::
write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMaker::Function *func,
const std::string &function_name,
bool coercion_allowed, bool &coercion_attempted,
ArgsType args_type, bool return_int) {
ArgsType args_type, bool return_int, bool write_comment) {
ostringstream out;
std::map<int, std::set<FunctionRemap *> > MapSets;
@ -2463,7 +2523,11 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak
// Other functions should raise an exception if the this
// pointer isn't set or is the wrong type.
out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n";
out << " return NULL;\n";
if (return_int) {
out << " return -1;\n";
} else {
out << " return NULL;\n";
}
}
out << " }\n";
}
@ -2486,12 +2550,9 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak
switch (args_type) {
case AT_keyword_args:
indent(out, 2) << "int parameter_count = PyTuple_Size(args);\n";
if (args_type == AT_keyword_args) {
indent(out, 2) << "if (kwds != NULL && PyDict_Check(kwds)) {\n";
indent(out, 2) << " parameter_count += PyDict_Size(kwds);\n";
indent(out, 2) << "}\n";
}
indent(out, 2) << "if (kwds != NULL) {\n";
indent(out, 2) << " parameter_count += PyDict_Size(kwds);\n";
indent(out, 2) << "}\n";
break;
case AT_varargs:
@ -2499,7 +2560,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak
break;
case AT_single_arg:
// It shouldń't get here, but we'll handle these cases nonetheless.
// It shouldn't get here, but we'll handle these cases nonetheless.
indent(out, 2) << "const int parameter_count = 1;\n";
break;
@ -2576,11 +2637,47 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak
} else {
string expected_params = "";
for (mii = MapSets.begin(); mii != MapSets.end(); mii++) {
write_function_forset(out, obj, func, mii->second, expected_params, 2, is_inplace,
coercion_allowed, coercion_attempted, args_type, return_int);
mii = MapSets.begin();
// If no parameters are accepted, we do need to check that the argument
// count is indeed 0, since we won't check that in write_function_instance.
if (mii->first == 0 && args_type != AT_no_args) {
switch (args_type) {
case AT_keyword_args:
out << " if (PyTuple_Size(args) > 0 || (kwds != NULL && PyDict_Size(kwds) > 0)) {\n";
out << " int parameter_count = PyTuple_Size(args);\n";
out << " if (kwds != NULL) {\n";
out << " parameter_count += PyDict_Size(kwds);\n";
out << " }\n";
break;
case AT_varargs:
out << " if (PyTuple_Size(args) > 0) {\n";
out << " const int parameter_count = PyTuple_GET_SIZE(args);\n";
break;
case AT_single_arg:
default:
// Shouldn't happen, but let's handle this case nonetheless.
out << " {\n";
out << " const int parameter_count = 1;\n";
break;
}
out << " PyErr_Format(PyExc_TypeError,\n"
<< " \"" << methodNameFromCppName(func, "", false)
<< "() takes no arguments (%d given)\",\n"
<< " parameter_count);\n";
if (return_int) {
out << " return -1;\n";
} else {
out << " return (PyObject *) NULL;\n";
}
out << " }\n";
}
write_function_forset(out, obj, func, mii->second, expected_params, 2, is_inplace,
coercion_allowed, coercion_attempted, args_type, return_int);
out << " if (!PyErr_Occurred()) {\n";
out << " PyErr_SetString(PyExc_TypeError,\n";
out << " \"Arguments must match:\\n\"\n";
@ -2607,7 +2704,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak
FunctionComment = FunctionComment1 + "\n" + FunctionComment;
}
if (!return_int) {
if (write_comment) {
// Write out the function doc string. We only do this if it is
// not a constructor, since we don't have a place to put the
// constructor doc string.
@ -2922,7 +3019,6 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
string extra_convert;
string extra_param_check;
string extra_cleanup;
string direct_assign;
bool is_constructor = (remap->_type == FunctionRemap::T_constructor);
@ -2954,7 +3050,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
int num_params = 0;
bool only_pyobjects = true;
bool check_exceptions = false;
//bool check_exceptions = false;
int pn;
for (pn = 0; pn < (int)remap->_parameters.size(); ++pn) {
@ -3000,12 +3096,11 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
parameter_list += ", &" + param_name;
extra_convert += " Py_ssize_t " + param_name + "_len = PyUnicode_GetSize((PyObject *)" + param_name + ");"
" wchar_t *" + param_name + "_str = new wchar_t[" + param_name + "_len + 1];"
" wchar_t *" + param_name + "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));"
" PyUnicode_AsWideChar(" + param_name + ", " + param_name + "_str, " + param_name + "_len);"
" " + param_name + "_str[" + param_name + "_len] = 0;";
pexpr_string = param_name + "_str";
extra_cleanup += " delete[] " + param_name + "_str;";
expected_params += "unicode";
} else if (TypeManager::is_wstring(orig_type)) {
@ -3018,14 +3113,13 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
parameter_list += ", &" + param_name;
extra_convert += " Py_ssize_t " + param_name + "_len = PyUnicode_GetSize((PyObject *)" + param_name + ");"
" wchar_t *" + param_name + "_str = new wchar_t[" + param_name + "_len];"
" wchar_t *" + param_name + "_str = (wchar_t *)alloca(sizeof(wchar_t) * " + param_name + "_len);"
" PyUnicode_AsWideChar(" + param_name + ", " + param_name + "_str, " + param_name + "_len);";
pexpr_string = "basic_string<wchar_t>((wchar_t *)" +
pexpr_string = "basic_string<wchar_t>(" +
param_name + "_str, " +
param_name + "_len)";
extra_cleanup += " delete[] " + param_name + "_str;";
expected_params += "unicode";
} else if (TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) {
@ -3038,14 +3132,13 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
parameter_list += ", &" + param_name;
extra_convert += " Py_ssize_t " + param_name + "_len = PyUnicode_GetSize((PyObject *)" + param_name + ");"
" wchar_t *" + param_name + "_str = new wchar_t[" + param_name + "_len];"
" wchar_t *" + param_name + "_str = (wchar_t *)alloca(sizeof(wchar_t) * " + param_name + "_len);"
" PyUnicode_AsWideChar(" + param_name + ", " + param_name + "_str, " + param_name + "_len);";
pexpr_string = "&basic_string<wchar_t>((wchar_t *)" +
pexpr_string = "&basic_string<wchar_t>(" +
param_name + "_str, " +
param_name + "_len)";
extra_cleanup += " delete[] " + param_name + "_str;";
expected_params += "unicode";
} else {
@ -3057,7 +3150,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
<< param_name << "_str = PyUnicode_AsUTF8AndSize(arg, &"
<< param_name << "_len);\n";
out << "#else\n";
indent(out, indent_level) << "if (PyString_AsStringAndSize(arg, &"
indent(out, indent_level) << "if (PyString_AsStringAndSize(arg, &"
<< param_name << "_str, &" << param_name << "_len) == -1) {\n";
indent(out, indent_level + 2) << param_name << "_str = NULL;\n";
indent(out, indent_level) << "}\n";
@ -3142,14 +3235,9 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
++num_params;
} else if (TypeManager::is_integer(type)) {
if (args_type == AT_single_arg) {
pexpr_string = "(" + type->get_local_name(&parser) + ")PyInt_AS_LONG(arg)";
extra_param_check += " && PyInt_Check(arg)";
} else {
indent(out, indent_level) << "int " << param_name << ";\n";
format_specifiers += "i";
parameter_list += ", &" + param_name;
}
indent(out, indent_level) << "int " << param_name << ";\n";
format_specifiers += "i";
parameter_list += ", &" + param_name;
expected_params += "int";
only_pyobjects = false;
++num_params;
@ -3204,7 +3292,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
// It's reasonable to assume that a function taking a PyObject
// might also throw a TypeError if the type is incorrect.
check_exceptions = true;
//check_exceptions = true;
} else if (TypeManager::is_pointer_to_Py_buffer(type)) {
if (args_type == AT_single_arg) {
@ -3220,7 +3308,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
extra_cleanup += "Py_XDECREF(" + param_name + "_buffer);";
expected_params += "memoryview";
++num_params;
check_exceptions = true;
//check_exceptions = true;
} else if (TypeManager::is_pointer(type)) {
CPPType *obj_type = TypeManager::unwrap(TypeManager::resolve_type(type));
@ -3323,9 +3411,9 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
// If this is the only overload, don't bother checking for type errors.
// Any type error that is raised will simply pass through to below.
if (func->_remaps.size() == 1) {
check_exceptions = false;
}
//if (func->_remaps.size() == 1) {
// check_exceptions = false;
//}
// Track how many curly braces we've opened.
short open_scopes = 0;
@ -3396,6 +3484,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
}
string return_expr;
if (!remap->_void_return &&
remap->_return_type->new_type_is_atomic_string()) {
// Treat strings as a special case. We don't want to format the
@ -3475,6 +3564,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
type->output_instance(out, "return_value", &parser);
out << " = " << return_expr << ";\n";
}
if (track_interpreter) {
indent(out, indent_level) << "in_interpreter = 1;\n";
}
@ -3487,26 +3577,35 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
if (!extra_cleanup.empty()) {
indent(out, indent_level) << extra_cleanup << "\n";
}
if (!is_inplace) {
return_expr = manage_return_value(out, indent_level, remap, "return_value");
}
if (coercion_possible) {
indent(out, indent_level)
<< "Py_XDECREF(coerced);\n";
}
if (!is_inplace) {
if (remap->_return_type->return_value_needs_management()) {
// If a constructor returns NULL, that means allocation failed.
indent(out, indent_level) << "if (return_value == NULL) {\n";
if (return_int) {
indent(out, indent_level) << " PyErr_NoMemory();\n";
indent(out, indent_level) << " return -1;\n";
} else {
indent(out, indent_level) << " return PyErr_NoMemory();\n";
}
indent(out, indent_level) << "}\n";
}
return_expr = manage_return_value(out, indent_level, remap, "return_value");
}
return_expr = remap->_return_type->temporary_to_return(return_expr);
}
}
// If a method raises TypeError, continue.
if (check_exceptions) {
//if (check_exceptions) {
if (true) {
indent(out, indent_level)
<< "if (PyErr_Occurred()) {\n";
if (return_int && !return_expr.empty()) {
indent(out, indent_level + 2)
<< "delete return_value;\n";
}
delete_return_value(out, indent_level, remap, return_expr);
indent(out, indent_level)
<< " if (PyErr_ExceptionMatches(PyExc_TypeError)) {\n";
indent(out, indent_level)
@ -3541,10 +3640,8 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
<< "PyErr_SetString(PyExc_AssertionError, notify->get_assert_error_message().c_str());\n";
indent(out, indent_level + 2)
<< "notify->clear_assert_failed();\n";
delete_return_value(out, indent_level + 2, remap, return_expr);
if (return_int) {
if (!return_expr.empty()) {
indent(out, indent_level + 2) << "delete return_value;\n";
}
indent(out, indent_level + 2) << "return -1;\n";
} else {
indent(out, indent_level + 2) << "return (PyObject *)NULL;\n";
@ -3967,13 +4064,30 @@ record_object(TypeIndex type_index) {
for (int ei = 0; ei < num_elements; ei++) {
ElementIndex element_index = itype.get_element(ei);
const InterrogateElement &ielement = idb->get_element(element_index);
if (ielement.has_getter()) {
FunctionIndex func_index = ielement.get_getter();
record_function(itype, func_index);
}
Property *property = new Property(ielement);
if (ielement.has_setter()) {
FunctionIndex func_index = ielement.get_setter();
record_function(itype, func_index);
Function *setter = record_function(itype, func_index);
if (is_function_legal(setter)) {
property->_setter = setter;
}
}
if (ielement.has_getter()) {
FunctionIndex func_index = ielement.get_getter();
Function *getter = record_function(itype, func_index);
if (is_function_legal(getter)) {
property->_getter = getter;
}
}
if (property->_getter != NULL) {
object->_properties.push_back(property);
} else {
// No use exporting a property without a getter.
delete property;
}
}

View File

@ -95,7 +95,7 @@ private:
void write_function_for_name(ostream &out, Object *obj, Function *func,
const std::string &name,
bool coercion_allowed, bool &coercion_attempted,
ArgsType args_type, bool return_int);
ArgsType args_type, bool return_int, bool write_comment);
void write_function_forset(ostream &out, Object *obj, Function *func,
std::set<FunctionRemap*> &remaps, string &expected_params,

View File

@ -55,9 +55,9 @@ InterfaceMakerPythonObj::
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonObj::
write_prototypes(ostream &out, ostream *out_h) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_prototype_for(out, func);
}
@ -74,9 +74,9 @@ write_prototypes(ostream &out, ostream *out_h) {
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonObj::
write_functions(ostream &out) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_function_for(out, func);
}
@ -360,21 +360,21 @@ write_function_instance(ostream &out, int indent_level,
CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type();
CPPType *type = remap->_parameters[pn]._remap->get_new_type();
string param_name = remap->get_parameter_name(pn);
// This is the string to convert our local variable to the
// appropriate C++ type. Normally this is just a cast.
string pexpr_string =
"(" + type->get_local_name(&parser) + ")" + param_name;
if (remap->_parameters[pn]._remap->new_type_is_atomic_string()) {
if (TypeManager::is_char_pointer(orig_type)) {
out << "char *" << param_name;
format_specifiers += "s";
parameter_list += ", &" + param_name;
} else {
out << "char *" << param_name
<< "_str; int " << param_name << "_len";
<< "_str; Py_ssize_t " << param_name << "_len";
format_specifiers += "s#";
parameter_list += ", &" + param_name
+ "_str, &" + param_name + "_len";
@ -383,7 +383,7 @@ write_function_instance(ostream &out, int indent_level,
param_name + "_len)";
}
expected_params += "string";
} else if (TypeManager::is_bool(type)) {
out << "PyObject *" << param_name;
format_specifiers += "O";

View File

@ -53,9 +53,9 @@ InterfaceMakerPythonSimple::
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonSimple::
write_prototypes(ostream &out,ostream *out_h) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_prototype_for(out, func);
}
@ -72,9 +72,9 @@ write_prototypes(ostream &out,ostream *out_h) {
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonSimple::
write_functions(ostream &out) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_function_for(out, func);
}
@ -93,9 +93,9 @@ write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
out << "static PyMethodDef python_simple_funcs[] = {\n";
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
Function::Remaps::const_iterator ri;
for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
FunctionRemap *remap = (*ri);
@ -270,21 +270,21 @@ void InterfaceMakerPythonSimple::write_function_instance(ostream &out, Interface
CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type();
CPPType *type = remap->_parameters[pn]._remap->get_new_type();
string param_name = remap->get_parameter_name(pn);
// This is the string to convert our local variable to the
// appropriate C++ type. Normally this is just a cast.
string pexpr_string =
"(" + type->get_local_name(&parser) + ")" + param_name;
if (remap->_parameters[pn]._remap->new_type_is_atomic_string()) {
if (TypeManager::is_char_pointer(orig_type)) {
out << "char *" << param_name;
format_specifiers += "s";
parameter_list += ", &" + param_name;
} else if (TypeManager::is_wstring(orig_type)) {
out << "Py_UNICODE *" << param_name
<< "_str; int " << param_name << "_len";
<< "_str; Py_ssize_t " << param_name << "_len";
format_specifiers += "u#";
parameter_list += ", &" + param_name
+ "_str, &" + param_name + "_len";
@ -294,7 +294,7 @@ void InterfaceMakerPythonSimple::write_function_instance(ostream &out, Interface
} else {
out << "char *" << param_name
<< "_str; int " << param_name << "_len";
<< "_str; Py_ssize_t " << param_name << "_len";
format_specifiers += "s#";
parameter_list += ", &" + param_name
+ "_str, &" + param_name + "_len";
@ -302,7 +302,7 @@ void InterfaceMakerPythonSimple::write_function_instance(ostream &out, Interface
param_name + "_str, " +
param_name + "_len)";
}
} else if (TypeManager::is_bool(type)) {
out << "PyObject *" << param_name;
format_specifiers += "O";

View File

@ -44,6 +44,7 @@
#include "cppTypeDeclaration.h"
#include "cppEnumType.h"
#include "cppCommentBlock.h"
#include "cppMakeProperty.h"
#include "cppMakeSeq.h"
#include "pnotify.h"
@ -1357,6 +1358,11 @@ scan_element(CPPInstance *element, CPPStructType *struct_type,
ielement._name = element->get_local_name(scope);
ielement._scoped_name = descope(element->get_local_name(&parser));
// See if there happens to be a comment before the element.
if (element->_leading_comment != (CPPCommentBlock *)NULL) {
ielement._comment = trim_blanks(element->_leading_comment->_comment);
}
ielement._type = get_type(TypeManager::unwrap_reference(element_type), false);
if (ielement._type == 0) {
// If we can't understand what type it is, forget it.
@ -1641,6 +1647,7 @@ get_function(CPPInstance *function, string description,
CPPStructType *struct_type,
CPPScope *scope, int flags,
const string &expression) {
// Get a unique function signature. Make sure we tell the function
// where its native scope is, so we get a fully-scoped signature.
@ -1768,6 +1775,90 @@ get_function(CPPInstance *function, string description,
return index;
}
////////////////////////////////////////////////////////////////////
// Function: InterrogateBuilder::get_make_property
// Access: Private
// Description: Adds the indicated make_property to the database,
// if it is not already present. In either case,
// returns the MakeSeqIndex of the make_seq within the
// database.
////////////////////////////////////////////////////////////////////
ElementIndex InterrogateBuilder::
get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type) {
string property_name = make_property->get_local_name(&parser);
// First, check to see if it's already there.
PropertiesByName::const_iterator tni =
_properties_by_name.find(property_name);
if (tni != _properties_by_name.end()) {
ElementIndex index = (*tni).second;
return index;
}
// Find the getter so we can get its return type.
CPPInstance *getter = NULL;
CPPType *return_type = NULL;
CPPFunctionGroup *fgroup = make_property->_getter;
CPPFunctionGroup::Instances::const_iterator fi;
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
CPPInstance *function = (*fi);
CPPFunctionType *ftype =
function->_type->as_function_type();
if (ftype != NULL && ftype->_parameters->_parameters.size() == 0) {
getter = function;
return_type = ftype->_return_type;
// The return type of the non-const method probably better represents
// the type of the property we are creating.
if ((ftype->_flags & CPPFunctionType::F_const_method) == 0) {
break;
}
}
}
if (getter == NULL || return_type == NULL) {
cerr << "No instance of getter '"
<< make_property->_getter->_name << "' is suitable!\n";
return 0;
}
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
// It isn't here, so we'll have to define it.
ElementIndex index = idb->get_next_index();
_properties_by_name[property_name] = index;
InterrogateElement iproperty;
iproperty._name = make_property->get_simple_name();
iproperty._scoped_name = descope(make_property->get_local_name(&parser));
iproperty._type = get_type(return_type, false);
iproperty._flags |= InterrogateElement::F_has_getter;
iproperty._getter = get_function(getter, "", struct_type,
struct_type->get_scope(), 0);
// See if there happens to be a comment before the MAKE_PROPERTY macro.
if (make_property->_leading_comment != (CPPCommentBlock *)NULL) {
iproperty._comment = trim_blanks(make_property->_leading_comment->_comment);
}
// Now look for setters.
fgroup = make_property->_setter;
if (fgroup != NULL) {
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
CPPInstance *function = (*fi);
iproperty._flags |= InterrogateElement::F_has_setter;
iproperty._setter = get_function(function, "", struct_type,
struct_type->get_scope(), 0);
}
}
idb->add_element(index, iproperty);
return index;
}
////////////////////////////////////////////////////////////////////
// Function: InterrogateBuilder::get_make_seq
// Access: Private
@ -2279,6 +2370,10 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
TypeIndex nested_index = get_type(type, false);
itype._nested_types.push_back(nested_index);
}
} else if ((*di)->get_subtype() == CPPDeclaration::ST_make_property) {
ElementIndex element_index = get_make_property((*di)->as_make_property(), cpptype);
itype._elements.push_back(element_index);
}
}
@ -2566,6 +2661,10 @@ define_enum_type(InterrogateType &itype, CPPEnumType *cpptype) {
evalue._name = element->get_simple_name();
evalue._scoped_name = descope(element->get_local_name(&parser));
if (element->_leading_comment != (CPPCommentBlock *)NULL) {
evalue._comment = trim_blanks(element->_leading_comment->_comment);
}
if (element->_initializer != (CPPExpression *)NULL) {
CPPExpression::Result result = element->_initializer->evaluate();
next_value = result.as_integer();

View File

@ -38,6 +38,7 @@ class CPPScope;
class CPPIdentifier;
class CPPNameComponent;
class CPPManifest;
class CPPMakeProperty;
class CPPMakeSeq;
class InterrogateType;
class InterrogateFunction;
@ -108,6 +109,9 @@ public:
CPPStructType *struct_type, CPPScope *scope,
int flags, const string &expression = string());
ElementIndex
get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type);
MakeSeqIndex
get_make_seq(CPPMakeSeq *make_seq, CPPStructType *struct_type);
@ -132,10 +136,12 @@ public:
typedef map<string, TypeIndex> TypesByName;
typedef map<string, FunctionIndex> FunctionsByName;
typedef map<string, MakeSeqIndex> MakeSeqsByName;
typedef map<string, ElementIndex> PropertiesByName;
TypesByName _types_by_name;
FunctionsByName _functions_by_name;
MakeSeqsByName _make_seqs_by_name;
PropertiesByName _properties_by_name;
typedef map<string, char> IncludeFiles;
IncludeFiles _include_files;

View File

@ -21,7 +21,7 @@ InterrogateDatabase *InterrogateDatabase::_global_ptr = NULL;
int InterrogateDatabase::_file_major_version = 0;
int InterrogateDatabase::_file_minor_version = 0;
int InterrogateDatabase::_current_major_version = 2;
int InterrogateDatabase::_current_minor_version = 2;
int InterrogateDatabase::_current_minor_version = 3;
////////////////////////////////////////////////////////////////////
// Function: InterrogateDatabase::Constructor

View File

@ -48,6 +48,7 @@ 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;
@ -85,6 +86,26 @@ get_scoped_name() const {
return _scoped_name;
}
////////////////////////////////////////////////////////////////////
// Function: InterrogateElement::has_comment
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool InterrogateElement::
has_comment() const {
return !_comment.empty();
}
////////////////////////////////////////////////////////////////////
// Function: InterrogateElement::get_comment
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE const string &InterrogateElement::
get_comment() const {
return _comment;
}
////////////////////////////////////////////////////////////////////
// Element: InterrogateElement::get_type
// Access: Public

View File

@ -30,6 +30,7 @@ output(ostream &out) const {
<< _getter << " "
<< _setter << " ";
idf_output_string(out, _scoped_name);
idf_output_string(out, _comment, '\n');
}
////////////////////////////////////////////////////////////////////
@ -43,6 +44,10 @@ input(istream &in) {
InterrogateComponent::input(in);
in >> _flags >> _type >> _getter >> _setter;
idf_input_string(in, _scoped_name);
if (InterrogateDatabase::get_file_minor_version() >= 3) {
idf_input_string(in, _comment);
}
}
////////////////////////////////////////////////////////////////////

View File

@ -37,6 +37,9 @@ public:
INLINE bool has_scoped_name() const;
INLINE const string &get_scoped_name() const;
INLINE bool has_comment() const;
INLINE const string &get_comment() const;
INLINE TypeIndex get_type() const;
INLINE bool has_getter() const;
INLINE FunctionIndex get_getter() const;
@ -57,6 +60,7 @@ private:
int _flags;
string _scoped_name;
string _comment;
TypeIndex _type;
FunctionIndex _getter;
FunctionIndex _setter;

View File

@ -263,6 +263,19 @@ get_enum_value_scoped_name(int n) const {
return _empty_string;
}
////////////////////////////////////////////////////////////////////
// Function: InterrogateType::get_enum_value_comment
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE const 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;
}
////////////////////////////////////////////////////////////////////
// Function: InterrogateType::get_enum_value
// Access: Public

View File

@ -15,6 +15,7 @@
#include "interrogateType.h"
#include "indexRemapper.h"
#include "interrogate_datafile.h"
#include "interrogateDatabase.h"
#include <algorithm>
@ -76,6 +77,7 @@ 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;
}
@ -88,6 +90,9 @@ void InterrogateType::EnumValue::
input(istream &in) {
idf_input_string(in, _name);
idf_input_string(in, _scoped_name);
if (InterrogateDatabase::get_file_minor_version() >= 3) {
idf_input_string(in, _comment);
}
in >> _value;
}

View File

@ -66,6 +66,7 @@ public:
INLINE int number_of_enum_values() const;
INLINE const string &get_enum_value_name(int n) const;
INLINE const string &get_enum_value_scoped_name(int n) const;
INLINE const string &get_enum_value_comment(int n) const;
INLINE int get_enum_value(int n) const;
INLINE bool is_struct() const;
@ -189,6 +190,7 @@ public:
string _name;
string _scoped_name;
string _comment;
int _value;
};

View File

@ -120,6 +120,18 @@ interrogate_element_scoped_name(ElementIndex element) {
return InterrogateDatabase::get_ptr()->get_element(element).get_scoped_name().c_str();
}
bool
interrogate_element_has_comment(ElementIndex element) {
//cerr << "interrogate_element_has_comment(" << element << ")\n";
return InterrogateDatabase::get_ptr()->get_element(element).has_comment();
}
const char *
interrogate_element_comment(ElementIndex element) {
//cerr << "interrogate_element_comment(" << element << ")\n";
return InterrogateDatabase::get_ptr()->get_element(element).get_comment().c_str();
}
ElementIndex
interrogate_get_element_by_name(const char *element_name) {
//cerr << "interrogate_get_element_by_name(" << element_name << ")\n";
@ -631,6 +643,12 @@ interrogate_type_enum_value_scoped_name(TypeIndex type, int n) {
return InterrogateDatabase::get_ptr()->get_type(type).get_enum_value_scoped_name(n).c_str();
}
const char *
interrogate_type_enum_value_comment(TypeIndex type, int n) {
//cerr << "interrogate_type_enum_value_comment(" << type << ", " << n << ")\n";
return InterrogateDatabase::get_ptr()->get_type(type).get_enum_value_comment(n).c_str();
}
int
interrogate_type_enum_value(TypeIndex type, int n) {
//cerr << "interrogate_type_enum_value(" << type << ", " << n << ")\n";

View File

@ -138,6 +138,8 @@ EXPCL_DTOOLCONFIG int interrogate_manifest_get_int_value(ManifestIndex manifest)
EXPCL_DTOOLCONFIG const char *interrogate_element_name(ElementIndex element);
EXPCL_DTOOLCONFIG const char *interrogate_element_scoped_name(ElementIndex element);
EXPCL_DTOOLCONFIG bool interrogate_element_has_comment(ElementIndex element);
EXPCL_DTOOLCONFIG const char *interrogate_element_comment(ElementIndex element);
EXPCL_DTOOLCONFIG ElementIndex interrogate_get_element_by_name(const char *element_name);
EXPCL_DTOOLCONFIG ElementIndex interrogate_get_element_by_scoped_name(const char *element_name);
@ -454,6 +456,7 @@ EXPCL_DTOOLCONFIG bool interrogate_type_is_enum(TypeIndex type);
EXPCL_DTOOLCONFIG int interrogate_type_number_of_enum_values(TypeIndex type);
EXPCL_DTOOLCONFIG const char *interrogate_type_enum_value_name(TypeIndex type, int n);
EXPCL_DTOOLCONFIG const char *interrogate_type_enum_value_scoped_name(TypeIndex type, int n);
EXPCL_DTOOLCONFIG const char *interrogate_type_enum_value_comment(TypeIndex type, int n);
EXPCL_DTOOLCONFIG int interrogate_type_enum_value(TypeIndex type, int n);
// If none of the above is true, the type is some extension type. It

View File

@ -40,6 +40,7 @@ extern "C" {
EXPCL_PYSTUB int PyErr_ExceptionMatches(...);
EXPCL_PYSTUB int PyErr_Fetch(...);
EXPCL_PYSTUB int PyErr_Format(...);
EXPCL_PYSTUB int PyErr_NoMemory(...);
EXPCL_PYSTUB int PyErr_Occurred(...);
EXPCL_PYSTUB int PyErr_Print(...);
EXPCL_PYSTUB int PyErr_Restore(...);
@ -214,6 +215,7 @@ int PyErr_Clear(...) { return 0; };
int PyErr_ExceptionMatches(...) { return 0; };
int PyErr_Fetch(...) { return 0; }
int PyErr_Format(...) { return 0; };
int PyErr_NoMemory(...) { return 0; }
int PyErr_Occurred(...) { return 0; }
int PyErr_Print(...) { return 0; }
int PyErr_Restore(...) { return 0; }

View File

@ -2877,14 +2877,8 @@ TargetAdd('p3interrogatedb_composite2.obj', opts=OPTS, input='p3interrogatedb_co
#
OPTS=['DIR:dtool/metalibs/dtoolconfig', 'BUILDING:DTOOLCONFIG']
if (PkgSkip("PYTHON")):
TargetAdd('p3dtoolconfig_pydtool.obj', opts=OPTS, input="null.cxx")
else:
TargetAdd('p3dtoolconfig_pydtool.obj', opts=OPTS, input="pydtool.cxx")
TargetAdd('p3dtoolconfig_dtoolconfig.obj', opts=OPTS, input='dtoolconfig.cxx')
TargetAdd('p3dtoolconfig_pydtool.obj', dep='dtool_have_python.dat')
TargetAdd('libp3dtoolconfig.dll', input='p3dtoolconfig_dtoolconfig.obj')
TargetAdd('libp3dtoolconfig.dll', input='p3dtoolconfig_pydtool.obj')
TargetAdd('libp3dtoolconfig.dll', input='p3interrogatedb_composite1.obj')
TargetAdd('libp3dtoolconfig.dll', input='p3interrogatedb_composite2.obj')
TargetAdd('libp3dtoolconfig.dll', input='p3dconfig_composite1.obj')
@ -2893,6 +2887,13 @@ TargetAdd('libp3dtoolconfig.dll', input='p3prc_composite2.obj')
TargetAdd('libp3dtoolconfig.dll', input='libp3dtool.dll')
TargetAdd('libp3dtoolconfig.dll', opts=['ADVAPI', 'OPENSSL', 'WINGDI', 'WINUSER'])
if not PkgSkip("PYTHON"):
TargetAdd('dtoolconfig_pydtool.obj', opts=OPTS, input="pydtool.cxx")
TargetAdd('dtoolconfig.pyd', input='dtoolconfig_pydtool.obj')
TargetAdd('dtoolconfig.pyd', input='libp3dtoolconfig.dll')
TargetAdd('dtoolconfig.pyd', input='libp3dtool.dll')
TargetAdd('dtoolconfig.pyd', opts=['PYTHON'])
#
# DIRECTORY: dtool/src/pystub/
#

View File

@ -430,6 +430,8 @@ def GetBison():
# We don't strictly need it, so don't give an error
return None
return BISON
FLEX = None
def GetFlex():
global FLEX
@ -445,6 +447,8 @@ def GetFlex():
# We don't strictly need it, so don't give an error
return None
return FLEX
########################################################################
##
## LocateBinary
@ -1842,13 +1846,18 @@ def SdkLocatePython(force_use_sys_executable = False):
exit("Could not find %s!" % SDK["PYTHONEXEC"])
# Determine which version it is by checking which dll is in the directory.
py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9].dll")
if (GetOptimize() <= 2):
py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9]_d.dll")
else:
py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9].dll")
if len(py_dlls) == 0:
exit("Could not find the Python dll in %s." % (SDK["PYTHON"]))
elif len(py_dlls) > 1:
exit("Found multiple Python dlls in %s." % (SDK["PYTHON"]))
SDK["PYTHONVERSION"] = "python" + py_dlls[0][-6] + "." + py_dlls[0][-5]
py_dll = os.path.basename(py_dlls[0])
SDK["PYTHONVERSION"] = "python" + py_dll[6] + "." + py_dll[7]
elif (GetTarget() == 'windows'):
SDK["PYTHON"] = os.path.dirname(sysconfig.get_python_inc())
@ -2581,7 +2590,7 @@ def CalcLocation(fn, ipath):
if (fn.endswith(".res")): return OUTPUTDIR+"/tmp/"+fn
if (fn.endswith(".tlb")): return OUTPUTDIR+"/tmp/"+fn
if (fn.endswith(".dll")): return OUTPUTDIR+"/bin/"+fn[:-4]+dllext+".dll"
if (fn.endswith(".pyd")): return OUTPUTDIR+"/panda3d/"+fn[:-4]+dllext+".pyd"
if (fn.endswith(".pyd")): return OUTPUTDIR+"/panda3d/"+fn[:-4]+".pyd"
if (fn.endswith(".ocx")): return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".ocx"
if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".mll"
if (fn.endswith(".dlo")): return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".dlo"

View File

@ -668,3 +668,35 @@ set_transform_dirty() {
transform_changed();
}
////////////////////////////////////////////////////////////////////
// Function: BulletBodyNode::get_shape_bounds
// Access: Published
// Description: Returns the current bounds of all collision shapes
// owned by this body.
////////////////////////////////////////////////////////////////////
BoundingSphere BulletBodyNode::
get_shape_bounds() const {
/*
btTransform tr;
tr.setIdentity();
btVector3 aabbMin,aabbMax;
ptr()->getAabb(tr,aabbMin,aabbMax);
btVector3 o = tr.getOrigin();
cout << "aabbMin " << aabbMin.x() << " " << aabbMin.y() << " " << aabbMin.z() << endl;
cout << "aabbMax " << aabbMax.x() << " " << aabbMax.y() << " " << aabbMax.z() << endl;
cout << "origin " << aabbMin.x() << " " << aabbMin.y() << " " << aabbMin.z() << endl;
*/
btVector3 center;
btScalar radius;
if (_shape) {
_shape->getBoundingSphere(center, radius);
}
BoundingSphere bounds(btVector3_to_LPoint3(center), (PN_stdfloat)radius);
return bounds;
}

View File

@ -24,6 +24,7 @@
#include "collideMask.h"
#include "collisionNode.h"
#include "transformState.h"
#include "boundingSphere.h"
class BulletShape;
@ -47,6 +48,7 @@ PUBLISHED:
LPoint3 get_shape_pos(int idx) const;
LMatrix4 get_shape_mat(int idx) const;
BoundingSphere get_shape_bounds() const;
void add_shapes_from_collision_solids(CollisionNode *cnode);

View File

@ -73,3 +73,31 @@ set_local_scale(const LVecBase3 &scale) {
ptr()->setLocalScaling(LVecBase3_to_btVector3(scale));
}
////////////////////////////////////////////////////////////////////
// Function: BulletShape::get_shape_bounds
// Access: Published
// Description: Returns the current bounds of this collision shape.
////////////////////////////////////////////////////////////////////
BoundingSphere BulletShape::
get_shape_bounds() const {
/*
btTransform tr;
tr.setIdentity();
btVector3 aabbMin,aabbMax;
ptr()->getAabb(tr,aabbMin,aabbMax);
btVector3 o = tr.getOrigin();
cout << "aabbMin " << aabbMin.x() << " " << aabbMin.y() << " " << aabbMin.z() << endl;
cout << "aabbMax " << aabbMax.x() << " " << aabbMax.y() << " " << aabbMax.z() << endl;
cout << "origin " << aabbMin.x() << " " << aabbMin.y() << " " << aabbMin.z() << endl;
*/
btVector3 center;
btScalar radius;
ptr()->getBoundingSphere(center, radius);
BoundingSphere bounds(btVector3_to_LPoint3(center), (PN_stdfloat)radius);
return bounds;
}

View File

@ -20,6 +20,7 @@
#include "bullet_includes.h"
#include "typedReferenceCount.h"
#include "boundingSphere.h"
////////////////////////////////////////////////////////////////////
// Class : BulletShape
@ -43,6 +44,8 @@ PUBLISHED:
PN_stdfloat get_margin() const;
BoundingSphere get_shape_bounds() const;
public:
virtual btCollisionShape *ptr() const = 0;

View File

@ -18,6 +18,7 @@
#include "collisionPolygon.h"
#include "config_collide.h"
#include "dcast.h"
#include "epvector.h"
TypeHandle CollisionHandlerPusher::_type_handle;
@ -95,7 +96,7 @@ handle_entries() {
// shove. We hack around this by testing if two shove vectors
// share nearly the same direction, and if so, we keep only the
// longer of the two.
typedef epvector<ShoveData> Shoves;
Shoves shoves;
@ -110,13 +111,13 @@ handle_entries() {
LPoint3 interior_point;
if (!entry->get_all(def._target, surface_point, normal, interior_point)) {
#ifndef NDEBUG
#ifndef NDEBUG
if (collide_cat.is_debug()) {
collide_cat.debug()
<< "Cannot shove on " << from_node_path << " for collision into "
<< entry->get_into_node_path() << "; no normal/depth information.\n";
}
#endif
#endif
} else {
// Shove it just enough to clear the volume.
if (!surface_point.almost_equal(interior_point)) {

View File

@ -38,6 +38,7 @@
#include "geomLinestrips.h"
#include "geomVertexWriter.h"
#include "renderState.h"
#include "epvector.h"
#include <algorithm>
@ -1491,14 +1492,14 @@ fillin(DatagramIterator &scan, BamReader *manager) {
if (_points.size() >= 3) {
LMatrix4 to_3d_mat;
rederive_to_3d_mat(to_3d_mat);
epvector<LPoint3> verts;
verts.reserve(_points.size());
Points::const_iterator pi;
for (pi = _points.begin(); pi != _points.end(); ++pi) {
verts.push_back(to_3d((*pi)._p, to_3d_mat));
}
const LPoint3 *verts_begin = &verts[0];
const LPoint3 *verts_end = verts_begin + verts.size();
setup_points(verts_begin, verts_end);

View File

@ -331,6 +331,32 @@ get_target_tex_page() const {
return cdata->_target_tex_page;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayRegion::set_scissor_enabled
// Access: Published
// Description: Sets whether or not scissor testing is enabled
// for this region. The default is true, except for
// the overlay display region.
////////////////////////////////////////////////////////////////////
INLINE void DisplayRegion::
set_scissor_enabled(bool scissor_enabled) {
CDWriter cdata(_cycler);
cdata->_scissor_enabled = scissor_enabled;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayRegion::get_scissor_enabled
// Access: Published
// Description: Returns whether or not scissor testing is enabled
// for this region. The default is true, except for
// the overlay display region.
////////////////////////////////////////////////////////////////////
INLINE bool DisplayRegion::
get_scissor_enabled() const {
CDReader cdata(_cycler);
return cdata->_scissor_enabled;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayRegion::set_cull_callback
// Access: Published
@ -941,6 +967,18 @@ get_target_tex_page() const {
return _cdata->_target_tex_page;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayRegionPipelineReader::get_scissor_enabled
// Access: Published
// Description: Returns whether or not scissor testing is enabled
// for this region. The default is true, except for
// the overlay display region.
////////////////////////////////////////////////////////////////////
INLINE bool DisplayRegionPipelineReader::
get_scissor_enabled() const {
return _cdata->_scissor_enabled;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayRegionPipelineReader::get_draw_callback
// Access: Published

View File

@ -392,7 +392,7 @@ get_cull_traverser() {
// Access: Published, Virtual
// Description: This is a special parameter that is only used when
// rendering the faces of a cube map or multipage and/or
// multiview texture.
// multiview texture.
//
// This sets up the DisplayRegion to render to the ith
// page and jth view of its associated texture(s); the
@ -832,7 +832,8 @@ CData() :
_sort(0),
_stereo_channel(Lens::SC_mono),
_tex_view_offset(0),
_target_tex_page(-1)
_target_tex_page(-1),
_scissor_enabled(true)
{
_regions.push_back(Region());
}
@ -852,7 +853,8 @@ CData(const DisplayRegion::CData &copy) :
_sort(copy._sort),
_stereo_channel(copy._stereo_channel),
_tex_view_offset(copy._tex_view_offset),
_target_tex_page(copy._target_tex_page)
_target_tex_page(copy._target_tex_page),
_scissor_enabled(copy._scissor_enabled)
{
}

View File

@ -38,6 +38,7 @@
#include "cullTraverser.h"
#include "callbackObject.h"
#include "luse.h"
#include "epvector.h"
class GraphicsOutput;
class GraphicsPipe;
@ -120,6 +121,9 @@ PUBLISHED:
virtual void set_target_tex_page(int page);
INLINE int get_target_tex_page() const;
INLINE void set_scissor_enabled(bool scissor_enabled);
INLINE bool get_scissor_enabled() const;
INLINE void set_cull_callback(CallbackObject *object);
INLINE void clear_cull_callback();
INLINE CallbackObject *get_cull_callback() const;
@ -172,7 +176,7 @@ public:
LVecBase4i _pixels;
LVecBase4i _pixels_i;
};
typedef pvector<Region> Regions;
typedef epvector<Region> Regions;
private:
class CData;
@ -214,15 +218,16 @@ private:
Regions _regions;
int _lens_index; // index into which lens of a camera is associated with this display region. 0 is default
NodePath _camera;
Camera *_camera_node;
bool _active;
int _sort;
Lens::StereoChannel _stereo_channel;
int _tex_view_offset;
int _target_tex_page;
bool _scissor_enabled;
PT(CallbackObject) _cull_callback;
PT(CallbackObject) _draw_callback;
@ -323,6 +328,7 @@ public:
INLINE int get_tex_view_offset();
INLINE bool get_clear_depth_between_eyes() const;
INLINE int get_target_tex_page() const;
INLINE bool get_scissor_enabled() const;
INLINE CallbackObject *get_draw_callback() const;
INLINE void get_pixels(int &pl, int &pr, int &pb, int &pt) const;

View File

@ -41,19 +41,19 @@ GraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
<< "Creating new offscreen buffer " << get_name() << "\n";
}
_overlay_display_region->compute_pixels(_x_size, _y_size);
_overlay_display_region->compute_pixels(_size.get_x(), _size.get_y());
_open_request = OR_none;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsBuffer::Destructor
// Access: Published, Virtual
// Description:
// Description:
////////////////////////////////////////////////////////////////////
GraphicsBuffer::
~GraphicsBuffer() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsBuffer::set_size
// Access: Public, Virtual

View File

@ -40,7 +40,7 @@ protected:
PUBLISHED:
virtual ~GraphicsBuffer();
void set_size(int x, int y);
virtual void set_size(int x, int y);
public:
virtual void request_open();

View File

@ -150,6 +150,25 @@ get_rtm_mode(int i) const {
return cdata->_textures[i]._rtm_mode;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_size
// Access: Published
// Description: Returns the visible size of the window or buffer, if
// it is known. In certain cases (e.g. fullscreen
// windows), the size may not be known until after the
// object has been fully created. Check has_size()
// first.
//
// Certain objects (like windows) may change size
// spontaneously; this method is not thread-safe. To
// get the size of a window in a thread-safe manner,
// query get_properties().
////////////////////////////////////////////////////////////////////
INLINE const LVecBase2i &GraphicsOutput::
get_size() const {
return _size;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_x_size
// Access: Published
@ -166,7 +185,7 @@ get_rtm_mode(int i) const {
////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput::
get_x_size() const {
return _x_size;
return _size.get_x();
}
////////////////////////////////////////////////////////////////////
@ -185,7 +204,7 @@ get_x_size() const {
////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput::
get_y_size() const {
return _y_size;
return _size.get_y();
}
////////////////////////////////////////////////////////////////////
@ -198,7 +217,7 @@ get_y_size() const {
////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput::
get_fb_x_size() const {
return max(int(_x_size * get_pixel_factor()), 1);
return max(int(_size.get_x() * get_pixel_factor()), 1);
}
////////////////////////////////////////////////////////////////////
@ -211,7 +230,7 @@ get_fb_x_size() const {
////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput::
get_fb_y_size() const {
return max(int(_y_size * get_pixel_factor()), 1);
return max(int(_size.get_y() * get_pixel_factor()), 1);
}
////////////////////////////////////////////////////////////////////
@ -226,7 +245,7 @@ get_fb_y_size() const {
INLINE int GraphicsOutput::
get_sbs_left_x_size() const {
PN_stdfloat left_w = _sbs_left_dimensions[1] - _sbs_left_dimensions[0];
return max(int(_x_size * left_w), 1);
return max(int(_size.get_x() * left_w), 1);
}
////////////////////////////////////////////////////////////////////
@ -241,7 +260,7 @@ get_sbs_left_x_size() const {
INLINE int GraphicsOutput::
get_sbs_left_y_size() const {
PN_stdfloat left_h = _sbs_left_dimensions[3] - _sbs_left_dimensions[2];
return max(int(_y_size * left_h), 1);
return max(int(_size.get_y() * left_h), 1);
}
////////////////////////////////////////////////////////////////////
@ -256,7 +275,7 @@ get_sbs_left_y_size() const {
INLINE int GraphicsOutput::
get_sbs_right_x_size() const {
PN_stdfloat right_w = _sbs_right_dimensions[1] - _sbs_right_dimensions[0];
return max(int(_x_size * right_w), 1);
return max(int(_size.get_x() * right_w), 1);
}
////////////////////////////////////////////////////////////////////
@ -271,7 +290,7 @@ get_sbs_right_x_size() const {
INLINE int GraphicsOutput::
get_sbs_right_y_size() const {
PN_stdfloat right_h = _sbs_right_dimensions[3] - _sbs_right_dimensions[2];
return max(int(_y_size * right_h), 1);
return max(int(_size.get_y() * right_h), 1);
}
////////////////////////////////////////////////////////////////////

View File

@ -78,7 +78,8 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
bool default_stereo_flags) :
_lock("GraphicsOutput"),
_cull_window_pcollector(_cull_pcollector, name),
_draw_window_pcollector(_draw_pcollector, name)
_draw_window_pcollector(_draw_pcollector, name),
_size(0, 0)
{
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);
@ -90,13 +91,11 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
_fb_properties = fb_prop;
_name = name;
_creation_flags = flags;
_x_size = _y_size = 0;
_has_size = win_prop.has_size();
_is_nonzero_size = false;
if (_has_size) {
_x_size = win_prop.get_x_size();
_y_size = win_prop.get_y_size();
_is_nonzero_size = (_x_size > 0 && _y_size > 0);
_size = win_prop.get_size();
_is_nonzero_size = (_size[0] > 0 && _size[1] > 0);
}
if (_creation_flags & GraphicsPipe::BF_size_track_host) {
// If we're tracking the host size, we assume we'll be nonzero
@ -152,6 +151,7 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
// clear() and get_screenshot().
_overlay_display_region = make_mono_display_region(0.0f, 1.0f, 0.0f, 1.0f);
_overlay_display_region->set_active(false);
_overlay_display_region->set_scissor_enabled(false);
// Make sure the "active" flag is set true for pipeline stage 0.
{
@ -546,14 +546,14 @@ set_inverted(bool inverted) {
if (_inverted != inverted) {
_inverted = inverted;
if (_y_size != 0) {
if (get_y_size() != 0) {
// All of our DisplayRegions need to recompute their pixel
// positions now.
TotalDisplayRegions::iterator dri;
for (dri = _total_display_regions.begin();
dri != _total_display_regions.end();
++dri) {
(*dri)->compute_pixels(_x_size, _y_size);
(*dri)->compute_pixels(get_x_size(), get_y_size());
}
}
}
@ -1102,7 +1102,7 @@ make_cube_map(const string &name, int size, NodePath &camera_rig,
NodePath GraphicsOutput::
get_texture_card() {
if (_texture_card == 0) {
PT(GeomVertexData) vdata = create_texture_card_vdata(_x_size, _y_size);
PT(GeomVertexData) vdata = create_texture_card_vdata(get_x_size(), get_y_size());
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
strip->set_shade_model(Geom::SM_uniform);
strip->add_next_vertices(4);
@ -1262,11 +1262,10 @@ clear_pipe() {
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
set_size_and_recalc(int x, int y) {
_x_size = x;
_y_size = y;
_size.set(x, y);
_has_size = true;
_is_nonzero_size = (_x_size > 0 && _y_size > 0);
_is_nonzero_size = (x > 0 && y > 0);
int fb_x_size = get_fb_x_size();
int fb_y_size = get_fb_y_size();
@ -1498,7 +1497,7 @@ process_events() {
void GraphicsOutput::
pixel_factor_changed() {
if (_has_size) {
set_size_and_recalc(_x_size, _y_size);
set_size_and_recalc(get_x_size(), get_y_size());
}
}

View File

@ -128,10 +128,11 @@ PUBLISHED:
INLINE RenderTexturePlane get_texture_plane(int i=0) const;
INLINE RenderTextureMode get_rtm_mode(int i=0) const;
void clear_render_textures();
void add_render_texture(Texture *tex, RenderTextureMode mode,
void add_render_texture(Texture *tex, RenderTextureMode mode,
RenderTexturePlane bitplane=RTP_COUNT);
void setup_render_texture(Texture *tex, bool allow_bind, bool to_ram);
INLINE const LVecBase2i &get_size() const;
INLINE int get_x_size() const;
INLINE int get_y_size() const;
INLINE int get_fb_x_size() const;
@ -290,7 +291,7 @@ protected:
private:
PT(GeomVertexData) create_texture_card_vdata(int x, int y);
DisplayRegion *add_display_region(DisplayRegion *display_region);
bool do_remove_display_region(DisplayRegion *display_region);
@ -323,7 +324,7 @@ protected:
RenderTextureMode _rtm_mode;
};
typedef pvector<RenderTexture> RenderTextures;
private:
int _sort;
int _child_sort;
@ -346,9 +347,9 @@ protected:
// have, we don't auto-close the buffer (since that would deallocate
// the memory associated with the texture).
pvector<WPT(Texture)> _hold_textures;
protected:
LightMutex _lock;
LightMutex _lock;
// protects _display_regions.
PT(DisplayRegion) _overlay_display_region;
typedef pvector< PT(DisplayRegion) > TotalDisplayRegions;
@ -382,8 +383,7 @@ protected:
protected:
int _creation_flags;
int _x_size;
int _y_size;
LVecBase2i _size;
bool _has_size;
bool _is_valid;
bool _is_nonzero_size;
@ -394,7 +394,7 @@ protected:
static PStatCollector _draw_pcollector;
PStatCollector _cull_window_pcollector;
PStatCollector _draw_window_pcollector;
public:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -170,8 +170,7 @@ request_properties(const WindowProperties &requested_properties) {
// stick. This is helpful for the MultitexReducer, which needs to
// know the size of the textures that it will be working with,
// even if the texture hasn't been fully generated yet.
_x_size = _requested_properties.get_x_size();
_y_size = _requested_properties.get_y_size();
_size = _requested_properties.get_size();
// Don't set _has_size yet, because we don't really know yet.
}

View File

@ -27,15 +27,15 @@ TypeHandle ParasiteBuffer::_type_handle;
ParasiteBuffer::
ParasiteBuffer(GraphicsOutput *host, const string &name,
int x_size, int y_size, int flags) :
GraphicsOutput(host->get_engine(), host->get_pipe(),
GraphicsOutput(host->get_engine(), host->get_pipe(),
name, host->get_fb_properties(),
WindowProperties::size(x_size, y_size), flags,
WindowProperties::size(x_size, y_size), flags,
host->get_gsg(), host, false)
{
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);
#endif
if (display_cat.is_debug()) {
display_cat.debug()
<< "Creating new parasite buffer " << get_name()
@ -43,25 +43,24 @@ ParasiteBuffer(GraphicsOutput *host, const string &name,
}
_creation_flags = flags;
if (flags & GraphicsPipe::BF_size_track_host) {
x_size = host->get_x_size();
y_size = host->get_y_size();
_size = host->get_size();
} else {
_size.set(x_size, y_size);
}
_x_size = x_size;
_y_size = y_size;
_has_size = true;
_overlay_display_region->compute_pixels(_x_size, _y_size);
_overlay_display_region->compute_pixels(_size.get_x(), _size.get_y());
_is_valid = true;
set_inverted(host->get_gsg()->get_copy_texture_inverted());
}
////////////////////////////////////////////////////////////////////
// Function: ParasiteBuffer::Destructor
// Access: Published, Virtual
// Description:
// Description:
////////////////////////////////////////////////////////////////////
ParasiteBuffer::
~ParasiteBuffer() {
@ -201,19 +200,18 @@ begin_frame(FrameMode mode, Thread *current_thread) {
}
if (_creation_flags & GraphicsPipe::BF_size_track_host) {
if ((_host->get_x_size() != _x_size)||
(_host->get_y_size() != _y_size)) {
if (_host->get_size() != _size) {
set_size_and_recalc(_host->get_x_size(),
_host->get_y_size());
}
} else {
if (_host->get_x_size() < _x_size ||
_host->get_y_size() < _y_size) {
set_size_and_recalc(min(_x_size, _host->get_x_size()),
min(_y_size, _host->get_y_size()));
if (_host->get_x_size() < get_x_size() ||
_host->get_y_size() < get_y_size()) {
set_size_and_recalc(min(get_x_size(), _host->get_x_size()),
min(get_y_size(), _host->get_y_size()));
}
}
clear_cube_map_selection();
return true;
}

View File

@ -229,14 +229,13 @@ rebuild_bitplanes() {
// Decide how big the bitplanes should be.
if ((_host != 0)&&(_creation_flags & GraphicsPipe::BF_size_track_host)) {
if ((_host->get_x_size() != _x_size)||
(_host->get_y_size() != _y_size)) {
if (_host->get_size() != _size) {
set_size_and_recalc(_host->get_x_size(),
_host->get_y_size());
}
}
int bitplane_x = _x_size;
int bitplane_y = _y_size;
int bitplane_x = get_x_size();
int bitplane_y = get_y_size();
if (Texture::get_textures_power_2() != ATS_none) {
bitplane_x = Texture::up_to_power_2(bitplane_x);
bitplane_y = Texture::up_to_power_2(bitplane_y);
@ -350,7 +349,7 @@ rebuild_bitplanes() {
<< "Unable to re-create texture " << *depth_ctx->get_texture() << endl;
return false;
}
if (depth_tex->get_texture_type() == Texture::TT_2d_texture) {
depth_d3d_tex = depth_ctx->_d3d_2d_texture;
nassertr(depth_d3d_tex != 0, false);

View File

@ -276,25 +276,24 @@ rebuild_bitplanes() {
IDirect3DSurface9 *color_surf = 0;
IDirect3DSurface9 *depth_surf = 0;
DWORD render_target_index;
render_target_index = 0;
// Decide how big the bitplanes should be.
if ((_host != 0)&&(_creation_flags & GraphicsPipe::BF_size_track_host)) {
if ((_host->get_x_size() != _x_size)||
(_host->get_y_size() != _y_size)) {
if (_host->get_size() != _size) {
set_size_and_recalc(_host->get_x_size(),
_host->get_y_size());
}
}
int bitplane_x = _x_size;
int bitplane_y = _y_size;
int bitplane_x = get_x_size();
int bitplane_y = get_y_size();
if (Texture::get_textures_power_2() != ATS_none) {
bitplane_x = Texture::up_to_power_2(bitplane_x);
bitplane_y = Texture::up_to_power_2(bitplane_y);
}
// Find the color and depth textures. Either may be present,
// or neither.
//
@ -342,7 +341,7 @@ rebuild_bitplanes() {
}
break;
}
}
}
}
}
@ -373,7 +372,7 @@ rebuild_bitplanes() {
_color_backing_store = NULL;
}
color_tex = get_texture(color_tex_index);
color_tex->set_size_padded(_x_size, _y_size);
color_tex->set_size_padded(get_x_size(), get_y_size());
// color_tex->set_format(Texture::F_rgba);
color_ctx =
DCAST(DXTextureContext9,
@ -445,14 +444,14 @@ rebuild_bitplanes() {
_depth_backing_store = NULL;
}
if (_shared_depth_buffer) {
if (_shared_depth_buffer) {
depth_tex = _shared_depth_buffer -> get_texture(depth_tex_index);
}
if (depth_tex == 0) {
if (depth_tex == 0) {
depth_tex = get_texture(depth_tex_index);
}
depth_tex->set_size_padded(_x_size, _y_size);
depth_tex->set_size_padded(get_x_size(), get_y_size());
depth_tex->set_format(Texture::F_depth_stencil);
depth_ctx =
DCAST(DXTextureContext9,
@ -855,7 +854,7 @@ share_depth_buffer(GraphicsOutput *graphics_output) {
if (_debug) {
printf ("share_depth_buffer\n");
}
// check buffer sizes
if (this -> get_x_size() != input_graphics_output -> get_x_size()) {
if (_debug) {

View File

@ -27,6 +27,7 @@
#include "eggVertex.h"
#include "eggTextureCollection.h"
#include "eggMaterialCollection.h"
#include "epvector.h"
#include "pt_EggTexture.h"
#include "pt_EggMaterial.h"
#include "config_egg.h"

View File

@ -21,7 +21,7 @@
#include "indent.h"
#include "pvector.h"
#include "epvector.h"
////////////////////////////////////////////////////////////////////
// Class : EggMorphList

View File

@ -73,11 +73,11 @@ PUBLISHED:
virtual void transform(const LMatrix4d &mat);
public:
double _switch_in, _switch_out, _fade;
LPoint3d _center;
public:
static TypeHandle get_class_type() {
return _type_handle;
}

View File

@ -1,3 +1,5 @@
defconstruct TypeHandle new TypeHandle(TypeHandle::none())
forcetype PandaSystem
forcetype DSearchPath
forcetype DSearchPath::Results

View File

@ -155,8 +155,7 @@ begin_frame(FrameMode mode, Thread *current_thread) {
}
}
if (_creation_flags & GraphicsPipe::BF_size_track_host) {
if ((_host->get_x_size() != _x_size)||
(_host->get_y_size() != _y_size)) {
if (_host->get_size() != _size) {
// We also need to rebuild if we need to change size.
_needs_rebuild = true;
}
@ -277,14 +276,14 @@ rebuild_bitplanes() {
// Calculate bitplane size. This can be larger than the buffer.
if (_creation_flags & GraphicsPipe::BF_size_track_host) {
if ((_host->get_x_size() != _x_size)||
(_host->get_y_size() != _y_size)) {
if (_host->get_size() != _size) {
set_size_and_recalc(_host->get_x_size(),
_host->get_y_size());
}
}
int bitplane_x = _x_size;
int bitplane_y = _y_size;
int bitplane_x = get_x_size();
int bitplane_y = get_y_size();
if (Texture::get_textures_power_2() != ATS_none) {
bitplane_x = Texture::up_to_power_2(bitplane_x);
bitplane_y = Texture::up_to_power_2(bitplane_y);
@ -602,7 +601,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
if (tex->get_texture_type() != Texture::TT_cube_map && _rb_size_z > 1) {
tex->set_z_size(_rb_size_z);
}
tex->set_pad_size(_rb_size_x - _x_size, _rb_size_y - _y_size);
tex->set_pad_size(_rb_size_x - get_x_size(), _rb_size_y - get_y_size());
// Adjust the texture format based on the requested framebuffer settings.
switch (slot) {
@ -1072,6 +1071,10 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) {
gtc->set_active(true);
_texture_contexts.push_back(gtc);
// It seems that binding the texture is necessary before binding
// to a framebuffer attachment.
glgsg->apply_texture(gtc);
#ifndef OPENGLES
GLclampf priority = 1.0f;
glPrioritizeTextures(1, &gtc->_index, &priority);
@ -1191,7 +1194,7 @@ end_frame(FrameMode mode, Thread *current_thread) {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsBuffer)::
set_size(int x, int y) {
if (_x_size != x || _y_size != y) {
if (_size.get_x() != x || _size.get_y() != y) {
_needs_rebuild = true;
}
@ -1280,7 +1283,7 @@ open_buffer() {
// A lot of code seems to depend on being able to get a
// color buffer by just setting the rgb_color bit.
if (_fb_properties.get_color_bits() == 0 &&
_fb_properties.get_rgb_color() > 0) {
_fb_properties.get_rgb_color()) {
_fb_properties.set_color_bits(1);
}

View File

@ -310,6 +310,8 @@ CLP(GraphicsStateGuardian)(GraphicsEngine *engine, GraphicsPipe *pipe) :
_check_errors = gl_check_errors;
_force_flush = gl_force_flush;
_scissor_enabled = false;
#ifdef DO_PSTATS
if (gl_finish) {
GLCAT.warning()
@ -1423,6 +1425,7 @@ reset() {
}
_glDrawBuffers = NULL;
_glClearBufferfv = NULL;
#ifndef OPENGLES
if (is_at_least_gl_version(2, 0)) {
_glDrawBuffers = (PFNGLDRAWBUFFERSPROC)
@ -1438,6 +1441,11 @@ reset() {
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers);
_max_color_targets = max_draw_buffers;
}
if (is_at_least_gl_version(3, 0)) {
_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)
get_extension_func("glClearBufferfv");
}
#endif // OPENGLES
#ifndef OPENGLES
@ -2178,9 +2186,7 @@ clear(DrawableRegion *clearable) {
PStatTimer timer(_clear_pcollector);
report_my_gl_errors();
if ((!clearable->get_clear_color_active())&&
(!clearable->get_clear_depth_active())&&
(!clearable->get_clear_stencil_active())) {
if (!clearable->is_any_clear_active()) {
return;
}
@ -2188,59 +2194,113 @@ clear(DrawableRegion *clearable) {
int mask = 0;
for (int i=0; i<_current_properties->get_aux_rgba(); i++) {
int layerid = GraphicsOutput::RTP_aux_rgba_0 + i;
int layerbit = RenderBuffer::T_aux_rgba_0 << i;
if (clearable->get_clear_active(layerid)) {
LColor v = clearable->get_clear_value(layerid);
glClearColor(v[0],v[1],v[2],v[3]);
set_draw_buffer(layerbit);
glClear(GL_COLOR_BUFFER_BIT);
}
}
for (int i=0; i<_current_properties->get_aux_hrgba(); i++) {
int layerid = GraphicsOutput::RTP_aux_hrgba_0 + i;
int layerbit = RenderBuffer::T_aux_hrgba_0 << i;
if (clearable->get_clear_active(layerid)) {
LColor v = clearable->get_clear_value(layerid);
glClearColor(v[0],v[1],v[2],v[3]);
set_draw_buffer(layerbit);
glClear(GL_COLOR_BUFFER_BIT);
}
}
for (int i=0; i<_current_properties->get_aux_float(); i++) {
int layerid = GraphicsOutput::RTP_aux_float_0 + i;
int layerbit = RenderBuffer::T_aux_float_0 << i;
if (clearable->get_clear_active(layerid)) {
LColor v = clearable->get_clear_value(layerid);
glClearColor(v[0],v[1],v[2],v[3]);
set_draw_buffer(layerbit);
glClear(GL_COLOR_BUFFER_BIT);
}
}
#ifndef OPENGLES
if (_current_fbo != 0 && _glClearBufferfv != NULL) {
// We can use glClearBuffer to clear all the color attachments,
// which protects us from the overhead of having to call set_draw_buffer
// for every single attachment.
int index = 0;
// In the past, it was possible to set the draw buffer
// once in prepare_display_region and then forget about it.
// Now, with aux layers, it is necessary to occasionally
// change the draw buffer. In time, I think there will need
// to be a draw buffer attrib. Until then, this little hack
// to put things back the way they were after
// prepare_display_region will do.
set_draw_buffer(_draw_buffer_type);
if (_current_properties->get_color_bits() > 0) {
if (clearable->get_clear_color_active()) {
LColor v = clearable->get_clear_color();
glClearColor(v[0],v[1],v[2],v[3]);
if (gl_color_mask) {
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
if (_current_properties->get_color_bits() > 0) {
if (_current_properties->is_stereo()) {
// Clear both left and right attachments.
if (clearable->get_clear_active(GraphicsOutput::RTP_color)) {
LColorf v = LCAST(float, clearable->get_clear_value(GraphicsOutput::RTP_color));
_glClearBufferfv(GL_COLOR, index, v.get_data());
_glClearBufferfv(GL_COLOR, index + 1, v.get_data());
}
index += 2;
} else {
if (clearable->get_clear_active(GraphicsOutput::RTP_color)) {
LColorf v = LCAST(float, clearable->get_clear_value(GraphicsOutput::RTP_color));
_glClearBufferfv(GL_COLOR, index, v.get_data());
}
++index;
}
}
for (int i = 0; i < _current_properties->get_aux_rgba(); ++i) {
int layerid = GraphicsOutput::RTP_aux_rgba_0 + i;
if (clearable->get_clear_active(layerid)) {
LColorf v = LCAST(float, clearable->get_clear_value(layerid));
_glClearBufferfv(GL_COLOR, index, v.get_data());
}
++index;
}
for (int i = 0; i < _current_properties->get_aux_hrgba(); ++i) {
int layerid = GraphicsOutput::RTP_aux_hrgba_0 + i;
if (clearable->get_clear_active(layerid)) {
LColorf v = LCAST(float, clearable->get_clear_value(layerid));
_glClearBufferfv(GL_COLOR, index, v.get_data());
}
++index;
}
for (int i = 0; i < _current_properties->get_aux_float(); ++i) {
int layerid = GraphicsOutput::RTP_aux_float_0 + i;
if (clearable->get_clear_active(layerid)) {
LColorf v = LCAST(float, clearable->get_clear_value(layerid));
_glClearBufferfv(GL_COLOR, index, v.get_data());
}
++index;
}
} else
#endif
{
if (_current_properties->get_aux_mask() != 0) {
for (int i = 0; i < _current_properties->get_aux_rgba(); ++i) {
int layerid = GraphicsOutput::RTP_aux_rgba_0 + i;
int layerbit = RenderBuffer::T_aux_rgba_0 << i;
if (clearable->get_clear_active(layerid)) {
LColor v = clearable->get_clear_value(layerid);
glClearColor(v[0], v[1], v[2], v[3]);
set_draw_buffer(layerbit);
glClear(GL_COLOR_BUFFER_BIT);
}
}
for (int i = 0; i < _current_properties->get_aux_hrgba(); ++i) {
int layerid = GraphicsOutput::RTP_aux_hrgba_0 + i;
int layerbit = RenderBuffer::T_aux_hrgba_0 << i;
if (clearable->get_clear_active(layerid)) {
LColor v = clearable->get_clear_value(layerid);
glClearColor(v[0], v[1], v[2], v[3]);
set_draw_buffer(layerbit);
glClear(GL_COLOR_BUFFER_BIT);
}
}
for (int i = 0; i < _current_properties->get_aux_float(); ++i) {
int layerid = GraphicsOutput::RTP_aux_float_0 + i;
int layerbit = RenderBuffer::T_aux_float_0 << i;
if (clearable->get_clear_active(layerid)) {
LColor v = clearable->get_clear_value(layerid);
glClearColor(v[0], v[1], v[2], v[3]);
set_draw_buffer(layerbit);
glClear(GL_COLOR_BUFFER_BIT);
}
}
// In the past, it was possible to set the draw buffer
// once in prepare_display_region and then forget about it.
// Now, with aux layers, it is necessary to occasionally
// change the draw buffer. In time, I think there will need
// to be a draw buffer attrib. Until then, this little hack
// to put things back the way they were after
// prepare_display_region will do.
set_draw_buffer(_draw_buffer_type);
}
if (_current_properties->get_color_bits() > 0) {
if (clearable->get_clear_color_active()) {
LColor v = clearable->get_clear_color();
glClearColor(v[0], v[1], v[2], v[3]);
if (gl_color_mask) {
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
_state_mask.clear_bit(ColorWriteAttrib::get_class_slot());
mask |= GL_COLOR_BUFFER_BIT;
}
_state_mask.clear_bit(ColorWriteAttrib::get_class_slot());
mask |= GL_COLOR_BUFFER_BIT;
}
}
if (clearable->get_clear_depth_active()) {
#ifdef OPENGLES
glClearDepthf(clearable->get_clear_depth());
@ -2311,12 +2371,18 @@ prepare_display_region(DisplayRegionPipelineReader *dr) {
_draw_buffer_type |= _current_properties->get_aux_mask();
set_draw_buffer(_draw_buffer_type);
glEnable(GL_SCISSOR_TEST);
if (dr->get_scissor_enabled()) {
glEnable(GL_SCISSOR_TEST);
_scissor_enabled = true;
} else {
glDisable(GL_SCISSOR_TEST);
_scissor_enabled = false;
}
if (_supports_viewport_arrays) {
int count = dr->get_num_regions();
GLfloat *viewports = new GLfloat[4 * count];
GLint *scissors = new GLint[4 * count];
GLfloat *viewports = (GLfloat *)alloca(sizeof(GLfloat) * 4 * count);
GLint *scissors = (GLint *)alloca(sizeof(GLint) * 4 * count);
for (int i = 0; i < count; ++i) {
GLint *sr = scissors + i * 4;
@ -2328,13 +2394,15 @@ prepare_display_region(DisplayRegionPipelineReader *dr) {
vr[3] = (GLfloat) sr[3];
}
_glViewportArrayv(0, count, viewports);
_glScissorArrayv(0, count, scissors);
delete[] viewports;
delete[] scissors;
if (dr->get_scissor_enabled()) {
_glScissorArrayv(0, count, scissors);
}
} else {
glScissor(x, y, width, height);
glViewport(x, y, width, height);
if (dr->get_scissor_enabled()) {
glScissor(x, y, width, height);
}
}
report_my_gl_errors();
@ -6322,19 +6390,19 @@ set_draw_buffer(int rbtype) {
++index;
}
}
for (int i=0; i<_current_properties->get_aux_rgba(); i++) {
for (int i = 0; i < _current_properties->get_aux_rgba(); ++i) {
if (rbtype & (RenderBuffer::T_aux_rgba_0 << i)) {
buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index;
}
++index;
}
for (int i=0; i<_current_properties->get_aux_hrgba(); i++) {
for (int i = 0; i < _current_properties->get_aux_hrgba(); ++i) {
if (rbtype & (RenderBuffer::T_aux_hrgba_0 << i)) {
buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index;
}
++index;
}
for (int i=0; i<_current_properties->get_aux_float(); i++) {
for (int i = 0; i < _current_properties->get_aux_float(); ++i) {
if (rbtype & (RenderBuffer::T_aux_float_0 << i)) {
buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index;
}
@ -6423,19 +6491,19 @@ set_read_buffer(int rbtype) {
}
++index;
}
for (int i=0; i<_current_properties->get_aux_rgba(); i++) {
for (int i = 0; i < _current_properties->get_aux_rgba(); ++i) {
if (rbtype & (RenderBuffer::T_aux_rgba_0 << i)) {
buffer = GL_COLOR_ATTACHMENT0_EXT + index;
}
++index;
}
for (int i=0; i<_current_properties->get_aux_hrgba(); i++) {
for (int i = 0; i < _current_properties->get_aux_hrgba(); ++i) {
if (rbtype & (RenderBuffer::T_aux_hrgba_0 << i)) {
buffer = GL_COLOR_ATTACHMENT0_EXT + index;
}
++index;
}
for (int i=0; i<_current_properties->get_aux_float(); i++) {
for (int i = 0; i < _current_properties->get_aux_float(); ++i) {
if (rbtype & (RenderBuffer::T_aux_float_0 << i)) {
buffer = GL_COLOR_ATTACHMENT0_EXT + index;
}
@ -6487,8 +6555,6 @@ set_read_buffer(int rbtype) {
#endif // OPENGLES
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::get_numeric_type
// Access: Protected, Static
@ -11056,7 +11122,6 @@ bind_fbo(GLuint fbo) {
_current_fbo = fbo;
}
////////////////////////////////////////////////////////////////////
// GL stencil code section
////////////////////////////////////////////////////////////////////
@ -11292,9 +11357,9 @@ do_issue_stencil() {
}
}
if (stencil -> get_render_state (StencilAttrib::SRS_clear)) {
if (stencil -> get_render_state (StencilAttrib::SRS_clear)) {
GLbitfield mask = 0;
// clear stencil buffer
glClearStencil(stencil -> get_render_state (StencilAttrib::SRS_clear_value));
mask |= GL_STENCIL_BUFFER_BIT;
@ -11310,18 +11375,30 @@ do_issue_stencil() {
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::do_issue_scissor
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
do_issue_scissor() {
const ScissorAttrib *target_scissor = DCAST(ScissorAttrib, _target_rs->get_attrib_def(ScissorAttrib::get_class_slot()));
const LVecBase4 &frame = target_scissor->get_frame();
int x = (int)(_viewport_x + _viewport_width * frame[0] + 0.5f);
int y = (int)(_viewport_y + _viewport_height * frame[2] + 0.5f);
int width = (int)(_viewport_width * (frame[1] - frame[0]) + 0.5f);
int height = (int)(_viewport_height * (frame[3] - frame[2]) + 0.5f);
if (target_scissor->is_off()) {
if (_scissor_enabled) {
glDisable(GL_SCISSOR_TEST);
_scissor_enabled = false;
}
} else {
if (!_scissor_enabled) {
glEnable(GL_SCISSOR_TEST);
_scissor_enabled = true;
}
glEnable(GL_SCISSOR_TEST);
glScissor(x, y, width, height);
const LVecBase4 &frame = target_scissor->get_frame();
int x = (int)(_viewport_x + _viewport_width * frame[0] + 0.5f);
int y = (int)(_viewport_y + _viewport_height * frame[2] + 0.5f);
int width = (int)(_viewport_width * (frame[1] - frame[0]) + 0.5f);
int height = (int)(_viewport_height * (frame[3] - frame[2]) + 0.5f);
glScissor(x, y, width, height);
}
}

View File

@ -88,6 +88,7 @@ typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
@ -528,6 +529,7 @@ protected:
PN_stdfloat _point_size;
bool _point_perspective;
bool _vertex_blending_enabled;
bool _scissor_enabled;
#ifndef OPENGLES_1
PT(Shader) _current_shader;
@ -689,6 +691,7 @@ public:
INLINE bool get_supports_framebuffer_blit();
PFNGLBLITFRAMEBUFFEREXTPROC _glBlitFramebuffer;
PFNGLDRAWBUFFERSPROC _glDrawBuffers;
PFNGLCLEARBUFFERFVPROC _glClearBufferfv;
int _max_fb_samples;
bool _supports_viewport_arrays;
bool _supports_bindless_texture;

View File

@ -267,6 +267,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
if (size > 6 && matrix_name.compare(size - 6, 6, "Matrix") == 0) {
Shader::ShaderMatSpec bind;
bind._id = arg_id;
bind._func = Shader::SMF_compose;
if (transpose) {
bind._piece = Shader::SMP_transpose;
} else {
@ -274,9 +275,10 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
}
bind._arg[0] = NULL;
bind._arg[1] = NULL;
bind._dep[0] = Shader::SSD_general | Shader::SSD_transform;
bind._dep[1] = Shader::SSD_general | Shader::SSD_transform;
if (matrix_name == "ModelViewProjectionMatrix") {
bind._func = Shader::SMF_compose;
if (inverse) {
bind._part[0] = Shader::SMO_apiclip_to_view;
bind._part[1] = Shader::SMO_view_to_model;
@ -284,11 +286,8 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
bind._part[0] = Shader::SMO_model_to_view;
bind._part[1] = Shader::SMO_view_to_apiclip;
}
bind._dep[0] = Shader::SSD_general | Shader::SSD_transform;
bind._dep[1] = Shader::SSD_general | Shader::SSD_transform;
} else if (matrix_name == "ModelViewMatrix") {
bind._func = Shader::SMF_compose;
if (inverse) {
bind._part[0] = Shader::SMO_apiview_to_view;
bind._part[1] = Shader::SMO_view_to_model;
@ -296,11 +295,8 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
bind._part[0] = Shader::SMO_model_to_view;
bind._part[1] = Shader::SMO_view_to_apiview;
}
bind._dep[0] = Shader::SSD_general | Shader::SSD_transform;
bind._dep[1] = Shader::SSD_general | Shader::SSD_transform;
} else if (matrix_name == "ProjectionMatrix") {
bind._func = Shader::SMF_compose;
if (inverse) {
bind._part[0] = Shader::SMO_apiclip_to_view;
bind._part[1] = Shader::SMO_view_to_apiview;
@ -308,12 +304,9 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
bind._part[0] = Shader::SMO_apiview_to_view;
bind._part[1] = Shader::SMO_view_to_apiclip;
}
bind._dep[0] = Shader::SSD_general | Shader::SSD_transform;
bind._dep[1] = Shader::SSD_general | Shader::SSD_transform;
} else if (matrix_name == "NormalMatrix") {
// This is really the upper 3x3 of the ModelViewMatrixInverseTranspose.
bind._func = Shader::SMF_compose;
if (inverse) {
bind._part[0] = Shader::SMO_model_to_view;
bind._part[1] = Shader::SMO_view_to_apiview;
@ -321,8 +314,6 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
bind._part[0] = Shader::SMO_apiview_to_view;
bind._part[1] = Shader::SMO_view_to_model;
}
bind._dep[0] = Shader::SSD_general | Shader::SSD_transform;
bind._dep[1] = Shader::SSD_general | Shader::SSD_transform;
if (transpose) {
bind._piece = Shader::SMP_upper3x3;
@ -330,6 +321,33 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
bind._piece = Shader::SMP_transpose3x3;
}
} else if (matrix_name == "ModelMatrix") {
if (inverse) {
bind._part[0] = Shader::SMO_world_to_view;
bind._part[1] = Shader::SMO_view_to_model;
} else {
bind._part[0] = Shader::SMO_model_to_view;
bind._part[1] = Shader::SMO_view_to_world;
}
} else if (matrix_name == "ViewMatrix") {
if (inverse) {
bind._part[0] = Shader::SMO_apiview_to_view;
bind._part[1] = Shader::SMO_view_to_world;
} else {
bind._part[0] = Shader::SMO_world_to_view;
bind._part[1] = Shader::SMO_view_to_apiview;
}
} else if (matrix_name == "ViewProjectionMatrix") {
if (inverse) {
bind._part[0] = Shader::SMO_apiclip_to_view;
bind._part[1] = Shader::SMO_view_to_world;
} else {
bind._part[0] = Shader::SMO_world_to_view;
bind._part[1] = Shader::SMO_view_to_apiclip;
}
} else {
GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n";
continue;
@ -410,21 +428,21 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
if (param_name == "osg_ViewMatrix") {
bind._piece = Shader::SMP_whole;
bind._func = Shader::SMF_first;
bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_world_to_view;
bind._part[1] = Shader::SMO_identity;
bind._part[1] = Shader::SMO_view_to_apiview;
bind._dep[0] = Shader::SSD_general | Shader::SSD_transform;
bind._dep[1] = Shader::SSD_NONE;
bind._dep[1] = Shader::SSD_general | Shader::SSD_transform;
s->_mat_spec.push_back(bind);
continue;
} else if (param_name == "osg_InverseViewMatrix") {
bind._piece = Shader::SMP_whole;
bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_view_to_world;
bind._part[1] = Shader::SMO_identity;
bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_apiview_to_view;
bind._part[1] = Shader::SMO_view_to_world;
bind._dep[0] = Shader::SSD_general | Shader::SSD_transform;
bind._dep[1] = Shader::SSD_NONE;
bind._dep[1] = Shader::SSD_general | Shader::SSD_transform;
s->_mat_spec.push_back(bind);
continue;
@ -1135,9 +1153,14 @@ disable_shader_texture_bindings() {
if (gl_enable_memory_barriers) {
for (int i = 0; i < num_image_units; ++i) {
// We don't distinguish between read-only and read-write/write-only
// image access, so we have to assume that the shader wrote to it.
_glsl_img_textures[i]->mark_incoherent();
const InternalName *name = _glsl_img_inputs[i];
const ShaderInput *input = _glgsg->_target_shader->get_shader_input(name);
if ((input->_access & ShaderInput::A_write) != 0) {
_glsl_img_textures[i]->mark_incoherent(true);
} else {
_glsl_img_textures[i]->mark_incoherent(false);
}
_glsl_img_textures[i] = NULL;
}
}
@ -1175,21 +1198,18 @@ update_shader_texture_bindings(ShaderContext *prev) {
int num_image_units = min(_glsl_img_inputs.size(), (size_t)_glgsg->_max_image_units);
if (num_image_units > 0) {
GLuint *multi_img = NULL;
// If we support multi-bind, prepare an array.
if (_glgsg->_supports_multi_bind) {
multi_img = new GLuint[num_image_units];
}
for (int i = 0; i < num_image_units; ++i) {
const InternalName *name = _glsl_img_inputs[i];
Texture *tex = _glgsg->_target_shader->get_shader_input_texture(name);
const ShaderInput *input = _glgsg->_target_shader->get_shader_input(name);
Texture *tex = input->get_texture();
GLuint gl_tex = 0;
CLP(TextureContext) *gtc;
if (tex != NULL) {
int view = _glgsg->get_current_tex_view_offset();
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg));
gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg));
if (gtc != (TextureContext*)NULL) {
_glsl_img_textures[i] = gtc;
@ -1202,26 +1222,44 @@ update_shader_texture_bindings(ShaderContext *prev) {
}
}
if (multi_img != NULL) {
// Put in array so we can multi-bind later.
multi_img[i] = gl_tex;
if (gl_tex == 0) {
_glgsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
} else {
// We don't support multi-bind, so bind now in the same way that multi-bind would have done it.
if (gl_tex == 0) {
_glgsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
} else {
//TODO: automatically convert to sized type instead of plain GL_RGBA
// If a base type is used, it will crash.
GLint internal_format = _glgsg->get_internal_image_format(tex);
_glgsg->_glBindImageTexture(i, gl_tex, 0, GL_TRUE, 0, GL_READ_WRITE, internal_format);
}
}
}
//TODO: automatically convert to sized type instead of plain GL_RGBA
// If a base type is used, it will crash.
if (gtc->_internal_format == GL_RGBA || gtc->_internal_format == GL_RGB) {
GLCAT.error()
<< "Texture " << tex->get_name() << " has an unsized format. Textures bound "
<< "to a shader as an image need a sized format.\n";
if (multi_img != NULL) {
_glgsg->_glBindImageTextures(0, num_image_units, multi_img);
delete[] multi_img;
// This may not actually be right, but may still prevent a crash.
if (gtc->_internal_format == GL_RGBA) {
gtc->_internal_format = GL_RGBA8;
} else {
gtc->_internal_format = GL_RGB8;
}
}
GLenum access = GL_READ_ONLY;
GLboolean layered = (input->_access & ShaderInput::A_layered) != 0;
if ((input->_access & ShaderInput::A_read) != 0 &&
(input->_access & ShaderInput::A_write) != 0) {
access = GL_READ_WRITE;
} else if ((input->_access & ShaderInput::A_read) != 0) {
access = GL_READ_ONLY;
} else if ((input->_access & ShaderInput::A_write) != 0) {
access = GL_WRITE_ONLY;
} else {
access = GL_READ_ONLY;
gl_tex = 0;
}
_glgsg->_glBindImageTexture(i, gl_tex, input->_bind_level, layered,
input->_bind_layer, access, gtc->_internal_format);
}
}
}
#endif
@ -1314,7 +1352,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
#ifndef OPENGLES
if (barriers != 0) {
// Issue a memory barrier.
// Issue a memory barrier prior to this shader's execution.
_glgsg->issue_memory_barrier(barriers);
}
#endif

View File

@ -28,7 +28,6 @@ CLP(TextureContext)(CLP(GraphicsStateGuardian) *glgsg,
glGenTextures(1, &_index);
_handle = 0;
_needs_barrier = false;
_has_storage = false;
_immutable = false;
_uses_mipmaps = false;

View File

@ -87,7 +87,6 @@ reset_data() {
_handle = 0;
_handle_resident = false;
_needs_barrier = false;
_has_storage = false;
_immutable = false;
@ -169,15 +168,25 @@ needs_barrier(GLbitfield barrier) {
// Function: GLTextureContext::mark_incoherent
// Access: Public
// Description: Mark a texture as needing a memory barrier, since
// a non-coherent write just happened to it.
// a non-coherent read or write just happened to it.
// If 'wrote' is true, it was written to.
////////////////////////////////////////////////////////////////////
void CLP(TextureContext)::
mark_incoherent() {
mark_incoherent(bool wrote) {
if (!gl_enable_memory_barriers) {
return;
}
_glgsg->_textures_needing_fetch_barrier.insert(this);
// If we only read from it, the next read operation won't need
// another barrier, since it'll be reading the same data.
if (wrote) {
_glgsg->_textures_needing_fetch_barrier.insert(this);
}
// We could still write to it before we read from it, so we have
// to always insert these barriers. This could be slightly
// optimized so that we don't issue a barrier between consecutive
// image reads, but that may not be worth the trouble.
_glgsg->_textures_needing_image_access_barrier.insert(this);
_glgsg->_textures_needing_update_barrier.insert(this);
_glgsg->_textures_needing_framebuffer_barrier.insert(this);

View File

@ -40,7 +40,7 @@ public:
CONSTEXPR bool needs_barrier(GLbitfield barrier) { return false; };
#else
bool needs_barrier(GLbitfield barrier);
void mark_incoherent();
void mark_incoherent(bool wrote);
#endif
// This is the GL "name" of the texture object.
@ -50,11 +50,6 @@ public:
GLuint64 _handle;
bool _handle_resident;
// This is true if the texture was recently written to in a
// non-coherent way, and Panda may have to call glMemoryBarrier
// for the results of this write to become visible.
bool _needs_barrier;
// These are the parameters that we specified with the last
// glTexImage2D() or glTexStorage2D() call. If none of these have
// changed, we can reload the texture image with a glTexSubImage2D().

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