Merge branch 'master' into cmake
This commit is contained in:
commit
57fb97053b
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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 ¶meter_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 ¶meter_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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -247,10 +247,6 @@ output(ostream &out) const {
|
|||
out << "RSHIFTEQUAL";
|
||||
break;
|
||||
|
||||
case TOKENPASTE:
|
||||
out << "TOKENPASTE";
|
||||
break;
|
||||
|
||||
case KW_BOOL:
|
||||
out << "KW_BOOL";
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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> ©) : 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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> ©) : 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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 = "";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ operator = (const InterrogateElement ©) {
|
|||
InterrogateComponent::operator = (copy);
|
||||
_flags = copy._flags;
|
||||
_scoped_name = copy._scoped_name;
|
||||
_comment = copy._comment;
|
||||
_type = copy._type;
|
||||
_getter = copy._getter;
|
||||
_setter = copy._setter;
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
#
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
|||
_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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "indent.h"
|
||||
|
||||
#include "pvector.h"
|
||||
#include "epvector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : EggMorphList
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
defconstruct TypeHandle new TypeHandle(TypeHandle::none())
|
||||
|
||||
forcetype PandaSystem
|
||||
forcetype DSearchPath
|
||||
forcetype DSearchPath::Results
|
||||
|
|
|
|||
|
|
@ -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, >c->_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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue