support instancing syntax

This commit is contained in:
David Rose 2008-10-30 22:26:57 +00:00
parent d2d151010f
commit 83d21bc2b1
6 changed files with 1083 additions and 898 deletions

View File

@ -121,6 +121,14 @@ EggGroup::
void EggGroup:: void EggGroup::
set_group_type(GroupType type) { set_group_type(GroupType type) {
if (type != get_group_type()) { if (type != get_group_type()) {
#ifndef NDEBUG
if (type != GT_instance) {
// Only valid to change to a non-instance type if we have no
// group refs.
nassertv(_group_refs.empty());
}
#endif
// Make sure the user didn't give us any stray bits. // Make sure the user didn't give us any stray bits.
nassertv((type & ~F_group_type)==0); nassertv((type & ~F_group_type)==0);
_flags = (_flags & ~F_group_type) | type; _flags = (_flags & ~F_group_type) | type;
@ -259,6 +267,13 @@ write(ostream &out, int indent_level) const {
<< "<Scalar> blenda { " << c[3] << " }\n"; << "<Scalar> blenda { " << c[3] << " }\n";
} }
GroupRefs::const_iterator gri;
for (gri = _group_refs.begin(); gri != _group_refs.end(); ++gri) {
EggGroup *group_ref = (*gri);
indent(out, indent_level + 2)
<< "<Ref> { " << group_ref->get_name() << " }\n";
}
// We have to write the children nodes before we write the vertex // We have to write the children nodes before we write the vertex
// references, since we might be referencing a vertex that's defined // references, since we might be referencing a vertex that's defined
// in one of those children nodes! // in one of those children nodes!
@ -767,6 +782,65 @@ test_vref_integrity() const {
#endif // NDEBUG #endif // NDEBUG
////////////////////////////////////////////////////////////////////
// Function: EggGroup::add_group_ref
// Access: Published
// Description: Adds a new <Ref> entry to the group. This declares
// an internal reference to another node, and is used to
// implement scene-graph instancing; it is only valid if
// the group_type is GT_instance.
////////////////////////////////////////////////////////////////////
void EggGroup::
add_group_ref(EggGroup *group) {
nassertv(get_group_type() == GT_instance);
_group_refs.push_back(group);
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::get_num_group_refs
// Access: Published
// Description: Returns the number of <Ref> entries within this
// group. See add_group_ref().
////////////////////////////////////////////////////////////////////
int EggGroup::
get_num_group_refs() const {
return _group_refs.size();
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::get_group_ref
// Access: Published
// Description: Returns the nth <Ref> entry within this group. See
// add_group_ref().
////////////////////////////////////////////////////////////////////
EggGroup *EggGroup::
get_group_ref(int n) const {
nassertr(n >= 0 && n < (int)_group_refs.size(), NULL);
return _group_refs[n];
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::remove_group_ref
// Access: Published
// Description: Removes the nth <Ref> entry within this group. See
// add_group_ref().
////////////////////////////////////////////////////////////////////
void EggGroup::
remove_group_ref(int n) {
nassertv(n >= 0 && n < (int)_group_refs.size());
_group_refs.erase(_group_refs.begin() + n);
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::clear_group_refs
// Access: Published
// Description: Removes all of the <Ref> entries within this group.
// See add_group_ref().
////////////////////////////////////////////////////////////////////
void EggGroup::
clear_group_refs() {
_group_refs.clear();
}

View File

@ -285,6 +285,12 @@ PUBLISHED:
void test_vref_integrity() const { } void test_vref_integrity() const { }
#endif // NDEBUG #endif // NDEBUG
void add_group_ref(EggGroup *group);
int get_num_group_refs() const;
EggGroup *get_group_ref(int n) const;
void remove_group_ref(int n);
void clear_group_refs();
static GroupType string_group_type(const string &strval); static GroupType string_group_type(const string &strval);
static DartType string_dart_type(const string &strval); static DartType string_dart_type(const string &strval);
static DCSType string_dcs_type(const string &strval); static DCSType string_dcs_type(const string &strval);
@ -353,6 +359,9 @@ private:
TagData _tag_data; TagData _tag_data;
VertexRef _vref; VertexRef _vref;
typedef pvector< PT(EggGroup) > GroupRefs;
GroupRefs _group_refs;
public: public:

File diff suppressed because it is too large Load Diff

View File

@ -79,6 +79,10 @@ static Textures textures;
typedef pmap<string, PT_EggMaterial > Materials; typedef pmap<string, PT_EggMaterial > Materials;
static Materials materials; static Materials materials;
// Group names to groups.
typedef pmap<string, PT(EggGroup) > Groups;
static Groups groups;
// We need to be able to save the index number requested for a vertex // We need to be able to save the index number requested for a vertex
// temporarily. // temporarily.
static int vertex_index; static int vertex_index;
@ -101,6 +105,7 @@ egg_init_parser(istream &in, const string &filename,
vertex_pools.clear(); vertex_pools.clear();
textures.clear(); textures.clear();
materials.clear(); materials.clear();
groups.clear();
egg_stack.push_back(tos); egg_stack.push_back(tos);
egg_top_node = top_node; egg_top_node = top_node;
@ -140,6 +145,7 @@ egg_cleanup_parser() {
vertex_pools.clear(); vertex_pools.clear();
textures.clear(); textures.clear();
materials.clear(); materials.clear();
groups.clear();
} }
%} %}
@ -208,6 +214,7 @@ egg_cleanup_parser() {
%type <_egg> texture_name %type <_egg> texture_name
%type <_egg> material_name %type <_egg> material_name
%type <_egg> vertex_pool_name %type <_egg> vertex_pool_name
%type <_egg> group_name
%type <_number> real %type <_number> real
%type <_number> integer %type <_number> integer
@ -1137,8 +1144,12 @@ group:
} }
'{' group_body '}' '{' group_body '}'
{ {
$$ = egg_stack.back(); EggGroup *group = DCAST(EggGroup, egg_stack.back());
$$ = group;
egg_stack.pop_back(); egg_stack.pop_back();
if (group->has_name()) {
groups[group->get_name()] = group;
}
Thread::consider_yield(); Thread::consider_yield();
} }
; ;
@ -1180,8 +1191,12 @@ instance:
} }
'{' group_body '}' '{' group_body '}'
{ {
$$ = egg_stack.back(); EggGroup *group = DCAST(EggGroup, egg_stack.back());
$$ = group;
egg_stack.pop_back(); egg_stack.pop_back();
if (group->has_name()) {
groups[group->get_name()] = group;
}
} }
; ;
@ -1419,6 +1434,15 @@ group_body:
| group_body transform | group_body transform
| group_body group_vertex_ref | group_body group_vertex_ref
| group_body switchcondition | group_body switchcondition
| group_body REF '{' group_name '}'
{
EggGroup *group = DCAST(EggGroup, egg_stack.back());
if (group->get_group_type() != EggGroup::GT_instance) {
eggyyerror("<Ref> valid only within <Instance>");
} else if ($4 != (EggObject *)NULL) {
group->add_group_ref(DCAST(EggGroup, $4));
}
}
| group_body node | group_body node
{ {
DCAST(EggGroup, egg_stack.back())->add_child(DCAST(EggNode, $2)); DCAST(EggGroup, egg_stack.back())->add_child(DCAST(EggNode, $2));
@ -2825,6 +2849,26 @@ vertex_pool_name:
} }
; ;
/*
* group_name
*
* enter:
* exit: Returns an EggGroup pointer, or NULL.
*
*/
group_name:
required_name
{
string name = $1;
Groups::iterator vpi = groups.find(name);
if (vpi == groups.end()) {
eggyyerror("Unknown group " + name);
$$ = PT(EggObject)();
} else {
$$ = (*vpi).second;
}
}
;
/* /*
* required_name * required_name

View File

@ -1758,6 +1758,7 @@ make_lod(EggBin *egg_bin, PandaNode *parent) {
lod_node->add_switch(instance._d->_switch_in, instance._d->_switch_out); lod_node->add_switch(instance._d->_switch_in, instance._d->_switch_out);
} }
_groups[egg_bin] = lod_node;
return create_group_arc(egg_bin, parent, lod_node); return create_group_arc(egg_bin, parent, lod_node);
} }
@ -1897,6 +1898,19 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
if (node == (PandaNode *)NULL) { if (node == (PandaNode *)NULL) {
return NULL; return NULL;
} }
// Associate any instances with this node.
int num_group_refs = egg_group->get_num_group_refs();
for (int gri = 0; gri < num_group_refs; ++gri) {
EggGroup *group_ref = egg_group->get_group_ref(gri);
Groups::const_iterator gi = _groups.find(group_ref);
if (gi != _groups.end()) {
PandaNode *node_ref = (*gi).second;
node->add_child(node_ref);
}
}
_groups[egg_group] = node;
return create_group_arc(egg_group, parent, node); return create_group_arc(egg_group, parent, node);
} }

View File

@ -224,6 +224,9 @@ private:
Materials _materials; Materials _materials;
Materials _materials_bface; Materials _materials_bface;
typedef pmap<PT(EggGroup), PT(PandaNode) > Groups;
Groups _groups;
typedef pset<PandaNode *> ExtraNodes; typedef pset<PandaNode *> ExtraNodes;
ExtraNodes _decals; ExtraNodes _decals;
ExtraNodes _sequences; ExtraNodes _sequences;