open_toontown_panda3d/panda/src/pgui/pgFrameStyle.cxx

808 lines
28 KiB
C++

/**
* 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."
*
* @file pgFrameStyle.cxx
* @author drose
* @date 2001-07-03
*/
#include "pgFrameStyle.h"
#include "geomNode.h"
#include "pandaNode.h"
#include "transparencyAttrib.h"
#include "pointerTo.h"
#include "nodePath.h"
#include "textureAttrib.h"
#include "renderState.h"
#include "shadeModelAttrib.h"
#include "colorAttrib.h"
#include "geom.h"
#include "geomTristrips.h"
#include "geomVertexWriter.h"
using std::max;
using std::min;
// Specifies the UV range of textures applied to the frame. Maybe we'll have
// a reason to make this a parameter of the frame style one day, but for now
// it's hardcoded to fit the entire texture over the rectangular frame.
static const LVecBase4 uv_range = LVecBase4(0.0f, 1.0f, 0.0f, 1.0f);
std::ostream &
operator << (std::ostream &out, PGFrameStyle::Type type) {
switch (type) {
case PGFrameStyle::T_none:
return out << "none";
case PGFrameStyle::T_flat:
return out << "flat";
case PGFrameStyle::T_bevel_out:
return out << "bevel_out";
case PGFrameStyle::T_bevel_in:
return out << "bevel_in";
case PGFrameStyle::T_groove:
return out << "groove";
case PGFrameStyle::T_ridge:
return out << "ridge";
case PGFrameStyle::T_texture_border:
return out << "texture_border";
}
return out << "**unknown(" << (int)type << ")**";
}
/**
* Computes the size of the internal frame, given the indicated external
* frame, appropriate for this kind of frame style. This simply subtracts the
* border width for those frame styles that include a border.
*/
LVecBase4 PGFrameStyle::
get_internal_frame(const LVecBase4 &frame) const {
LPoint2 center((frame[0] + frame[1]) / 2.0f,
(frame[2] + frame[3]) / 2.0f);
LVecBase4 scaled_frame
((frame[0] - center[0]) * _visible_scale[0] + center[0],
(frame[1] - center[0]) * _visible_scale[0] + center[0],
(frame[2] - center[1]) * _visible_scale[1] + center[1],
(frame[3] - center[1]) * _visible_scale[1] + center[1]);
switch (_type) {
case T_none:
case T_flat:
return scaled_frame;
default:
break;
}
return LVecBase4(scaled_frame[0] + _width[0],
scaled_frame[1] - _width[0],
scaled_frame[2] + _width[1],
scaled_frame[3] - _width[1]);
}
/**
*
*/
void PGFrameStyle::
output(std::ostream &out) const {
out << _type << " color = " << _color << " width = " << _width;
if (_visible_scale != LVecBase2(1.0f, 1.0f)) {
out << "visible_scale = " << get_visible_scale();
}
if (has_texture()) {
out << " texture = " << *get_texture();
}
}
/**
* Applies the indicated transform to the FrameStyle. The return value is
* true if the frame style is transformed, or false if it was not affected by
* the transform.
*/
bool PGFrameStyle::
xform(const LMatrix4 &mat) {
// All we can do is scale the X and Y bevel sizes.
// Extract the X and Z axes from the matrix.
LVector3 x, z;
mat.get_row3(x, 0);
PN_stdfloat x_scale = x.length();
mat.get_row3(z, 2);
PN_stdfloat z_scale = z.length();
_width[0] *= x_scale;
_width[1] *= z_scale;
switch (_type) {
case T_none:
case T_flat:
return false;
case T_bevel_out:
case T_bevel_in:
case T_groove:
case T_ridge:
case T_texture_border:
return true;
}
// Shouldn't get here, but this makes the compiler happy.
return true;
}
/**
* Generates geometry representing a frame of the indicated size, and parents
* it to the indicated node, with the indicated scene graph sort order.
*
* The return value is the generated NodePath, if any, or an empty NodePath if
* nothing is generated.
*/
NodePath PGFrameStyle::
generate_into(const NodePath &parent, const LVecBase4 &frame,
int sort) {
PT(PandaNode) new_node;
LPoint2 center((frame[0] + frame[1]) / 2.0f,
(frame[2] + frame[3]) / 2.0f);
LVecBase4 scaled_frame
((frame[0] - center[0]) * _visible_scale[0] + center[0],
(frame[1] - center[0]) * _visible_scale[0] + center[0],
(frame[2] - center[1]) * _visible_scale[1] + center[1],
(frame[3] - center[1]) * _visible_scale[1] + center[1]);
switch (_type) {
case T_none:
return NodePath();
case T_flat:
new_node = generate_flat_geom(scaled_frame);
break;
case T_bevel_out:
new_node = generate_bevel_geom(scaled_frame, false);
break;
case T_bevel_in:
new_node = generate_bevel_geom(scaled_frame, true);
break;
case T_groove:
new_node = generate_groove_geom(scaled_frame, true);
break;
case T_ridge:
new_node = generate_groove_geom(scaled_frame, false);
break;
case T_texture_border:
new_node = generate_texture_border_geom(scaled_frame);
break;
default:
break;
}
if (new_node != nullptr && _color[3] != 1.0f) {
// We've got some alpha on the color; we need transparency.
new_node->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
}
// Adding the node to the parent keeps the reference count.
return parent.attach_new_node(new_node, sort);
}
/**
* Generates the GeomNode appropriate to a T_flat frame.
*/
PT(PandaNode) PGFrameStyle::
generate_flat_geom(const LVecBase4 &frame) {
PT(GeomNode) gnode = new GeomNode("flat");
PN_stdfloat left = frame[0];
PN_stdfloat right = frame[1];
PN_stdfloat bottom = frame[2];
PN_stdfloat top = frame[3];
CPT(GeomVertexFormat) format;
if (has_texture()) {
format = GeomVertexFormat::get_v3t2();
} else {
format = GeomVertexFormat::get_v3();
}
PT(GeomVertexData) vdata = new GeomVertexData
("PGFrame", format, Geom::UH_static);
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
if (has_texture()) {
// Generate UV's.
left = uv_range[0];
right = uv_range[1];
bottom = uv_range[2];
top = uv_range[3];
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
texcoord.add_data2(left, top);
texcoord.add_data2(left, bottom);
texcoord.add_data2(right, top);
texcoord.add_data2(right, bottom);
}
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
strip->add_next_vertices(4);
strip->close_primitive();
CPT(RenderState) state = RenderState::make(ColorAttrib::make_flat(_color), -1);
if (has_texture()) {
state = state->set_attrib(TextureAttrib::make(get_texture()));
}
PT(Geom) geom = new Geom(vdata);
geom->add_primitive(strip);
gnode->add_geom(geom, state);
return gnode;
}
/**
* Generates the GeomNode appropriate to a T_bevel_in or T_bevel_out frame.
*/
PT(PandaNode) PGFrameStyle::
generate_bevel_geom(const LVecBase4 &frame, bool in) {
/*
* Colors: * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * ctop * * * *
* * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * cleft *
* _color * cright* * * * * *
* * * * * * * * * * * * * * * * * * * *
* * * * * * * * cbottom
* * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * Vertices: tristrip 1: 4 * * * * * * * * * * * * * * *
* * * * * * * 6 * * * * *
* * * * * * 5 * * * * * * * * * * * *
* * 7 * * * * * * * * * * * 3 * * * * * *
* * * * * * * * 1 * * * * *
* * * * * 2 * * * * * * * * * * * * * *
* * * * * * * * 0 tristrip 2: 1 * * * * * * 5 * * * * * * * * * * * * *
* 3 * * * * *
* * * * * * *
* * * * * * 4 * * * * * * * * * * * * *
* 2 * * * * * * * 0
*/
PT(GeomNode) gnode = new GeomNode("bevel");
PN_stdfloat left = frame[0];
PN_stdfloat right = frame[1];
PN_stdfloat bottom = frame[2];
PN_stdfloat top = frame[3];
PN_stdfloat cx = (left + right) * 0.5;
PN_stdfloat cy = (top + bottom) * 0.5;
PN_stdfloat inner_left = min(left + _width[0], cx);
PN_stdfloat inner_right = max(right - _width[0], cx);
PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
PN_stdfloat inner_top = max(top - _width[1], cy);
PN_stdfloat left_color_scale = 1.2;
PN_stdfloat right_color_scale = 0.8;
PN_stdfloat bottom_color_scale = 0.7;
PN_stdfloat top_color_scale = 1.3;
if (in) {
right_color_scale = 1.2;
left_color_scale = 0.8;
top_color_scale = 0.7;
bottom_color_scale = 1.3;
}
// Clamp all colors at white, and don't scale the alpha.
LColor cleft(min(_color[0] * left_color_scale, (PN_stdfloat)1.0),
min(_color[1] * left_color_scale, (PN_stdfloat)1.0),
min(_color[2] * left_color_scale, (PN_stdfloat)1.0),
_color[3]);
LColor cright(min(_color[0] * right_color_scale, (PN_stdfloat)1.0),
min(_color[1] * right_color_scale, (PN_stdfloat)1.0),
min(_color[2] * right_color_scale, (PN_stdfloat)1.0),
_color[3]);
LColor cbottom(min(_color[0] * bottom_color_scale, (PN_stdfloat)1.0),
min(_color[1] * bottom_color_scale, (PN_stdfloat)1.0),
min(_color[2] * bottom_color_scale, (PN_stdfloat)1.0),
_color[3]);
LColor ctop(min(_color[0] * top_color_scale, (PN_stdfloat)1.0),
min(_color[1] * top_color_scale, (PN_stdfloat)1.0),
min(_color[2] * top_color_scale, (PN_stdfloat)1.0),
_color[3]);
CPT(GeomVertexFormat) format;
if (has_texture()) {
format = GeomVertexFormat::get_v3cpt2();
} else {
format = GeomVertexFormat::get_v3cp();
}
PT(GeomVertexData) vdata = new GeomVertexData
("PGFrame", format, Geom::UH_static);
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
GeomVertexWriter color(vdata, InternalName::get_color());
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
// Tristrip 1.
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
color.add_data4(cbottom);
color.add_data4(cbottom);
color.add_data4(cbottom);
color.add_data4(cbottom);
color.add_data4(cleft);
color.add_data4(cleft);
color.add_data4(ctop);
color.add_data4(ctop);
strip->add_next_vertices(8);
strip->close_primitive();
// Tristrip 2.
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
color.add_data4(cright);
color.add_data4(cright);
color.add_data4(cright);
color.add_data4(cright);
color.add_data4(_color);
color.add_data4(_color);
strip->add_next_vertices(6);
strip->close_primitive();
strip->set_shade_model(Geom::SM_flat_last_vertex);
if (has_texture()) {
// Generate UV's.
PN_stdfloat left = uv_range[0];
PN_stdfloat right = uv_range[1];
PN_stdfloat bottom = uv_range[2];
PN_stdfloat top = uv_range[3];
PN_stdfloat cx = (left + right) * 0.5;
PN_stdfloat cy = (top + bottom) * 0.5;
PN_stdfloat inner_left = min(left + _uv_width[0], cx);
PN_stdfloat inner_right = max(right - _uv_width[0], cx);
PN_stdfloat inner_bottom = min(bottom + _uv_width[1], cy);
PN_stdfloat inner_top = max(top - _uv_width[1], cy);
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
texcoord.add_data2(right, bottom);
texcoord.add_data2(inner_right, inner_bottom);
texcoord.add_data2(left, bottom);
texcoord.add_data2(inner_left, inner_bottom);
texcoord.add_data2(left, top);
texcoord.add_data2(inner_left, inner_top);
texcoord.add_data2(right, top);
texcoord.add_data2(inner_right, inner_top);
texcoord.add_data2(right, bottom);
texcoord.add_data2(right, top);
texcoord.add_data2(inner_right, inner_bottom);
texcoord.add_data2(inner_right, inner_top);
texcoord.add_data2(inner_left, inner_bottom);
texcoord.add_data2(inner_left, inner_top);
}
PT(Geom) geom = new Geom(vdata);
geom->add_primitive(strip);
CPT(RenderState) state;
state = RenderState::make(ShadeModelAttrib::make(ShadeModelAttrib::M_flat),
ColorAttrib::make_vertex());
if (has_texture()) {
state = state->set_attrib(TextureAttrib::make(get_texture()));
}
gnode->add_geom(geom, state);
return gnode;
}
/**
* Generates the GeomNode appropriate to a T_groove or T_ridge frame.
*/
PT(PandaNode) PGFrameStyle::
generate_groove_geom(const LVecBase4 &frame, bool in) {
/*
* Colors: * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * ctop * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * cbottom * * * * *
* * * * * * * * * * * * * * * * *
* * * * * * * * * * *
* * * * * * * cleft * cright* _color
* * cleft * cright* * * * * * * *
* * * * * * * * * * * * * * *
* * * * * * * * * * * *
* * * * * ctop * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * cbottom * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Vertices:
* tristrip 1: 4 * * * * * * * * * * * * * * * * * * * * * * * * * 6 * *
* * * * * * *
* * * 5 * * * * * * * * * * * * * * * * * 7 * * * * *
* * * * * * * * * * * * * * * * *
* * * * * * * 3 * * * * * * * * * * * * * * * * * 1 * *
* * * * * * *
* * 2 * * * * * * * * * * * * * * * * * * * * * * * * * 0 tristrip 2: 4 * * *
* * * * * * * * * * * * * * * 6 * * * * *
* * * * * * 5 * * * * * * * * * 7 * * *
* * * * * * * * * 3 * * * * * * * * * 1 * *
* * * * * * * * 2 *
* * * * * * * * * * * * * * * * * 0 tristrip 3: 1 * * * * * * 3 *
* * * * * * * * * * 7 * * * * * * * * * 5 *
* * * * * * * * *
* * * * * * * * *
* * * * * * 6 * * * * * * * * * 4 *
* * * * * * * * * * * 2 * * * * * * * 0
*/
PT(GeomNode) gnode = new GeomNode("groove");
PN_stdfloat left = frame[0];
PN_stdfloat right = frame[1];
PN_stdfloat bottom = frame[2];
PN_stdfloat top = frame[3];
PN_stdfloat cx = (left + right) * 0.5;
PN_stdfloat cy = (top + bottom) * 0.5;
PN_stdfloat mid_left = min(left + 0.5f * _width[0], cx);
PN_stdfloat mid_right = max(right - 0.5f * _width[0], cx);
PN_stdfloat mid_bottom = min(bottom + 0.5f * _width[1], cy);
PN_stdfloat mid_top = max(top - 0.5f * _width[1], cy);
PN_stdfloat inner_left = min(left + _width[0], cx);
PN_stdfloat inner_right = max(right - _width[0], cx);
PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
PN_stdfloat inner_top = max(top - _width[1], cy);
PN_stdfloat left_color_scale = 1.2;
PN_stdfloat right_color_scale = 0.8f;
PN_stdfloat bottom_color_scale = 0.7f;
PN_stdfloat top_color_scale = 1.3;
if (in) {
right_color_scale = 1.2;
left_color_scale = 0.8f;
top_color_scale = 0.7f;
bottom_color_scale = 1.3;
}
// Clamp all colors at white, and don't scale the alpha.
LColor cleft(min(_color[0] * left_color_scale, (PN_stdfloat)1.0),
min(_color[1] * left_color_scale, (PN_stdfloat)1.0),
min(_color[2] * left_color_scale, (PN_stdfloat)1.0),
_color[3]);
LColor cright(min(_color[0] * right_color_scale, (PN_stdfloat)1.0),
min(_color[1] * right_color_scale, (PN_stdfloat)1.0),
min(_color[2] * right_color_scale, (PN_stdfloat)1.0),
_color[3]);
LColor cbottom(min(_color[0] * bottom_color_scale, (PN_stdfloat)1.0),
min(_color[1] * bottom_color_scale, (PN_stdfloat)1.0),
min(_color[2] * bottom_color_scale, (PN_stdfloat)1.0),
_color[3]);
LColor ctop(min(_color[0] * top_color_scale, (PN_stdfloat)1.0),
min(_color[1] * top_color_scale, (PN_stdfloat)1.0),
min(_color[2] * top_color_scale, (PN_stdfloat)1.0),
_color[3]);
CPT(GeomVertexFormat) format;
if (has_texture()) {
format = GeomVertexFormat::get_v3cpt2();
} else {
format = GeomVertexFormat::get_v3cp();
}
PT(GeomVertexData) vdata = new GeomVertexData
("PGFrame", format, Geom::UH_static);
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
GeomVertexWriter color(vdata, InternalName::get_color());
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
// Tristrip 1.
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_bottom));
vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_top));
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
color.add_data4(cbottom);
color.add_data4(cbottom);
color.add_data4(cbottom);
color.add_data4(cbottom);
color.add_data4(cleft);
color.add_data4(cleft);
color.add_data4(ctop);
color.add_data4(ctop);
strip->add_next_vertices(8);
strip->close_primitive();
// Tristrip 2.
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_bottom));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_top));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
color.add_data4(ctop);
color.add_data4(ctop);
color.add_data4(ctop);
color.add_data4(ctop);
color.add_data4(cright);
color.add_data4(cright);
color.add_data4(cbottom);
color.add_data4(cbottom);
strip->add_next_vertices(8);
strip->close_primitive();
// Tristrip 3.
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
color.add_data4(cright);
color.add_data4(cright);
color.add_data4(cright);
color.add_data4(cright);
color.add_data4(cleft);
color.add_data4(cleft);
color.add_data4(_color);
color.add_data4(_color);
strip->add_next_vertices(8);
strip->close_primitive();
strip->set_shade_model(Geom::SM_flat_last_vertex);
if (has_texture()) {
// Generate UV's.
PN_stdfloat left = uv_range[0];
PN_stdfloat right = uv_range[1];
PN_stdfloat bottom = uv_range[2];
PN_stdfloat top = uv_range[3];
PN_stdfloat cx = (left + right) * 0.5;
PN_stdfloat cy = (top + bottom) * 0.5;
PN_stdfloat mid_left = min(left + 0.5f * _width[0], cx);
PN_stdfloat mid_right = max(right - 0.5f * _width[0], cx);
PN_stdfloat mid_bottom = min(bottom + 0.5f * _width[1], cy);
PN_stdfloat mid_top = max(top - 0.5f * _width[1], cy);
PN_stdfloat inner_left = min(left + _width[0], cx);
PN_stdfloat inner_right = max(right - _width[0], cx);
PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
PN_stdfloat inner_top = max(top - _width[1], cy);
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
texcoord.add_data2(right, bottom);
texcoord.add_data2(mid_right, mid_bottom);
texcoord.add_data2(left, bottom);
texcoord.add_data2(mid_left, mid_bottom);
texcoord.add_data2(left, top);
texcoord.add_data2(mid_left, mid_top);
texcoord.add_data2(right, top);
texcoord.add_data2(mid_right, mid_top);
texcoord.add_data2(mid_right, mid_bottom);
texcoord.add_data2(inner_right, inner_bottom);
texcoord.add_data2(mid_left, mid_bottom);
texcoord.add_data2(inner_left, inner_bottom);
texcoord.add_data2(mid_left, mid_top);
texcoord.add_data2(inner_left, inner_top);
texcoord.add_data2(mid_right, mid_top);
texcoord.add_data2(inner_right, inner_top);
texcoord.add_data2(right, bottom);
texcoord.add_data2(right, top);
texcoord.add_data2(mid_right, mid_bottom);
texcoord.add_data2(mid_right, mid_top);
texcoord.add_data2(inner_right, inner_bottom);
texcoord.add_data2(inner_right, inner_top);
texcoord.add_data2(inner_left, inner_bottom);
texcoord.add_data2(inner_left, inner_top);
}
PT(Geom) geom = new Geom(vdata);
geom->add_primitive(strip);
CPT(RenderState) state = RenderState::make(ShadeModelAttrib::make(ShadeModelAttrib::M_flat),
ColorAttrib::make_vertex());
if (has_texture()) {
state = state->set_attrib(TextureAttrib::make(get_texture()));
}
gnode->add_geom(geom, state);
return gnode;
}
/**
* Generates the GeomNode appropriate to a T_texture_border frame.
*/
PT(PandaNode) PGFrameStyle::
generate_texture_border_geom(const LVecBase4 &frame) {
/*
* Vertices: tristrip 1: 0 * * * 2 * * * * * * * * * * * * * 4 * * * 6 * *
* * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * 1 * * * 3 * * * * * * *
* * * * * * * 5 * * * 7 tristrip 2: 1 * * * 3 * * * * * * * * * * * * * 5 * *
* * 7 * * * * * * * *
* * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * 8 * * *10 * * * * * * * * * * * * *12
* * * *14 tristrip 3: 8 * * *10 * * * * * * * * * * * * *12 * * *14 * * *
* * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * 9 * * *11 * * * * * * * * * * * * *13 * *
* *15
*/
PT(GeomNode) gnode = new GeomNode("flat");
PN_stdfloat left = frame[0];
PN_stdfloat right = frame[1];
PN_stdfloat bottom = frame[2];
PN_stdfloat top = frame[3];
PN_stdfloat cx = (left + right) * 0.5;
PN_stdfloat cy = (top + bottom) * 0.5;
PN_stdfloat inner_left = min(left + _width[0], cx);
PN_stdfloat inner_right = max(right - _width[0], cx);
PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
PN_stdfloat inner_top = max(top - _width[1], cy);
CPT(GeomVertexFormat) format;
if (has_texture()) {
format = GeomVertexFormat::get_v3t2();
} else {
format = GeomVertexFormat::get_v3();
}
PT(GeomVertexData) vdata = new GeomVertexData
("PGFrame", format, Geom::UH_static);
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
// verts 0,1,2,3
vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
vertex.add_data3(LPoint3::rfu(left, 0.0f, inner_top));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, top));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
// verts 4,5,6,7
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, top));
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
vertex.add_data3(LPoint3::rfu(right, 0.0f, inner_top));
// verts 8,9,10,11
vertex.add_data3(LPoint3::rfu(left, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, bottom));
// verts 12,13,14,15
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, bottom));
vertex.add_data3(LPoint3::rfu(right, 0.0f, inner_bottom));
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
if (has_texture()) {
// Generate UV's.
PN_stdfloat left = uv_range[0];
PN_stdfloat right = uv_range[1];
PN_stdfloat bottom = uv_range[2];
PN_stdfloat top = uv_range[3];
PN_stdfloat cx = (left + right) * 0.5;
PN_stdfloat cy = (top + bottom) * 0.5;
PN_stdfloat inner_left = min(left + _uv_width[0], cx);
PN_stdfloat inner_right = max(right - _uv_width[0], cx);
PN_stdfloat inner_bottom = min(bottom + _uv_width[1], cy);
PN_stdfloat inner_top = max(top - _uv_width[1], cy);
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
// verts 0,1,2,3
texcoord.add_data2(left, top);
texcoord.add_data2(left, inner_top);
texcoord.add_data2(inner_left, top);
texcoord.add_data2(inner_left, inner_top);
// verts 4,5,6,7
texcoord.add_data2(inner_right, top);
texcoord.add_data2(inner_right, inner_top);
texcoord.add_data2(right, top);
texcoord.add_data2(right, inner_top);
// verts 8,9,10,11
texcoord.add_data2(left, inner_bottom);
texcoord.add_data2(left, bottom);
texcoord.add_data2(inner_left, inner_bottom);
texcoord.add_data2(inner_left, bottom);
// verts 12,13,14,15
texcoord.add_data2(inner_right, inner_bottom);
texcoord.add_data2(inner_right, bottom);
texcoord.add_data2(right, inner_bottom);
texcoord.add_data2(right, bottom);
}
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
// tristrip #1
strip->add_consecutive_vertices(0, 8);
strip->close_primitive();
// tristrip #2
strip->add_vertex(1);
strip->add_vertex(8);
strip->add_vertex(3);
strip->add_vertex(10);
strip->add_vertex(5);
strip->add_vertex(12);
strip->add_vertex(7);
strip->add_vertex(14);
strip->close_primitive();
// tristrip #3
strip->add_consecutive_vertices(8, 8);
strip->close_primitive();
CPT(RenderState) state = RenderState::make(ColorAttrib::make_flat(_color), -1);
if (has_texture()) {
state = state->set_attrib(TextureAttrib::make(get_texture()));
}
PT(Geom) geom = new Geom(vdata);
geom->add_primitive(strip);
gnode->add_geom(geom, state);
return gnode;
}