383 lines
14 KiB
C
383 lines
14 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 textNode.h
|
||
|
* @author drose
|
||
|
* @date 2002-03-13
|
||
|
*/
|
||
|
|
||
|
#ifndef TEXTNODE_H
|
||
|
#define TEXTNODE_H
|
||
|
|
||
|
#include "pandabase.h"
|
||
|
|
||
|
#include "config_text.h"
|
||
|
#include "textEncoder.h"
|
||
|
#include "textProperties.h"
|
||
|
#include "textFont.h"
|
||
|
#include "textAssembler.h"
|
||
|
#include "pandaNode.h"
|
||
|
#include "luse.h"
|
||
|
#include "geom.h"
|
||
|
#include "pmutex.h"
|
||
|
#include "mutexHolder.h"
|
||
|
|
||
|
/**
|
||
|
* The primary interface to this module. This class does basic text assembly;
|
||
|
* given a string of text and a TextFont object, it creates a piece of
|
||
|
* geometry that may be placed in the 3-d or 2-d world to represent the
|
||
|
* indicated text.
|
||
|
*
|
||
|
* The TextNode may be used in one of two ways. Naively, it may simply be
|
||
|
* parented directly into the scene graph and rendered as if it were a
|
||
|
* GeomNode; in this mode, the actual polygon geometry that renders the text
|
||
|
* is not directly visible or accessible, but remains hidden within the
|
||
|
* TextNode.
|
||
|
*
|
||
|
* The second way TextNode may be used is as a text generator. To use it in
|
||
|
* this way, do not parent the TextNode to the scene graph; instead, set the
|
||
|
* properties of the text and call generate() to return an ordinary node,
|
||
|
* containing ordinary geometry, which you may use however you like. Each
|
||
|
* time you call generate() a new node is returned.
|
||
|
*/
|
||
|
class EXPCL_PANDA_TEXT TextNode : public PandaNode, public TextEncoder, public TextProperties {
|
||
|
PUBLISHED:
|
||
|
explicit TextNode(const std::string &name);
|
||
|
explicit TextNode(const std::string &name, const TextProperties ©);
|
||
|
protected:
|
||
|
TextNode(const TextNode ©);
|
||
|
virtual PandaNode *make_copy() const;
|
||
|
|
||
|
PUBLISHED:
|
||
|
~TextNode();
|
||
|
|
||
|
enum FlattenFlags {
|
||
|
FF_none = 0x0000,
|
||
|
FF_light = 0x0001,
|
||
|
FF_medium = 0x0002,
|
||
|
FF_strong = 0x0004,
|
||
|
FF_dynamic_merge = 0x0008,
|
||
|
};
|
||
|
|
||
|
INLINE PN_stdfloat get_line_height() const;
|
||
|
|
||
|
INLINE void set_max_rows(int max_rows);
|
||
|
INLINE void clear_max_rows();
|
||
|
INLINE bool has_max_rows() const;
|
||
|
INLINE int get_max_rows() const;
|
||
|
INLINE bool has_overflow() const;
|
||
|
|
||
|
INLINE void set_frame_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a);
|
||
|
INLINE void set_frame_color(const LColor &frame_color);
|
||
|
INLINE LColor get_frame_color() const;
|
||
|
|
||
|
INLINE void set_card_border(PN_stdfloat size, PN_stdfloat uv_portion);
|
||
|
INLINE void clear_card_border();
|
||
|
INLINE PN_stdfloat get_card_border_size() const;
|
||
|
INLINE PN_stdfloat get_card_border_uv_portion() const;
|
||
|
INLINE bool has_card_border() const;
|
||
|
|
||
|
INLINE void set_card_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a);
|
||
|
INLINE void set_card_color(const LColor &card_color);
|
||
|
INLINE LColor get_card_color() const;
|
||
|
|
||
|
INLINE void set_card_texture(Texture *card_texture);
|
||
|
INLINE void clear_card_texture();
|
||
|
INLINE bool has_card_texture() const;
|
||
|
INLINE Texture *get_card_texture() const;
|
||
|
|
||
|
INLINE void set_frame_as_margin(PN_stdfloat left, PN_stdfloat right,
|
||
|
PN_stdfloat bottom, PN_stdfloat top);
|
||
|
INLINE void set_frame_actual(PN_stdfloat left, PN_stdfloat right,
|
||
|
PN_stdfloat bottom, PN_stdfloat top);
|
||
|
INLINE void clear_frame();
|
||
|
INLINE bool has_frame() const;
|
||
|
INLINE bool is_frame_as_margin() const;
|
||
|
INLINE LVecBase4 get_frame_as_set() const;
|
||
|
INLINE LVecBase4 get_frame_actual() const;
|
||
|
|
||
|
INLINE void set_frame_line_width(PN_stdfloat line_width);
|
||
|
INLINE PN_stdfloat get_frame_line_width() const;
|
||
|
INLINE void set_frame_corners(bool corners);
|
||
|
INLINE bool get_frame_corners() const;
|
||
|
|
||
|
INLINE void set_card_as_margin(PN_stdfloat left, PN_stdfloat right,
|
||
|
PN_stdfloat bottom, PN_stdfloat top);
|
||
|
INLINE void set_card_actual(PN_stdfloat left, PN_stdfloat right,
|
||
|
PN_stdfloat bottom, PN_stdfloat top);
|
||
|
INLINE void set_card_decal(bool card_decal);
|
||
|
INLINE void clear_card();
|
||
|
INLINE bool has_card() const;
|
||
|
INLINE bool get_card_decal() const;
|
||
|
INLINE bool is_card_as_margin() const;
|
||
|
INLINE LVecBase4 get_card_as_set() const;
|
||
|
INLINE LVecBase4 get_card_actual() const;
|
||
|
INLINE LVecBase4 get_card_transformed() const;
|
||
|
|
||
|
INLINE void set_transform(const LMatrix4 &transform);
|
||
|
INLINE LMatrix4 get_transform() const;
|
||
|
|
||
|
INLINE void set_coordinate_system(CoordinateSystem cs);
|
||
|
INLINE CoordinateSystem get_coordinate_system() const;
|
||
|
|
||
|
INLINE void set_usage_hint(Geom::UsageHint usage_hint);
|
||
|
INLINE Geom::UsageHint get_usage_hint() const;
|
||
|
|
||
|
INLINE void set_flatten_flags(int flatten_flags);
|
||
|
INLINE int get_flatten_flags() const;
|
||
|
|
||
|
// These methods are inherited from TextProperties, but we override here so
|
||
|
// we can flag the TextNode as dirty when they have been changed.
|
||
|
|
||
|
INLINE void set_font(TextFont *font);
|
||
|
INLINE void clear_font();
|
||
|
|
||
|
INLINE void set_small_caps(bool small_caps);
|
||
|
INLINE void clear_small_caps();
|
||
|
|
||
|
INLINE void set_small_caps_scale(PN_stdfloat small_caps_scale);
|
||
|
INLINE void clear_small_caps_scale();
|
||
|
|
||
|
INLINE void set_slant(PN_stdfloat slant);
|
||
|
INLINE void clear_slant();
|
||
|
|
||
|
INLINE void set_align(Alignment align_type);
|
||
|
INLINE void clear_align();
|
||
|
|
||
|
INLINE void set_indent(PN_stdfloat indent);
|
||
|
INLINE void clear_indent();
|
||
|
|
||
|
INLINE void set_wordwrap(PN_stdfloat wordwrap);
|
||
|
INLINE void clear_wordwrap();
|
||
|
|
||
|
INLINE void set_text_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a);
|
||
|
INLINE void set_text_color(const LColor &text_color);
|
||
|
INLINE void clear_text_color();
|
||
|
|
||
|
INLINE void set_shadow_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a);
|
||
|
INLINE void set_shadow_color(const LColor &shadow_color);
|
||
|
INLINE void clear_shadow_color();
|
||
|
|
||
|
INLINE void set_shadow(PN_stdfloat xoffset, PN_stdfloat yoffset);
|
||
|
INLINE void set_shadow(const LVecBase2 &shadow_offset);
|
||
|
INLINE void clear_shadow();
|
||
|
|
||
|
INLINE void set_bin(const std::string &bin);
|
||
|
INLINE void clear_bin();
|
||
|
|
||
|
INLINE int set_draw_order(int draw_order);
|
||
|
INLINE void clear_draw_order();
|
||
|
|
||
|
INLINE void set_tab_width(PN_stdfloat tab_width);
|
||
|
INLINE void clear_tab_width();
|
||
|
|
||
|
INLINE void set_glyph_scale(PN_stdfloat glyph_scale);
|
||
|
INLINE void clear_glyph_scale();
|
||
|
|
||
|
INLINE void set_glyph_shift(PN_stdfloat glyph_shift);
|
||
|
INLINE void clear_glyph_shift();
|
||
|
|
||
|
// After the text has been set, you can query this to determine how it will
|
||
|
// be wordwrapped.
|
||
|
INLINE std::string get_wordwrapped_text() const;
|
||
|
|
||
|
// These methods calculate the width of a single character or a line of text
|
||
|
// in the current font.
|
||
|
PN_stdfloat calc_width(wchar_t character) const;
|
||
|
INLINE PN_stdfloat calc_width(const std::string &line) const;
|
||
|
|
||
|
bool has_exact_character(wchar_t character) const;
|
||
|
bool has_character(wchar_t character) const;
|
||
|
bool is_whitespace(wchar_t character) const;
|
||
|
|
||
|
INLINE std::wstring get_wordwrapped_wtext() const;
|
||
|
PN_stdfloat calc_width(const std::wstring &line) const;
|
||
|
|
||
|
virtual void output(std::ostream &out) const;
|
||
|
virtual void write(std::ostream &out, int indent_level = 0) const;
|
||
|
|
||
|
// The following functions return information about the text that was last
|
||
|
// built (and is currently visible).
|
||
|
INLINE PN_stdfloat get_left() const;
|
||
|
INLINE PN_stdfloat get_right() const;
|
||
|
INLINE PN_stdfloat get_bottom() const;
|
||
|
INLINE PN_stdfloat get_top() const;
|
||
|
INLINE PN_stdfloat get_height() const;
|
||
|
INLINE PN_stdfloat get_width() const;
|
||
|
|
||
|
INLINE LPoint3 get_upper_left_3d() const;
|
||
|
INLINE LPoint3 get_lower_right_3d() const;
|
||
|
|
||
|
INLINE int get_num_rows() const;
|
||
|
|
||
|
INLINE PT(PandaNode) generate();
|
||
|
INLINE void update();
|
||
|
INLINE void force_update();
|
||
|
|
||
|
PT(PandaNode) get_internal_geom() const;
|
||
|
|
||
|
PUBLISHED:
|
||
|
MAKE_PROPERTY(max_rows, get_max_rows, set_max_rows);
|
||
|
MAKE_PROPERTY(frame_color, get_frame_color, set_frame_color);
|
||
|
MAKE_PROPERTY(card_color, get_card_color, set_card_color);
|
||
|
MAKE_PROPERTY(card_texture, get_card_texture, set_card_texture);
|
||
|
MAKE_PROPERTY(frame_line_width, get_frame_line_width, set_frame_line_width);
|
||
|
MAKE_PROPERTY(frame_corners, get_frame_corners, set_frame_corners);
|
||
|
MAKE_PROPERTY(transform, get_transform, set_transform);
|
||
|
MAKE_PROPERTY(coordinate_system, get_coordinate_system, set_coordinate_system);
|
||
|
MAKE_PROPERTY(usage_hint, get_usage_hint, set_usage_hint);
|
||
|
MAKE_PROPERTY(flatten_flags, get_flatten_flags, set_flatten_flags);
|
||
|
|
||
|
MAKE_PROPERTY2(font, has_font, get_font, set_font, clear_font);
|
||
|
MAKE_PROPERTY2(small_caps, has_small_caps, get_small_caps,
|
||
|
set_small_caps, clear_small_caps);
|
||
|
MAKE_PROPERTY2(small_caps_scale, has_small_caps_scale, get_small_caps_scale,
|
||
|
set_small_caps_scale, clear_small_caps_scale);
|
||
|
MAKE_PROPERTY2(slant, has_slant, get_slant, set_slant, clear_slant);
|
||
|
MAKE_PROPERTY2(underscore, has_underscore, get_underscore,
|
||
|
set_underscore, clear_underscore);
|
||
|
MAKE_PROPERTY2(underscore_height, has_underscore_height, get_underscore_height,
|
||
|
set_underscore_height, clear_underscore_height);
|
||
|
MAKE_PROPERTY2(align, has_align, get_align, set_align, clear_align);
|
||
|
MAKE_PROPERTY2(indent, has_indent, get_indent, set_indent, clear_indent);
|
||
|
MAKE_PROPERTY2(wordwrap, has_wordwrap, get_wordwrap, set_wordwrap, clear_wordwrap);
|
||
|
MAKE_PROPERTY2(preserve_trailing_whitespace,
|
||
|
has_preserve_trailing_whitespace, get_preserve_trailing_whitespace,
|
||
|
set_preserve_trailing_whitespace, clear_preserve_trailing_whitespace);
|
||
|
MAKE_PROPERTY2(text_color, has_text_color, get_text_color,
|
||
|
set_text_color, clear_text_color);
|
||
|
MAKE_PROPERTY2(shadow_color, has_shadow_color, get_shadow_color,
|
||
|
set_shadow_color, clear_shadow_color);
|
||
|
MAKE_PROPERTY2(shadow, has_shadow, get_shadow, set_shadow, clear_shadow);
|
||
|
MAKE_PROPERTY2(bin, has_bin, get_bin, set_bin, clear_bin);
|
||
|
MAKE_PROPERTY2(draw_order, has_draw_order, get_draw_order,
|
||
|
set_draw_order, clear_draw_order);
|
||
|
MAKE_PROPERTY2(tab_width, has_tab_width, get_tab_width,
|
||
|
set_tab_width, clear_tab_width);
|
||
|
MAKE_PROPERTY2(glyph_scale, has_glyph_scale, get_glyph_scale,
|
||
|
set_glyph_scale, clear_glyph_scale);
|
||
|
MAKE_PROPERTY2(glyph_shift, has_glyph_shift, get_glyph_shift,
|
||
|
set_glyph_shift, clear_glyph_shift);
|
||
|
MAKE_PROPERTY2(text_scale, has_text_scale, get_text_scale,
|
||
|
set_text_scale, clear_text_scale);
|
||
|
|
||
|
public:
|
||
|
// From parent class TextEncoder;
|
||
|
virtual void text_changed() final;
|
||
|
|
||
|
// From parent class PandaNode
|
||
|
virtual int get_unsafe_to_apply_attribs() const;
|
||
|
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs,
|
||
|
int attrib_types,
|
||
|
GeomTransformer &transformer);
|
||
|
virtual CPT(TransformState)
|
||
|
calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
||
|
bool &found_any,
|
||
|
const TransformState *transform,
|
||
|
Thread *current_thread) const;
|
||
|
|
||
|
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
|
||
|
virtual bool is_renderable() const;
|
||
|
|
||
|
virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
|
||
|
int &internal_vertices,
|
||
|
int pipeline_stage,
|
||
|
Thread *current_thread) const;
|
||
|
|
||
|
virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg,
|
||
|
const RenderState *node_state,
|
||
|
GeomTransformer &transformer,
|
||
|
Thread *current_thread);
|
||
|
|
||
|
private:
|
||
|
INLINE void invalidate_no_measure();
|
||
|
INLINE void invalidate_with_measure();
|
||
|
INLINE void check_rebuild() const;
|
||
|
INLINE void check_measure() const;
|
||
|
|
||
|
void do_rebuild();
|
||
|
void do_measure();
|
||
|
|
||
|
PT(PandaNode) do_generate();
|
||
|
PT(PandaNode) do_get_internal_geom() const;
|
||
|
|
||
|
PT(PandaNode) make_frame();
|
||
|
PT(PandaNode) make_card();
|
||
|
PT(PandaNode) make_card_with_border();
|
||
|
|
||
|
static int count_geoms(PandaNode *node);
|
||
|
|
||
|
Mutex _lock;
|
||
|
PT(PandaNode) _internal_geom;
|
||
|
|
||
|
PT(Texture) _card_texture;
|
||
|
LColor _frame_color;
|
||
|
LColor _card_color;
|
||
|
|
||
|
enum Flags {
|
||
|
F_has_frame = 0x0001,
|
||
|
F_frame_as_margin = 0x0002,
|
||
|
F_has_card = 0x0004,
|
||
|
F_card_as_margin = 0x0008,
|
||
|
F_has_card_texture = 0x0010,
|
||
|
F_frame_corners = 0x0020,
|
||
|
F_card_transp = 0x0040,
|
||
|
F_has_card_border = 0x0080,
|
||
|
F_needs_rebuild = 0x0100,
|
||
|
F_needs_measure = 0x0200,
|
||
|
F_has_overflow = 0x0400,
|
||
|
F_card_decal = 0x0800,
|
||
|
};
|
||
|
|
||
|
int _flags;
|
||
|
int _max_rows;
|
||
|
GeomEnums::UsageHint _usage_hint;
|
||
|
int _flatten_flags;
|
||
|
PN_stdfloat _frame_width;
|
||
|
PN_stdfloat _card_border_size;
|
||
|
PN_stdfloat _card_border_uv_portion;
|
||
|
|
||
|
LVector2 _frame_ul, _frame_lr;
|
||
|
LVector2 _card_ul, _card_lr;
|
||
|
|
||
|
LMatrix4 _transform;
|
||
|
CoordinateSystem _coordinate_system;
|
||
|
|
||
|
LPoint3 _ul3d, _lr3d;
|
||
|
|
||
|
// Returned from TextAssembler:
|
||
|
LVector2 _text_ul, _text_lr;
|
||
|
int _num_rows;
|
||
|
std::wstring _wordwrapped_wtext;
|
||
|
|
||
|
static PStatCollector _text_generate_pcollector;
|
||
|
|
||
|
public:
|
||
|
static TypeHandle get_class_type() {
|
||
|
return _type_handle;
|
||
|
}
|
||
|
static void init_type() {
|
||
|
PandaNode::init_type();
|
||
|
TextProperties::init_type();
|
||
|
register_type(_type_handle, "TextNode",
|
||
|
PandaNode::get_class_type(),
|
||
|
TextProperties::get_class_type());
|
||
|
}
|
||
|
virtual TypeHandle get_type() const {
|
||
|
return get_class_type();
|
||
|
}
|
||
|
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||
|
|
||
|
private:
|
||
|
static TypeHandle _type_handle;
|
||
|
};
|
||
|
|
||
|
#include "textNode.I"
|
||
|
|
||
|
#endif
|