diff --git a/panda/metalibs/panda/Sources.pp b/panda/metalibs/panda/Sources.pp index 59bc995229..3f229761df 100644 --- a/panda/metalibs/panda/Sources.pp +++ b/panda/metalibs/panda/Sources.pp @@ -6,7 +6,7 @@ #define DIR_TYPE metalib #define BUILDING_DLL BUILDING_PANDA -#define USE_PACKAGES net cv +#define USE_PACKAGES net #define COMPONENT_LIBS \ recorder pgraph \ diff --git a/panda/src/chan/animControl.I b/panda/src/chan/animControl.I index 63df29f07f..4974c05910 100644 --- a/panda/src/chan/animControl.I +++ b/panda/src/chan/animControl.I @@ -16,92 +16,6 @@ // //////////////////////////////////////////////////////////////////// -#include - - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::set_play_rate -// Access: Published -// Description: Sets the speed of the animation, relative to its -// "normal" speed. Setting this number to 2.0 plays it -// twice as fast, 0.5 half as fast. -1.0 plays it -// backwards, and 0.0 stops it. The change is actually -// retroactive to the last frame. -// -// If you are going to change the play_rate from a -// positive number to a negative number, or vice-versa, -// you should do this before starting the animation. -// The various flavors of play() and loop() do slightly -// different behavior based on whether play_rate is -// positive or negative. -//////////////////////////////////////////////////////////////////// -INLINE void AnimControl:: -set_play_rate(double play_rate) { - _play_rate = play_rate; -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::get_play_rate -// Access: Published -// Description: Returns the current speed of the animation. See -// set_play_rate(). -//////////////////////////////////////////////////////////////////// -INLINE double AnimControl:: -get_play_rate() const { - return _play_rate; -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::get_frame_rate -// Access: Published -// Description: Returns the actual frame rate of the animation, based -// on the play_rate (see set_play_rate()) and the -// animation's base frame rate (see -// AnimBundle::get_base_frame_rate()). This is in -// frames per second. -//////////////////////////////////////////////////////////////////// -INLINE double AnimControl:: -get_frame_rate() const { - return get_play_rate() * get_anim()->get_base_frame_rate(); -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::get_frame -// Access: Published -// Description: Returns the current frame number of the animation. -//////////////////////////////////////////////////////////////////// -INLINE int AnimControl:: -get_frame() const { - // We have to use floor() here instead of simply casting the number - // to an integer, becase the frame number might have become - // negative. - return (int)cfloor(_frame + 0.0001); -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::get_num_frames -// Access: Published -// Description: Returns the number of frames of animation. This is -// actually just extracted directly from the AnimBundle; -// the function is duplicated here for convenience. The -// frame number will never be outside the range 0 <= -// frame < get_num_frames(). -//////////////////////////////////////////////////////////////////// -INLINE int AnimControl:: -get_num_frames() const { - return get_anim()->get_num_frames(); -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::is_playing -// Access: Published -// Description: Returns true if the AnimControl is currently playing, -// false otherwise. -//////////////////////////////////////////////////////////////////// -INLINE bool AnimControl:: -is_playing() const { - return _playing; -} //////////////////////////////////////////////////////////////////// // Function: AnimControl::get_anim diff --git a/panda/src/chan/animControl.cxx b/panda/src/chan/animControl.cxx index c3a6322d19..312b3dd952 100644 --- a/panda/src/chan/animControl.cxx +++ b/panda/src/chan/animControl.cxx @@ -16,16 +16,11 @@ // //////////////////////////////////////////////////////////////////// - #include "animControl.h" #include "animChannelBase.h" #include "partBundle.h" #include "config_chan.h" -#include "event.h" -#include "throw_event.h" - - TypeHandle AnimControl::_type_handle; //////////////////////////////////////////////////////////////////// @@ -42,18 +37,15 @@ AnimControl(PartBundle *part, AnimBundle *anim, int channel_index) { _part = part; _anim = anim; _channel_index = channel_index; - - _play_rate = 1.0f; - _frame = 0.0f; - _as_of_time = 0.0f; - _playing = false; + set_frame_rate(_anim->get_base_frame_rate()); + set_num_frames(_anim->get_num_frames()); _marked_frame = -1; } //////////////////////////////////////////////////////////////////// // Function: AnimControl::Destructor -// Access: Published +// Access: Published, Virtual // Description: //////////////////////////////////////////////////////////////////// AnimControl:: @@ -61,296 +53,6 @@ AnimControl:: get_part()->set_control_effect(this, 0.0f); } - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::play -// Access: Published -// Description: Runs the entire animation from beginning to end and -// stops, throwing the stop event (if it is non-NULL). -//////////////////////////////////////////////////////////////////// -void AnimControl:: -play(const CPT_Event &stop_event) { - nassertv(get_num_frames() > 0); - - if (get_play_rate() < 0.0f) { - play(get_num_frames()-1, 0, stop_event); - } else { - play(0, get_num_frames()-1, stop_event); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::play -// Access: Published -// Description: Runs the animation from the frame "from" to and -// including the frame "to", at which point the -// animation is stopped and the indicated stop event is -// thrown (if it is non-NULL). If the to frame is less -// than the from frame (unless play_rate is negative), -// the animation will wrap around the end and begins -// again at the beginning before the animation stops. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -play(int from, int to, const CPT_Event &stop_event) { - nassertv(get_num_frames() > 0); - - nassertv(from >= 0 && from < get_num_frames()); - nassertv(to >= 0 && to < get_num_frames()); - _as_of_time = ClockObject::get_global_clock()->get_frame_time(); - _playing = true; - - _actions = _user_actions; - if (stop_event != (Event*)0L) { - insert_event_action(_actions, to, stop_event); - } - insert_stop_action(_actions, to); - - get_part()->control_activated(this); - set_frame(from); -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::loop -// Access: Published -// Description: Starts the entire animation looping. If restart is -// true, the animation is restarted from the beginning; -// otherwise, it continues from the current frame. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -loop(bool restart) { - nassertv(get_num_frames() > 0); - - _as_of_time = ClockObject::get_global_clock()->get_frame_time(); - _playing = true; - - _actions = _user_actions; - get_part()->control_activated(this); - - if (restart) { - if (get_play_rate() < 0.0f) { - set_frame(get_num_frames() - 1); - } else { - set_frame(0); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::loop -// Access: Published -// Description: Loops the animation from the frame "from" to and -// including the frame "to", indefinitely. If restart -// is true, the animation is restarted from the -// beginning; otherwise, it continues from the current -// frame. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -loop(bool restart, int from, int to) { - nassertv(get_num_frames() > 0); - - nassertv(from >= 0 && from < get_num_frames()); - nassertv(to >= 0 && to < get_num_frames()); - _as_of_time = ClockObject::get_global_clock()->get_frame_time(); - _playing = true; - - _actions = _user_actions; - - if (get_play_rate() < 0.0f) { - // If we're playing backward, we need to set up the loop a little - // differently. - - if ((to == 0 && from == get_num_frames()-1) || - (to == from-1)) { - - // In this case, the user has specified to loop over the whole - // range of animation. We don't need a special jump action to - // handle this. - - } else { - // Otherwise, set up a jump action to effect the loop. This isn't - // completely accurate, since it will always jump exactly to the - // first frame of the loop, no matter how many frames past the end - // we'd gotten to, but it should be reasonably close, especially - // if the number of frames in the loop is large enough and/or the - // frame rate is high enough. - insert_jump_action(_actions, (to-1+get_num_frames())%get_num_frames(), - from); - } - } else { - - if ((from == 0 && to == get_num_frames()-1) || - (from == to-1)) { - - // In this case, the user has specified to loop over the whole - // range of animation. We don't need a special jump action to - // handle this. - - } else { - // Otherwise, set up a jump action to effect the loop. This isn't - // completely accurate, since it will always jump exactly to the - // first frame of the loop, no matter how many frames past the end - // we'd gotten to, but it should be reasonably close, especially - // if the number of frames in the loop is large enough and/or the - // frame rate is high enough. - insert_jump_action(_actions, (to+1)%get_num_frames(), from); - } - } - - get_part()->control_activated(this); - if (restart) { - set_frame(from); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::pingpong -// Access: Published -// Description: Loops the animation from the frame "from" to and -// including the frame "to", and then back in the -// opposite direction, indefinitely. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -pingpong(bool restart, int from, int to) { - if (from == to) { - pose(from); - return; - } - - nassertv(get_num_frames() > 0); - - nassertv(from >= 0 && from < get_num_frames()); - nassertv(to >= 0 && to < get_num_frames()); - _as_of_time = ClockObject::get_global_clock()->get_frame_time(); - _playing = true; - - _actions = _user_actions; - - insert_forward_action(_actions, from); - insert_backward_action(_actions, to); - - get_part()->control_activated(this); - if (restart) { - set_frame(from); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::stop -// Access: Published -// Description: Stops a currently playing or looping animation right -// where it is. The animation remains posed at the -// current frame, and no event is thrown. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -stop() { - _playing = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::pose -// Access: Published -// Description: Sets the animation to the indicated frame and holds -// it there. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -pose(int frame) { - int num_frames = get_num_frames(); - nassertv(num_frames > 0); - - // Modulo the number of frames. - frame = (int)(frame - cfloor(frame / num_frames) * num_frames); - nassertv(frame >= 0 && frame < num_frames); - _as_of_time = ClockObject::get_global_clock()->get_frame_time(); - _playing = false; - - _actions = _user_actions; - - get_part()->control_activated(this); - set_frame(frame); -} - - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::add_event -// Access: Published -// Description: Adds the indicated event to the list of events that -// will be called whenever the animation reaches the -// indicated frame number. Once added, the event will -// persist until it is removed via remove_event() or -// remove_all_events(). -//////////////////////////////////////////////////////////////////// -void AnimControl:: -add_event(int frame, const CPT_Event &event) { - insert_event_action(_user_actions, frame, event); - if (_playing) { - insert_event_action(_actions, frame, event); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::remove_event -// Access: Published -// Description: Removes all events found that match the indicated -// event name, and returns the number of events -// removed. -//////////////////////////////////////////////////////////////////// -int AnimControl:: -remove_event(const string &event_name) { - Actions new_actions; - - int removed = 0; - - Actions::const_iterator ai; - for (ai = _user_actions.begin(); ai != _user_actions.end(); ++ai) { - const Action &action = (*ai).second; - if (action._type == AT_event && - action._event->get_name() == event_name) { - // Remove this event by not copying it to new_actions. - removed++; - } else { - // Preserve this event. - new_actions.insert(*ai); - } - } - - if (removed != 0) { - _user_actions.swap(new_actions); - - if (_playing) { - new_actions.clear(); - int p_removed = 0; - for (ai = _actions.begin(); ai != _actions.end(); ++ai) { - const Action &action = (*ai).second; - if (action._type == AT_event && - action._event->get_name() == event_name) { - // Remove this event by not copying it to new_actions. - p_removed++; - } else { - // Preserve this event. - new_actions.insert(*ai); - } - } - nassertr(p_removed == removed, removed); - _actions.swap(new_actions); - } - } - - return removed; -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::remove_all_events -// Access: Published -// Description: Removes all user-defined event messages. However, if -// called while an animation is running, this will not -// take effect until the animation is stopped and -// restarted. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -remove_all_events() { - _user_actions.clear(); -} - //////////////////////////////////////////////////////////////////// // Function: AnimControl::get_part // Access: Published @@ -370,77 +72,11 @@ get_part() const { void AnimControl:: output(ostream &out) const { out << "AnimControl(" << get_part()->get_name() - << ", " << get_anim()->get_name() << ")"; + << ", " << get_anim()->get_name() << ": "; + AnimInterface::output(out); + out << ")"; } - - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::advance_time -// Access: Public -// Description: Tells the AnimControl what time it is. This -// recomputes the frame number according to the amount -// of time elapsed since last time. Until this function -// is called, the frame number will not increment. The -// time passed to this function must be nondecreasing; -// it is an error to call it with a value less than a -// previously-passed value. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -advance_time(double time) { - double elapsed_time = time - _as_of_time; - double elapsed_frames = elapsed_time * get_frame_rate(); - _as_of_time = time; - - if (_playing && elapsed_frames != 0.0f) { - int orig_frame = get_frame(); - - _frame += elapsed_frames; - double num_frames = (double)get_num_frames(); - - int new_frame = get_frame(); - - // Now call all the actions. - if (elapsed_frames < 0.0f) { - // If we're playing the animation backward, we have to check the - // actions in reverse order. - - if (new_frame >= 0) { - do_actions_backward(orig_frame-1, new_frame); - } else { - if (do_actions_backward(orig_frame-1, 0)) { - // floor() is correct here, instead of simply an integer - // cast, because we are using floating-point arithmetic - // anyway (no need to convert to integer format and back - // again), and because we need correct behavior when the - // frame number is negative. - _frame = _frame - cfloor(_frame / num_frames) * num_frames; - new_frame = get_frame(); - do_actions_backward(get_num_frames(), new_frame); - } - } - } else { - // Normally, we'll be playing the animation forward. - - if (new_frame < get_num_frames()) { - do_actions_forward(orig_frame+1, new_frame); - } else { - if (do_actions_forward(orig_frame+1, get_num_frames()-1)) { - // floor() is correct here, instead of simply an integer - // cast, because we are using floating-point arithmetic - // anyway (no need to convert to integer format and back - // again), and because we need correct behavior when the - // frame number is negative. - _frame = _frame - cfloor(_frame / num_frames) * num_frames; - new_frame = get_frame(); - do_actions_forward(0, new_frame); - } - } - } - } -} - - //////////////////////////////////////////////////////////////////// // Function: AnimControl::channel_has_changed // Access: Public @@ -457,7 +93,6 @@ channel_has_changed(AnimChannelBase *channel) const { return channel->has_changed(_marked_frame, this_frame); } - //////////////////////////////////////////////////////////////////// // Function: AnimControl::mark_channels // Access: Public @@ -469,307 +104,14 @@ mark_channels() { _marked_frame = get_frame(); } - //////////////////////////////////////////////////////////////////// -// Function: AnimControl::insert_event_action -// Access: Private, Static -// Description: Inserts an "event" action at the indicated frame -// number. The event will be thrown as the animation -// reaches the indicated frame number. +// Function: AnimControl::animation_activated +// Access: Protected, Virtual +// Description: This is provided as a callback method for when the +// user calls one of the play/loop/pose type methods to +// start the animation playing. //////////////////////////////////////////////////////////////////// void AnimControl:: -insert_event_action(Actions &actions, int frame, const CPT_Event &event) { - Action new_action; - new_action._type = AT_event; - new_action._event = event; - actions.insert(pair(frame, new_action)); -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::insert_stop_action -// Access: Private, Static -// Description: Inserts a "stop" action at the indicated frame -// number. The animation will stop as soon as it -// reaches the indicated frame number, traveling from -// either direction. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -insert_stop_action(Actions &actions, int frame) { - Action new_action; - new_action._type = AT_stop; - actions.insert(pair(frame, new_action)); -} - - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::insert_jump_action -// Access: Private, Static -// Description: Inserts a "jump" action at the indicated frame -// number. When the animation reaches the indicated -// frame number, it will jump to the indicated jump_to -// frame. It will not seem to spend any time at the -// reached frame number. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -insert_jump_action(Actions &actions, int frame, int jump_to) { - Action new_action; - new_action._type = AT_jump; - new_action._jump_to = jump_to; - actions.insert(pair(frame, new_action)); -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::insert_forward_action -// Access: Private, Static -// Description: Inserts a "forward" action at the indicated frame -// number. When the animation hits this action while -// playing in a backward direction, it will stop and -// play in a forward direction instead. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -insert_forward_action(Actions &actions, int frame) { - Action new_action; - new_action._type = AT_forward; - actions.insert(pair(frame, new_action)); -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::insert_backward_action -// Access: Private, Static -// Description: Inserts a "backward" action at the indicated frame -// number. When the animation hits this action while -// playing in a forward direction, it will stop and -// play in a backward direction instead. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -insert_backward_action(Actions &actions, int frame) { - Action new_action; - new_action._type = AT_backward; - actions.insert(pair(frame, new_action)); -} - - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::set_frame -// Access: Private -// Description: Sets the current frame number to the indicated frame, -// and performs any actions on that frame. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -set_frame(double frame) { - _frame = frame; - int iframe = get_frame(); - do_actions_forward(iframe, iframe); -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::do_actions_forward -// Access: Private -// Description: Calls each of the actions, in turn, on the timeline -// between the indicated "from" frame and the indicated -// "to" frame, inclusive. If any of the actions -// specifies to stop the animation, the animation is -// stopped, the current frame number is set to the point -// of stopping, no further actions are called, and false -// is returned. Otherwise, true is returned. -//////////////////////////////////////////////////////////////////// -bool AnimControl:: -do_actions_forward(int from, int to) { - if (to >= from) { - Actions::const_iterator lower = _actions.lower_bound(from); - Actions::const_iterator upper = _actions.lower_bound(to+1); - - int sequence_frame = -1; - const Action *sequence_action; - - Actions::const_iterator ai; - for (ai = lower; ai != upper; ++ai) { - int frame = (*ai).first; - const Action &action = (*ai).second; - - if (sequence_frame != -1 && frame > sequence_frame) { - // We encountered an action that resequenced our frame numbers. - // Now that we've finished evaluating all the other actions that - // occurred in the same frame, evaluate this one action and - // exit. - do_sequence_action(sequence_frame, *sequence_action); - return false; - } - - do_action(frame, action, sequence_frame, sequence_action); - } - - if (sequence_frame != -1) { - do_sequence_action(sequence_frame, *sequence_action); - return false; - } - } - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::do_actions_backward -// Access: Private -// Description: Calls each of the actions, in turn, on the timeline -// between the indicated "from" frame and the indicated -// "to" frame, in reverse order. If any of the actions -// specifies to stop the animation, the animation is -// stopped, the current frame number is set to the point -// of stopping, no further actions are called, and false -// is returned. Otherwise, true is returned. -//////////////////////////////////////////////////////////////////// -bool AnimControl:: -do_actions_backward(int from, int to) { - if (from >= to) { -#if defined(WIN32_VC) && !defined(NO_PCH) - typedef Actions::const_reverse_iterator Action_reverse_iterator; -#else - typedef reverse_iterator Action_reverse_iterator; -#endif - Action_reverse_iterator lower(_actions.upper_bound(from)); - Action_reverse_iterator upper(_actions.upper_bound(to-1)); - - int sequence_frame = -1; - const Action *sequence_action; - - Action_reverse_iterator ai; - for (ai = lower; ai != upper; ++ai) { - int frame = (*ai).first; - const Action &action = (*ai).second; - - if (sequence_frame != -1 && frame < sequence_frame) { - // We encountered an action that resequenced our frame numbers. - // Now that we've finished evaluating all the other actions that - // occurred in the same frame, evaluate this one action and - // exit. - do_sequence_action(sequence_frame, *sequence_action); - return false; - } - - do_action(frame, action, sequence_frame, sequence_action); - } - - if (sequence_frame != -1) { - do_sequence_action(sequence_frame, *sequence_action); - return false; - } - } - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::do_action -// Access: Private -// Description: Performs a single action. If the action involves -// some resequencing behavior--stopping, or jumping -// around to a new frame or something--does nothing -// immediately, but instead sets sequence_frame and -// sequence_action to the current frame number and -// action, so they may be executed later (after all the -// other actions this frame have been executed). -//////////////////////////////////////////////////////////////////// -void AnimControl:: -do_action(int frame, const Action &action, - int &sequence_frame, const Action *&sequence_action) { - switch (action._type) { - case AT_stop: - case AT_jump: - sequence_frame = frame; - sequence_action = &action; - break; - - case AT_forward: - // We only see "forward" actions if we're currently playing - // backwards. - if (_play_rate < 0.0f) { - sequence_frame = frame; - sequence_action = &action; - } - break; - - case AT_backward: - // We only see "backward" actions if we're currently playing - // forwards. - if (_play_rate > 0.0f) { - sequence_frame = frame; - sequence_action = &action; - } - break; - - case AT_event: - throw_event(action._event); - break; - - default: - chan_cat.error() << "Invalid action!\n"; - abort(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::do_sequence_action -// Access: Private -// Description: Performs an action that was saved from do_action(), -// above. This action presumably does some mucking -// around with the frame number or something, so we -// needed to do all the other actions associated with -// that frame first. -//////////////////////////////////////////////////////////////////// -void AnimControl:: -do_sequence_action(int frame, const Action &action) { - switch (action._type) { - case AT_stop: - stop(); - break; - - case AT_jump: - set_frame(action._jump_to); - break; - - case AT_forward: - case AT_backward: - _play_rate = -_play_rate; - set_frame(frame); - break; - - case AT_event: - default: - chan_cat.error() << "Invalid sequence action!\n"; - abort(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControl::Action::output -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void AnimControl::Action:: -output(ostream &out) const { - switch (_type) { - case AT_event: - out << "event " << *_event; - break; - - case AT_stop: - out << "stop"; - break; - - case AT_jump: - out << "jump to " << _jump_to; - break; - - case AT_forward: - out << "forward"; - break; - - case AT_backward: - out << "backward"; - break; - - default: - out << "**error**"; - } +animation_activated() { + get_part()->control_activated(this); } diff --git a/panda/src/chan/animControl.h b/panda/src/chan/animControl.h index 125de0e2fa..4a0947c4d4 100644 --- a/panda/src/chan/animControl.h +++ b/panda/src/chan/animControl.h @@ -21,17 +21,11 @@ #include "pandabase.h" +#include "animInterface.h" #include "animBundle.h" #include "partGroup.h" -#include "clockObject.h" -#include "typedef.h" #include "referenceCount.h" -#include "event.h" -#include "pt_Event.h" -#include "cmath.h" -#include -#include "pmap.h" class PartBundle; class AnimChannelBase; @@ -44,93 +38,31 @@ class AnimChannelBase; // animation: whether started, stopped, or looping, and // the current frame number and play rate. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA AnimControl : public ReferenceCount { +class EXPCL_PANDA AnimControl : public ReferenceCount, public AnimInterface { public: AnimControl(PartBundle *part, AnimBundle *anim, int channel_index); PUBLISHED: - ~AnimControl(); - void play(const CPT_Event &stop_event = NULL); - void play(int from, int to, const CPT_Event &stop_event = NULL); - void loop(bool restart); - void loop(bool restart, int from, int to); - void pingpong(bool restart, int from, int to); - void stop(); - void pose(int frame); - - void add_event(int frame, const CPT_Event &event); - int remove_event(const string &event_name); - void remove_all_events(); - - INLINE void set_play_rate(double play_rate); - INLINE double get_play_rate() const; - INLINE double get_frame_rate() const; - - INLINE int get_frame() const; - INLINE int get_num_frames() const; - - INLINE bool is_playing() const; + virtual ~AnimControl(); PartBundle *get_part() const; INLINE AnimBundle *get_anim() const; INLINE int get_channel_index() const; - void output(ostream &out) const; + virtual void output(ostream &out) const; public: // The following functions aren't really part of the public // interface; they're just public so we don't have to declare a // bunch of friends. - void advance_time(double time); - bool channel_has_changed(AnimChannelBase *channel) const; void mark_channels(); -private: - - enum ActionType { - AT_event, - AT_stop, - AT_jump, - AT_forward, - AT_backward, - }; - -#ifdef WIN32_VC -public: -#endif - - class EXPCL_PANDA Action { - public: - ActionType _type; - CPT_Event _event; - int _jump_to; - - void output(ostream &out) const; - }; +protected: + virtual void animation_activated(); private: - typedef pmultimap Actions; - - static void insert_event_action(Actions &actions, int frame, const CPT_Event &event); - static void insert_stop_action(Actions &actions, int frame); - static void insert_jump_action(Actions &actions, int frame, int jump_to); - static void insert_forward_action(Actions &actions, int frame); - static void insert_backward_action(Actions &actions, int frame); - - void set_frame(double frame); - - bool do_actions_forward(int from, int to); - bool do_actions_backward(int from, int to); - - void do_action(int frame, const Action &action, - int &sequence_frame, const Action *&sequence_action); - void do_sequence_action(int frame, const Action &action); - - Actions _actions; - Actions _user_actions; - // This is a PT(PartGroup) instead of a PT(PartBundle), just because // we can't include partBundle.h for circular reasons. But it // actually keeps a pointer to a PartBundle. @@ -138,17 +70,6 @@ private: PT(AnimBundle) _anim; int _channel_index; - double _play_rate; - - // We keep a floating-point frame number. This increments fluidly, - // and records honest "between-frame" increments. However, whenever - // we report the current frame number, we just report the integer - // portion. - double _frame; - double _as_of_time; - - bool _playing; - // This is the frame number as of the last call to mark_channels(). int _marked_frame; @@ -158,27 +79,16 @@ public: } static void init_type() { ReferenceCount::init_type(); + AnimInterface::init_type(); register_type(_type_handle, "AnimControl", - ReferenceCount::get_class_type()); + ReferenceCount::get_class_type(), + AnimInterface::get_class_type()); } private: static TypeHandle _type_handle; - -friend inline ostream &operator << (ostream &, const AnimControl::Action &); -friend class AnimControl::Action; }; -inline ostream &operator << (ostream &out, const AnimControl &ac) { - ac.output(out); - return out; -} - -inline ostream &operator << (ostream &out, const AnimControl::Action &action) { - action.output(out); - return out; -} - #include "animControl.I" #endif diff --git a/panda/src/chan/animControlCollection.I b/panda/src/chan/animControlCollection.I index dca6e01775..213d0cf94b 100644 --- a/panda/src/chan/animControlCollection.I +++ b/panda/src/chan/animControlCollection.I @@ -17,60 +17,6 @@ //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Function: AnimControlCollection::set_stop_event -// Access: Public -// Description: Sets the event that will be thrown when the next -// animation that is played eventually comes to a stop. -// Setting this does not affect any stop event that is -// pending from a previously-started animation. -//////////////////////////////////////////////////////////////////// -INLINE void AnimControlCollection:: -set_stop_event(const CPT_Event &stop_event) { - _stop_event = stop_event; -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControlCollection::clear_stop_event -// Access: Public -// Description: Indicates that the next-started animation will not -// throw a stop event when it comes to a stop. This -// does not affect any already-started animations. -//////////////////////////////////////////////////////////////////// -INLINE void AnimControlCollection:: -clear_stop_event() { - _stop_event = (const Event *)NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControlCollection::has_stop_event -// Access: Public -// Description: Returns true if a stop event has been established via -// set_stop_event(). If true, this means that -// animations that are to be started in the future will -// throw this event when they stop. However, it does -// not necessarily mean that the currently-playing -// animation will throw this event. -//////////////////////////////////////////////////////////////////// -INLINE bool AnimControlCollection:: -has_stop_event() const { - return (_stop_event != (const Event *)NULL); -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimControlCollection::get_stop_event -// Access: Public -// Description: Returns the event that has been established via -// set_stop_event(). This is the event that will be -// thrown by animations that are started in the future -// when they stop. However, this may or may not be -// associated with any currently-playing animations. -//////////////////////////////////////////////////////////////////// -INLINE CPT_Event AnimControlCollection:: -get_stop_event() const { - return _stop_event; -} - //////////////////////////////////////////////////////////////////// // Function: AnimControlCollection::play // Access: Public @@ -83,7 +29,7 @@ play(const string &anim_name) { return false; } _last_started_control = control; - control->play(_stop_event); + control->play(); return true; } @@ -99,7 +45,7 @@ play(const string &anim_name, int from, int to) { return false; } _last_started_control = control; - control->play(from, to, _stop_event); + control->play(from, to); return true; } diff --git a/panda/src/chan/animControlCollection.h b/panda/src/chan/animControlCollection.h index 7b5349c557..920514be55 100644 --- a/panda/src/chan/animControlCollection.h +++ b/panda/src/chan/animControlCollection.h @@ -52,11 +52,6 @@ PUBLISHED: string get_anim_name(int n) const; void clear_anims(); - INLINE void set_stop_event(const CPT_Event &stop_event); - INLINE void clear_stop_event(); - INLINE bool has_stop_event() const; - INLINE CPT_Event get_stop_event() const; - // The following functions are convenience functions that vector // directly into the AnimControl's functionality by anim name. @@ -100,7 +95,6 @@ private: typedef pmap ControlsByName; ControlsByName _controls_by_name; - CPT_Event _stop_event; AnimControl *_last_started_control; }; diff --git a/panda/src/chan/partBundle.cxx b/panda/src/chan/partBundle.cxx index f36dd9d7ff..fccc616705 100644 --- a/panda/src/chan/partBundle.cxx +++ b/panda/src/chan/partBundle.cxx @@ -326,21 +326,6 @@ bind_anim(AnimBundle *anim, const string &name, return true; } -//////////////////////////////////////////////////////////////////// -// Function: PartBundle::advance_time -// Access: Public -// Description: Calls advance_time() on all AnimControls currently -// in effect. -//////////////////////////////////////////////////////////////////// -void PartBundle:: -advance_time(double time) { - ChannelBlend::const_iterator cbi; - for (cbi = _blend.begin(); cbi != _blend.end(); ++cbi) { - AnimControl *control = (*cbi).first; - control->advance_time(time); - } -} - //////////////////////////////////////////////////////////////////// // Function: PartBundle::update // Access: Public diff --git a/panda/src/chan/partBundle.h b/panda/src/chan/partBundle.h index 511eebaa29..3fd64319a0 100644 --- a/panda/src/chan/partBundle.h +++ b/panda/src/chan/partBundle.h @@ -123,7 +123,6 @@ public: // interface; they're just public so we don't have to declare a // bunch of friends. - void advance_time(double time); bool update(); bool force_update(); virtual void control_activated(AnimControl *control); diff --git a/panda/src/char/character.cxx b/panda/src/char/character.cxx index 5c0e37981c..2f32edd28e 100644 --- a/panda/src/char/character.cxx +++ b/panda/src/char/character.cxx @@ -160,10 +160,8 @@ cull_callback(CullTraverser *, CullTraverserData &) { PStatTimer timer(_joints_pcollector); - double now = ClockObject::get_global_clock()->get_frame_time(); - get_bundle()->advance_time(now); - if (char_cat.is_spam()) { + double now = ClockObject::get_global_clock()->get_frame_time(); char_cat.spam() << "Animating " << *this << " at time " << now << "\n"; } @@ -183,10 +181,8 @@ cull_callback(CullTraverser *, CullTraverserData &) { //////////////////////////////////////////////////////////////////// void Character:: update_to_now() { - double now = ClockObject::get_global_clock()->get_frame_time(); - get_bundle()->advance_time(now); - if (char_cat.is_spam()) { + double now = ClockObject::get_global_clock()->get_frame_time(); char_cat.spam() << "Animating " << *this << " at time " << now << "\n"; } diff --git a/panda/src/downloader/Sources.pp b/panda/src/downloader/Sources.pp index 64ca2db5f4..49533f9f0d 100644 --- a/panda/src/downloader/Sources.pp +++ b/panda/src/downloader/Sources.pp @@ -1,7 +1,7 @@ #define LOCAL_LIBS express pandabase #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \ dtoolutil:c dtoolbase:c dtool:m -#define USE_PACKAGES zlib net ssl +#define USE_PACKAGES zlib net openssl #begin lib_target #define TARGET downloader diff --git a/panda/src/downloader/bioPtr.cxx b/panda/src/downloader/bioPtr.cxx index e0d5dcbd2a..c03dca9a87 100644 --- a/panda/src/downloader/bioPtr.cxx +++ b/panda/src/downloader/bioPtr.cxx @@ -19,7 +19,7 @@ #include "bioPtr.h" #include "urlSpec.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: BioPtr::Constructor @@ -55,4 +55,4 @@ BioPtr:: } } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/bioPtr.h b/panda/src/downloader/bioPtr.h index 946c3f2521..2f4ed89ff8 100644 --- a/panda/src/downloader/bioPtr.h +++ b/panda/src/downloader/bioPtr.h @@ -22,7 +22,7 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #define OPENSSL_NO_KRB5 #include "referenceCount.h" @@ -63,7 +63,7 @@ private: #include "bioPtr.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/bioStream.cxx b/panda/src/downloader/bioStream.cxx index 8db4b476e0..a1787080d6 100644 --- a/panda/src/downloader/bioStream.cxx +++ b/panda/src/downloader/bioStream.cxx @@ -19,7 +19,7 @@ #include "bioStream.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: IBioStream::is_closed @@ -104,4 +104,4 @@ close() { _buf.close(); } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/bioStream.h b/panda/src/downloader/bioStream.h index d2c1094c5b..1c386856ce 100644 --- a/panda/src/downloader/bioStream.h +++ b/panda/src/downloader/bioStream.h @@ -22,7 +22,7 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "socketStream.h" #include "bioStreamBuf.h" @@ -94,7 +94,7 @@ private: #include "bioStream.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/bioStreamBuf.cxx b/panda/src/downloader/bioStreamBuf.cxx index 1215151f96..21539f1a57 100644 --- a/panda/src/downloader/bioStreamBuf.cxx +++ b/panda/src/downloader/bioStreamBuf.cxx @@ -21,7 +21,7 @@ #include "ssl_utils.h" #include -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #ifndef HAVE_STREAMSIZE // Some compilers (notably SGI) don't define this for us @@ -275,4 +275,4 @@ write_chars(const char *start, size_t length) { return length; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/bioStreamBuf.h b/panda/src/downloader/bioStreamBuf.h index 04090a0235..18317f0eb1 100644 --- a/panda/src/downloader/bioStreamBuf.h +++ b/panda/src/downloader/bioStreamBuf.h @@ -22,7 +22,7 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #define OPENSSL_NO_KRB5 #include "bioPtr.h" @@ -58,6 +58,6 @@ private: friend class BioStream; }; -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/bioStreamPtr.cxx b/panda/src/downloader/bioStreamPtr.cxx index 14f560c720..6b879b896b 100644 --- a/panda/src/downloader/bioStreamPtr.cxx +++ b/panda/src/downloader/bioStreamPtr.cxx @@ -18,7 +18,7 @@ #include "bioStreamPtr.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: BioStreamPtr::Destructor @@ -33,4 +33,4 @@ BioStreamPtr:: } } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/bioStreamPtr.h b/panda/src/downloader/bioStreamPtr.h index 60bff961f1..4365e53d03 100644 --- a/panda/src/downloader/bioStreamPtr.h +++ b/panda/src/downloader/bioStreamPtr.h @@ -22,7 +22,7 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #define OPENSSL_NO_KRB5 #include "bioStream.h" @@ -52,7 +52,7 @@ private: #include "bioStreamPtr.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/chunkedStream.cxx b/panda/src/downloader/chunkedStream.cxx index ea66f2e785..4562877a93 100644 --- a/panda/src/downloader/chunkedStream.cxx +++ b/panda/src/downloader/chunkedStream.cxx @@ -19,7 +19,7 @@ #include "chunkedStream.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: IChunkedStream::is_closed @@ -48,4 +48,4 @@ close() { _buf.close_read(); } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/chunkedStream.h b/panda/src/downloader/chunkedStream.h index 0f1c2b8e45..3a6b9fe2ae 100644 --- a/panda/src/downloader/chunkedStream.h +++ b/panda/src/downloader/chunkedStream.h @@ -22,7 +22,7 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "socketStream.h" #include "chunkedStreamBuf.h" @@ -55,7 +55,7 @@ private: #include "chunkedStream.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/chunkedStreamBuf.cxx b/panda/src/downloader/chunkedStreamBuf.cxx index d45c8b3de2..8b46eeecaf 100644 --- a/panda/src/downloader/chunkedStreamBuf.cxx +++ b/panda/src/downloader/chunkedStreamBuf.cxx @@ -21,7 +21,7 @@ #include // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #ifndef HAVE_STREAMSIZE // Some compilers (notably SGI) don't define this for us @@ -249,4 +249,4 @@ http_getline(string &str) { return false; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/chunkedStreamBuf.h b/panda/src/downloader/chunkedStreamBuf.h index ce8ca9611e..a9ea74da47 100644 --- a/panda/src/downloader/chunkedStreamBuf.h +++ b/panda/src/downloader/chunkedStreamBuf.h @@ -22,7 +22,7 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "httpChannel.h" #include "bioStreamPtr.h" @@ -60,6 +60,6 @@ private: friend class IChunkedStream; }; -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/config_downloader.cxx b/panda/src/downloader/config_downloader.cxx index a129727bcf..e0613a48e6 100644 --- a/panda/src/downloader/config_downloader.cxx +++ b/panda/src/downloader/config_downloader.cxx @@ -167,7 +167,7 @@ init_libdownloader() { } initialized = true; -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL HTTPChannel::init_type(); // We need to define this here, rather than above, to guarantee that @@ -194,5 +194,5 @@ init_libdownloader() { PandaSystem *ps = PandaSystem::get_global_ptr(); ps->add_system("OpenSSL"); -#endif +#endif // HAVE_OPENSSL } diff --git a/panda/src/downloader/httpAuthorization.cxx b/panda/src/downloader/httpAuthorization.cxx index 91344bbec5..0e1d7d9e1d 100644 --- a/panda/src/downloader/httpAuthorization.cxx +++ b/panda/src/downloader/httpAuthorization.cxx @@ -20,7 +20,7 @@ #include "httpChannel.h" #include "urlSpec.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL static const char base64_table[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', @@ -346,4 +346,4 @@ scan_quoted_or_unquoted_string(string &result, const string &source, return start; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/httpAuthorization.h b/panda/src/downloader/httpAuthorization.h index ecc16409a4..e0d7dce136 100644 --- a/panda/src/downloader/httpAuthorization.h +++ b/panda/src/downloader/httpAuthorization.h @@ -25,7 +25,7 @@ // actually use any OpenSSL code, because it is a support module for // HTTPChannel, which *does* use OpenSSL code. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "referenceCount.h" #include "httpEnum.h" @@ -81,7 +81,7 @@ protected: #include "httpAuthorization.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/httpBasicAuthorization.cxx b/panda/src/downloader/httpBasicAuthorization.cxx index 0a14f58904..cbb903144e 100644 --- a/panda/src/downloader/httpBasicAuthorization.cxx +++ b/panda/src/downloader/httpBasicAuthorization.cxx @@ -18,7 +18,7 @@ #include "httpBasicAuthorization.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL const string HTTPBasicAuthorization::_mechanism = "basic"; @@ -68,4 +68,4 @@ generate(HTTPEnum::Method, const string &, return "Basic " + base64_encode(username); } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/httpBasicAuthorization.h b/panda/src/downloader/httpBasicAuthorization.h index 5c0278acbe..42cc66c46e 100644 --- a/panda/src/downloader/httpBasicAuthorization.h +++ b/panda/src/downloader/httpBasicAuthorization.h @@ -25,7 +25,7 @@ // actually use any OpenSSL code, because it is a support module for // HTTPChannel, which *does* use OpenSSL code. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "httpAuthorization.h" @@ -53,7 +53,7 @@ private: #include "httpBasicAuthorization.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/httpChannel.cxx b/panda/src/downloader/httpChannel.cxx index 7feef43f4c..5375b78362 100644 --- a/panda/src/downloader/httpChannel.cxx +++ b/panda/src/downloader/httpChannel.cxx @@ -27,7 +27,7 @@ #include "clockObject.h" #include "ramfile.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include #ifdef WIN32_VC @@ -3498,4 +3498,4 @@ operator << (ostream &out, HTTPChannel::State state) { #endif // NDEBUG } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/httpChannel.h b/panda/src/downloader/httpChannel.h index 3254f4c846..3f508e2bbc 100644 --- a/panda/src/downloader/httpChannel.h +++ b/panda/src/downloader/httpChannel.h @@ -26,7 +26,7 @@ // the OpenSSL library to portably handle all of the socket // communications. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #define OPENSSL_NO_KRB5 #include "httpClient.h" @@ -429,7 +429,7 @@ ostream &operator << (ostream &out, HTTPChannel::State state); #include "httpChannel.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/httpClient.cxx b/panda/src/downloader/httpClient.cxx index 1f1ee00631..518de74f14 100644 --- a/panda/src/downloader/httpClient.cxx +++ b/panda/src/downloader/httpClient.cxx @@ -28,7 +28,7 @@ #include "httpDigestAuthorization.h" #include "globPattern.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include #include @@ -1629,4 +1629,4 @@ ssl_msg_callback(int write_p, int version, int content_type, } #endif // defined(SSL_097) && !defined(NDEBUG) -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/httpClient.h b/panda/src/downloader/httpClient.h index 5dca906d9d..77d9cd06cd 100644 --- a/panda/src/downloader/httpClient.h +++ b/panda/src/downloader/httpClient.h @@ -26,7 +26,7 @@ // the OpenSSL library to portably handle all of the socket // communications. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #define OPENSSL_NO_KRB5 #include "urlSpec.h" @@ -207,7 +207,7 @@ private: #include "httpClient.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/httpCookie.cxx b/panda/src/downloader/httpCookie.cxx index 76e95d0006..f665dce503 100644 --- a/panda/src/downloader/httpCookie.cxx +++ b/panda/src/downloader/httpCookie.cxx @@ -18,7 +18,7 @@ #include "httpCookie.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "ctype.h" #include "httpChannel.h" @@ -218,4 +218,4 @@ parse_cookie_param(const string ¶m, bool first_param) { return true; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/httpCookie.h b/panda/src/downloader/httpCookie.h index f307e273d1..f918d289a1 100644 --- a/panda/src/downloader/httpCookie.h +++ b/panda/src/downloader/httpCookie.h @@ -26,7 +26,7 @@ // the OpenSSL library to portably handle all of the socket // communications. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "httpDate.h" #include "urlSpec.h" @@ -88,6 +88,6 @@ INLINE ostream &operator << (ostream &out, const HTTPCookie &cookie); #include "httpCookie.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/httpDigestAuthorization.cxx b/panda/src/downloader/httpDigestAuthorization.cxx index 0059418298..6492e701fe 100644 --- a/panda/src/downloader/httpDigestAuthorization.cxx +++ b/panda/src/downloader/httpDigestAuthorization.cxx @@ -18,7 +18,7 @@ #include "httpDigestAuthorization.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include #include @@ -371,4 +371,4 @@ operator << (ostream &out, HTTPDigestAuthorization::Qop qop) { return out; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/httpDigestAuthorization.h b/panda/src/downloader/httpDigestAuthorization.h index 23ea480179..ebd96b2a6c 100644 --- a/panda/src/downloader/httpDigestAuthorization.h +++ b/panda/src/downloader/httpDigestAuthorization.h @@ -25,7 +25,7 @@ // actually use any OpenSSL code, because it is a support module for // HTTPChannel, which *does* use OpenSSL code. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "httpAuthorization.h" @@ -96,7 +96,7 @@ ostream &operator << (ostream &out, HTTPDigestAuthorization::Qop qop); #include "httpDigestAuthorization.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/httpEnum.cxx b/panda/src/downloader/httpEnum.cxx index 16c0d11cb3..cdbbed8551 100644 --- a/panda/src/downloader/httpEnum.cxx +++ b/panda/src/downloader/httpEnum.cxx @@ -18,7 +18,7 @@ #include "httpEnum.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: HTTPEnum::Method::output operator @@ -63,4 +63,4 @@ operator << (ostream &out, HTTPEnum::Method method) { return out; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/httpEnum.h b/panda/src/downloader/httpEnum.h index 7930a40eba..9344606534 100644 --- a/panda/src/downloader/httpEnum.h +++ b/panda/src/downloader/httpEnum.h @@ -26,7 +26,7 @@ // the OpenSSL library to portably handle all of the socket // communications. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Class : HTTPEnum @@ -57,7 +57,7 @@ PUBLISHED: ostream &operator << (ostream &out, HTTPEnum::Method method); -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/identityStream.cxx b/panda/src/downloader/identityStream.cxx index bce3af03cd..d8e815b24b 100644 --- a/panda/src/downloader/identityStream.cxx +++ b/panda/src/downloader/identityStream.cxx @@ -19,7 +19,7 @@ #include "identityStream.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: IIdentityStream::is_closed @@ -49,4 +49,4 @@ close() { _buf.close_read(); } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/identityStream.h b/panda/src/downloader/identityStream.h index d0958a324d..4b7544d4e0 100644 --- a/panda/src/downloader/identityStream.h +++ b/panda/src/downloader/identityStream.h @@ -22,7 +22,7 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "socketStream.h" #include "identityStreamBuf.h" @@ -62,7 +62,7 @@ private: #include "identityStream.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/identityStreamBuf.cxx b/panda/src/downloader/identityStreamBuf.cxx index 41aa2a811d..0cb799af21 100644 --- a/panda/src/downloader/identityStreamBuf.cxx +++ b/panda/src/downloader/identityStreamBuf.cxx @@ -19,7 +19,7 @@ #include "identityStreamBuf.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #ifndef HAVE_STREAMSIZE // Some compilers (notably SGI) don't define this for us @@ -180,4 +180,4 @@ read_chars(char *start, size_t length) { return read_count; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/identityStreamBuf.h b/panda/src/downloader/identityStreamBuf.h index 8b146179d5..3353bba942 100644 --- a/panda/src/downloader/identityStreamBuf.h +++ b/panda/src/downloader/identityStreamBuf.h @@ -22,7 +22,7 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "httpChannel.h" #include "bioStreamPtr.h" @@ -58,6 +58,6 @@ private: friend class IIdentityStream; }; -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/patcher.cxx b/panda/src/downloader/patcher.cxx index ba34612954..076e324235 100644 --- a/panda/src/downloader/patcher.cxx +++ b/panda/src/downloader/patcher.cxx @@ -18,7 +18,7 @@ #include "pandabase.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "config_downloader.h" #include "patcher.h" @@ -89,4 +89,4 @@ run() { return _patchfile->run(); } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/patcher.h b/panda/src/downloader/patcher.h index 56d4106a63..417ec28091 100644 --- a/panda/src/downloader/patcher.h +++ b/panda/src/downloader/patcher.h @@ -21,7 +21,7 @@ #include "pandabase.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "filename.h" #include "buffer.h" @@ -50,6 +50,6 @@ private: #include "patcher.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/socketStream.cxx b/panda/src/downloader/socketStream.cxx index 0cc743a447..cabea88a22 100644 --- a/panda/src/downloader/socketStream.cxx +++ b/panda/src/downloader/socketStream.cxx @@ -20,7 +20,7 @@ #include "datagram.h" #include "datagramIterator.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: SSReader::Destructor @@ -209,4 +209,4 @@ send_datagram(const Datagram &dg) { return !is_closed(); } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/socketStream.h b/panda/src/downloader/socketStream.h index 715bb47a69..93d9075a2b 100644 --- a/panda/src/downloader/socketStream.h +++ b/panda/src/downloader/socketStream.h @@ -29,7 +29,7 @@ // available, since the only current use for it is to implement // OpenSSL-defined constructs (like ISocketStream). -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Class : SSReader @@ -168,7 +168,7 @@ PUBLISHED: #include "socketStream.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/ssl_utils.cxx b/panda/src/downloader/ssl_utils.cxx index 6055ea5cca..81c7f29db7 100644 --- a/panda/src/downloader/ssl_utils.cxx +++ b/panda/src/downloader/ssl_utils.cxx @@ -19,7 +19,7 @@ #include "ssl_utils.h" #include "config_downloader.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #ifdef REPORT_OPENSSL_ERRORS #include @@ -53,4 +53,4 @@ void notify_ssl_errors() { #endif // REPORT_OPENSSL_ERRORS } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/downloader/ssl_utils.h b/panda/src/downloader/ssl_utils.h index 897a9bf928..8b28fa0154 100644 --- a/panda/src/downloader/ssl_utils.h +++ b/panda/src/downloader/ssl_utils.h @@ -22,14 +22,14 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #define OPENSSL_NO_KRB5 #include EXPCL_PANDAEXPRESS void notify_ssl_errors(); -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloadertools/Sources.pp b/panda/src/downloadertools/Sources.pp index da526cd912..88d45a2bbf 100644 --- a/panda/src/downloadertools/Sources.pp +++ b/panda/src/downloadertools/Sources.pp @@ -4,7 +4,7 @@ #begin bin_target #define TARGET apply_patch - #define BUILD_TARGET $[HAVE_SSL] + #define BUILD_TARGET $[HAVE_OPENSSL] #define SOURCES \ apply_patch.cxx @@ -15,7 +15,7 @@ #begin bin_target #define TARGET build_patch - #define BUILD_TARGET $[HAVE_SSL] + #define BUILD_TARGET $[HAVE_OPENSSL] #define SOURCES \ build_patch.cxx @@ -24,7 +24,7 @@ #begin bin_target #define TARGET show_ddb - #define BUILD_TARGET $[HAVE_SSL] + #define BUILD_TARGET $[HAVE_OPENSSL] #define SOURCES \ show_ddb.cxx @@ -53,8 +53,8 @@ #begin bin_target #define TARGET check_md5 - #define BUILD_TARGET $[HAVE_SSL] - #define USE_PACKAGES $[USE_PACKAGES] ssl + #define BUILD_TARGET $[HAVE_OPENSSL] + #define USE_PACKAGES $[USE_PACKAGES] openssl #define SOURCES \ check_md5.cxx @@ -91,8 +91,8 @@ #begin bin_target #define TARGET pencrypt - #define BUILD_TARGET $[HAVE_SSL] - #define USE_PACKAGES $[USE_PACKAGES] ssl + #define BUILD_TARGET $[HAVE_OPENSSL] + #define USE_PACKAGES $[USE_PACKAGES] openssl #define SOURCES \ pencrypt.cxx @@ -101,8 +101,8 @@ #begin bin_target #define TARGET pdecrypt - #define BUILD_TARGET $[HAVE_SSL] - #define USE_PACKAGES $[USE_PACKAGES] ssl + #define BUILD_TARGET $[HAVE_OPENSSL] + #define USE_PACKAGES $[USE_PACKAGES] openssl #define SOURCES \ pdecrypt.cxx diff --git a/panda/src/express/Sources.pp b/panda/src/express/Sources.pp index 8f474fd224..35514fc6ae 100644 --- a/panda/src/express/Sources.pp +++ b/panda/src/express/Sources.pp @@ -4,7 +4,7 @@ #begin lib_target #define TARGET express - #define USE_PACKAGES nspr net zlib ssl + #define USE_PACKAGES nspr net zlib openssl #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx diff --git a/panda/src/express/encryptStream.cxx b/panda/src/express/encryptStream.cxx index 87ede4d3e4..8d12080b03 100644 --- a/panda/src/express/encryptStream.cxx +++ b/panda/src/express/encryptStream.cxx @@ -18,7 +18,7 @@ #include "encryptStream.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: encrypt_string // Access: Published @@ -66,4 +66,4 @@ decrypt_string(const string &source, const string &password) { return output.str(); } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/express/encryptStream.h b/panda/src/express/encryptStream.h index 96680a9974..6843593b8e 100644 --- a/panda/src/express/encryptStream.h +++ b/panda/src/express/encryptStream.h @@ -22,7 +22,7 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "encryptStreamBuf.h" @@ -92,7 +92,7 @@ END_PUBLISH #include "encryptStream.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/express/encryptStreamBuf.cxx b/panda/src/express/encryptStreamBuf.cxx index 7a0d080789..8729ecaa15 100644 --- a/panda/src/express/encryptStreamBuf.cxx +++ b/panda/src/express/encryptStreamBuf.cxx @@ -21,7 +21,7 @@ #include "streamReader.h" #include "streamWriter.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include @@ -477,4 +477,4 @@ write_chars(const char *start, size_t length) { } } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/express/encryptStreamBuf.h b/panda/src/express/encryptStreamBuf.h index 1eb8da4a11..747a2ecd37 100644 --- a/panda/src/express/encryptStreamBuf.h +++ b/panda/src/express/encryptStreamBuf.h @@ -22,7 +22,7 @@ #include "pandabase.h" // This module is not compiled if OpenSSL is not available. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include @@ -84,6 +84,6 @@ private: #include "encryptStreamBuf.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/express/hashVal.I b/panda/src/express/hashVal.I index 972cfe7e29..1a97620a57 100644 --- a/panda/src/express/hashVal.I +++ b/panda/src/express/hashVal.I @@ -202,7 +202,7 @@ read_stream(StreamReader &source) { _hv[3] = source.get_uint32(); } -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: HashVal::hash_ramfile // Access: Published @@ -228,7 +228,7 @@ INLINE void HashVal:: hash_string(const string &data) { return hash_buffer(data.data(), data.length()); } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: HashVal::tohex diff --git a/panda/src/express/hashVal.cxx b/panda/src/express/hashVal.cxx index 9d4f3c3355..17ff12499f 100644 --- a/panda/src/express/hashVal.cxx +++ b/panda/src/express/hashVal.cxx @@ -21,9 +21,9 @@ #include -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include -#endif // HAVE_SSL +#endif // HAVE_OPENSSL //////////////////////////////////////////////////////////////////// @@ -164,7 +164,7 @@ set_from_hex(const string &text) { return !strm.fail(); } -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Function: HashVal::hash_file // Access: Published @@ -234,7 +234,7 @@ hash_buffer(const char *buffer, int length) { _hv[3] = (md[12] << 24) | (md[13] << 16) | (md[14] << 8) | (md[15]); } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL //////////////////////////////////////////////////////////////////// diff --git a/panda/src/express/hashVal.h b/panda/src/express/hashVal.h index 0bc22082e8..d60324f9ac 100644 --- a/panda/src/express/hashVal.h +++ b/panda/src/express/hashVal.h @@ -66,12 +66,12 @@ PUBLISHED: INLINE void write_stream(StreamWriter &destination) const; INLINE void read_stream(StreamReader &source); -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL bool hash_file(const Filename &filename); INLINE void hash_ramfile(const Ramfile &ramfile); INLINE void hash_string(const string &data); void hash_buffer(const char *buffer, int length); -#endif // HAVE_SSL +#endif // HAVE_OPENSSL private: static void encode_hex(PN_uint32 val, char *buffer); diff --git a/panda/src/express/multifile.I b/panda/src/express/multifile.I index ca447b4981..f6e7e06b83 100644 --- a/panda/src/express/multifile.I +++ b/panda/src/express/multifile.I @@ -92,13 +92,13 @@ get_scale_factor() const { //////////////////////////////////////////////////////////////////// INLINE void Multifile:: set_encryption_flag(bool flag) { -#ifndef HAVE_SSL +#ifndef HAVE_OPENSSL if (flag) { express_cat.warning() << "OpenSSL not compiled in; cannot generated encrypted multifiles.\n"; flag = false; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL _encryption_flag = flag; } diff --git a/panda/src/express/multifile.cxx b/panda/src/express/multifile.cxx index 0ffa99fa4f..5227cb40a1 100644 --- a/panda/src/express/multifile.cxx +++ b/panda/src/express/multifile.cxx @@ -846,12 +846,12 @@ open_read_subfile(int index) { subfile->_data_start + (streampos)subfile->_data_length); if ((subfile->_flags & SF_encrypted) != 0) { -#ifndef HAVE_SSL +#ifndef HAVE_OPENSSL express_cat.error() << "OpenSSL not compiled in; cannot read encrypted multifiles.\n"; delete stream; return NULL; -#else // HAVE_SSL +#else // HAVE_OPENSSL // The subfile is encrypted. So actually, return an // IDecryptStream that wraps around the ISubStream. IDecryptStream *wrapper = @@ -869,7 +869,7 @@ open_read_subfile(int index) { delete stream; return NULL; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL } if ((subfile->_flags & SF_compressed) != 0) { @@ -1182,11 +1182,11 @@ add_new_subfile(Subfile *subfile, int compression_level) { #endif // HAVE_ZLIB } -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL if (_encryption_flag) { subfile->_flags |= SF_encrypted; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL if (_next_index != (streampos)0) { // If we're adding a Subfile to an already-existing Multifile, we @@ -1566,7 +1566,7 @@ write_data(ostream &write, istream *read, streampos fpos, ostream *putter = &write; bool delete_putter = false; -#ifndef HAVE_SSL +#ifndef HAVE_OPENSSL // Without OpenSSL, we can't support encryption. The flag had // better not be set. nassertr((_flags & SF_encrypted) == 0, fpos); diff --git a/panda/src/express/password_hash.cxx b/panda/src/express/password_hash.cxx index 4f40fa9ae5..2ef0f46d55 100644 --- a/panda/src/express/password_hash.cxx +++ b/panda/src/express/password_hash.cxx @@ -20,7 +20,7 @@ // The functions defined within this file rely on algorithms defined // within OpenSSL. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include @@ -75,5 +75,5 @@ password_hash(const string &password, const string &salt, -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/express/password_hash.h b/panda/src/express/password_hash.h index ecb8f62940..dfa210ee0f 100644 --- a/panda/src/express/password_hash.h +++ b/panda/src/express/password_hash.h @@ -23,7 +23,7 @@ // The functions defined within this file rely on algorithms defined // within OpenSSL. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL BEGIN_PUBLISH @@ -32,6 +32,6 @@ string password_hash(const string &password, const string &salt, END_PUBLISH -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/express/patchfile.cxx b/panda/src/express/patchfile.cxx index cd1e0532b2..05e7049dd5 100644 --- a/panda/src/express/patchfile.cxx +++ b/panda/src/express/patchfile.cxx @@ -18,7 +18,7 @@ #include "pandabase.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "config_express.h" #include "error_utils.h" @@ -981,4 +981,4 @@ build(Filename file_orig, Filename file_new, Filename patch_name) { return true; } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/express/patchfile.h b/panda/src/express/patchfile.h index 550f438ecf..097fdd4e15 100644 --- a/panda/src/express/patchfile.h +++ b/panda/src/express/patchfile.h @@ -20,7 +20,7 @@ #include "pandabase.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL #include "typedef.h" #include "notify.h" @@ -136,6 +136,6 @@ protected: #include "patchfile.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 39766fb4fb..0f8192c05d 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -5700,6 +5700,9 @@ upload_texture_image(CLP(TextureContext) *gtc, } else { // We can reload the image over the previous image, possibly // saving on texture memory fragmentation. +#ifdef DO_PSTATS + _data_transferred_pcollector.add_level(get_external_texture_bytes(width, height, depth, external_format, component_type)); +#endif switch (target) { case GL_TEXTURE_1D: GLP(TexSubImage1D)(target, 0, 0, width, diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index 100c19b8a1..dc1432a574 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -57,7 +57,8 @@ userVertexTransform.I userVertexTransform.h \ vertexBufferContext.I vertexBufferContext.h \ vertexSlider.I vertexSlider.h \ - vertexTransform.I vertexTransform.h + vertexTransform.I vertexTransform.h \ + videoTexture.I videoTexture.h #define INCLUDED_SOURCES \ boundedObject.cxx \ @@ -104,7 +105,8 @@ userVertexTransform.cxx \ vertexBufferContext.cxx \ vertexSlider.cxx \ - vertexTransform.cxx + vertexTransform.cxx \ + videoTexture.cxx #define INSTALL_HEADERS \ boundedObject.I boundedObject.h \ @@ -156,7 +158,8 @@ userVertexTransform.I userVertexTransform.h \ vertexBufferContext.I vertexBufferContext.h \ vertexSlider.I vertexSlider.h \ - vertexTransform.I vertexTransform.h + vertexTransform.I vertexTransform.h \ + videoTexture.I videoTexture.h #define IGATESCAN all diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 3869ee5cbc..eb68af66cc 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -50,6 +50,7 @@ #include "userVertexTransform.h" #include "vertexTransform.h" #include "vertexSlider.h" +#include "videoTexture.h" #include "geomContext.h" #include "vertexBufferContext.h" #include "indexBufferContext.h" @@ -187,14 +188,6 @@ ConfigVariableEnum textures_square "a square aspect ratio when they are loaded from disk. Set this " "to 'none', 'down', or 'up'. See textures-power-2.")); -ConfigVariableString fake_texture_image -("fake-texture-image", "", - PRC_DESC("Set this to enable a speedy-load mode in which you don't care " - "what the world looks like, you just want it to load in minimal " - "time. This causes all texture loads via the TexturePool to use " - "the same texture file, which will presumably only be loaded " - "once.")); - ConfigVariableInt geom_cache_size ("geom-cache-size", 5000, PRC_DESC("Specifies the maximum number of entries in the cache " @@ -264,6 +257,7 @@ ConfigureFn(config_gobj) { UserVertexTransform::init_type(); VertexTransform::init_type(); VertexSlider::init_type(); + VideoTexture::init_type(); InternalName::init_type(); //Registration of writeable object's creation diff --git a/panda/src/gobj/config_gobj.h b/panda/src/gobj/config_gobj.h index 5dd7b19a3f..6cc55bae81 100644 --- a/panda/src/gobj/config_gobj.h +++ b/panda/src/gobj/config_gobj.h @@ -61,7 +61,6 @@ extern EXPCL_PANDA ConfigVariableBool connect_triangle_strips; extern EXPCL_PANDA ConfigVariableEnum bam_texture_mode; extern EXPCL_PANDA ConfigVariableEnum textures_power_2; extern EXPCL_PANDA ConfigVariableEnum textures_square; -extern EXPCL_PANDA ConfigVariableString fake_texture_image; extern EXPCL_PANDA ConfigVariableInt geom_cache_size; extern EXPCL_PANDA ConfigVariableInt geom_cache_min_frames; diff --git a/panda/src/gobj/gobj_composite2.cxx b/panda/src/gobj/gobj_composite2.cxx index b32c06d98a..505bbc84b0 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -26,3 +26,4 @@ #include "vertexBufferContext.cxx" #include "vertexSlider.cxx" #include "vertexTransform.cxx" +#include "videoTexture.cxx" diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 15b722a420..05c607f995 100755 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -91,7 +91,7 @@ parse_upto(string &result, string pattern, bool include) { GlobPattern endpat(pattern); int start = _parse; int last = _parse; - while (_parse < _text.size()) { + while (_parse < (int)_text.size()) { string t; parse_line(t, true, true); if (endpat.matches(t)) break; diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 15e45e0489..747dbbe28a 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -411,36 +411,18 @@ uses_mipmaps() const { } //////////////////////////////////////////////////////////////////// -// Function: Texture::has_ram_image +// Function: Texture::might_have_ram_image // Access: Published -// Description: Returns true if the Texture has its image contents -// available in main RAM, false if it exists only in -// texture memory or in the prepared GSG context. -// -// Note that this has nothing to do with whether -// get_ram_image() will fail or not. Even if -// has_ram_image() returns false, get_ram_image() may -// still return a valid RAM image, because -// get_ram_image() will automatically load the texture -// from disk if necessary. The only thing -// has_ram_image() tells you is whether the texture is -// available right now without hitting the disk first. -// -// Note also that if an application uses only one GSG, -// it may appear that has_ram_image() returns true if -// the texture has not yet been loaded by the GSG, but -// this correlation is not true in general and should -// not be depended on. Specifically, if an application -// ever uses multiple GSG's in its lifetime (for -// instance, by opening more than one window, or by -// closing its window and opening another one later), -// then has_ram_image() may well return false on -// textures that have never been loaded on the current -// GSG. +// Description: Returns true if the texture's image contents are +// currently available in main RAM, or there is reason +// to believe it can be loaded on demand. That is, this +// function returns a "best guess" as to whether +// get_ram_image() will succeed without actually calling +// it first. //////////////////////////////////////////////////////////////////// INLINE bool Texture:: -has_ram_image() const { - return !_image.empty(); +might_have_ram_image() const { + return (has_ram_image() || has_filename()); } //////////////////////////////////////////////////////////////////// @@ -479,21 +461,6 @@ get_expected_ram_page_size() const { return (size_t)(_x_size * _y_size * _num_components * _component_width); } -//////////////////////////////////////////////////////////////////// -// Function: Texture::might_have_ram_image -// Access: Published -// Description: Returns true if the texture's image contents are -// currently available in main RAM, or there is reason -// to believe it can be loaded on demand. That is, this -// function returns a "best guess" as to whether -// get_ram_image() will succeed without actually calling -// it first. -//////////////////////////////////////////////////////////////////// -INLINE bool Texture:: -might_have_ram_image() const { - return (has_ram_image() || has_filename()); -} - //////////////////////////////////////////////////////////////////// // Function: Texture::set_keep_ram_image // Access: Published @@ -514,19 +481,6 @@ set_keep_ram_image(bool keep_ram_image) { _keep_ram_image = keep_ram_image; } -//////////////////////////////////////////////////////////////////// -// Function: Texture::get_keep_ram_image -// Access: Published -// Description: Returns the flag that indicates whether this Texture -// is eligible to have its main RAM copy of the texture -// memory dumped when the texture is prepared for -// rendering. See set_keep_ram_image(). -//////////////////////////////////////////////////////////////////// -INLINE bool Texture:: -get_keep_ram_image() const { - return _keep_ram_image; -} - //////////////////////////////////////////////////////////////////// // Function: Texture::set_filename // Access: Published @@ -700,6 +654,17 @@ set_loaded_from_disk() { _loaded_from_disk = true; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_loaded_from_disk +// Access: Published +// Description: Returns the flag that indicates the texture has been +// loaded from a disk file. See set_loaded_from_disk(). +//////////////////////////////////////////////////////////////////// +INLINE bool Texture:: +get_loaded_from_disk() const { + return _loaded_from_disk; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::get_match_framebuffer_format // Access: Public diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 8509649261..dc37a4ef03 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -71,6 +71,44 @@ Texture(const string &name) : _loaded_from_disk = false; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::Copy Constructor +// Access: Protected +// Description: Use Texture::make_copy() to make a duplicate copy of +// an existing Texture. +//////////////////////////////////////////////////////////////////// +Texture:: +Texture(const Texture ©) : + Namable(copy), + _filename(copy._filename), + _alpha_filename(copy._alpha_filename), + _fullpath(copy._fullpath), + _alpha_fullpath(copy._alpha_fullpath), + _primary_file_num_channels(copy._primary_file_num_channels), + _alpha_file_channel(copy._alpha_file_channel), + _x_size(copy._x_size), + _y_size(copy._y_size), + _z_size(copy._z_size), + _num_components(copy._num_components), + _component_width(copy._component_width), + _texture_type(copy._texture_type), + _format(copy._format), + _component_type(copy._component_type), + _loaded_from_disk(copy._loaded_from_disk), + _wrap_u(copy._wrap_u), + _wrap_v(copy._wrap_v), + _wrap_w(copy._wrap_w), + _minfilter(copy._minfilter), + _magfilter(copy._magfilter), + _anisotropic_degree(copy._anisotropic_degree), + _keep_ram_image(copy._keep_ram_image), + _border_color(copy._border_color), + _match_framebuffer_format(copy._match_framebuffer_format), + _all_dirty_flags(0), + _image(copy._image) +{ +} + //////////////////////////////////////////////////////////////////// // Function: Texture::Destructor // Access: Published, Virtual @@ -81,6 +119,24 @@ Texture:: release_all(); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::make_copy +// Access: Published, Virtual +// Description: Returns a new copy of the same Texture. This copy, +// if applied to geometry, will be copied into texture +// as a separate texture from the original, so it will +// be duplicated in texture memory (and may be +// independently modified if desired). +// +// If the Texture is an AviTexture, the resulting +// duplicate may be animated independently of the +// original. +//////////////////////////////////////////////////////////////////// +PT(Texture) Texture:: +make_copy() { + return new Texture(*this); +} + //////////////////////////////////////////////////////////////////// // Function: Texture::setup_texture // Access: Published @@ -221,7 +277,7 @@ generate_normalization_cube_map(int size) { //////////////////////////////////////////////////////////////////// // Function: Texture::read -// Access: Published +// Access: Published, Virtual // Description: Reads the texture from the indicated filename. If // num_channels is not 0, it specifies the number of // components to downgrade the image to if it is greater @@ -262,7 +318,7 @@ read(const Filename &fullpath, int z, int primary_file_num_channels) { //////////////////////////////////////////////////////////////////// // Function: Texture::read -// Access: Published +// Access: Published, Virtual // Description: Combine a 3-component image with a grayscale image // to get a 4-component image // @@ -477,7 +533,7 @@ write_pages(const HashFilename &fullpath_template) { //////////////////////////////////////////////////////////////////// // Function: Texture::load -// Access: Published +// Access: Published, Virtual // Description: Fills the texture system RAM data from the // already-read PNMImage. // @@ -496,85 +552,21 @@ write_pages(const HashFilename &fullpath_template) { //////////////////////////////////////////////////////////////////// bool Texture:: load(const PNMImage &pnmimage, int z) { - if (z >= _z_size) { - // If we're loading a page past _z_size, treat it as an implicit - // request to enlarge _z_size. However, this is only legal if - // this is, in fact, a 3-d texture (cube maps always have z_size - // 6, and other types have z_size 1). - nassertr(_texture_type == Texture::TT_3d_texture, false); - - _z_size = z + 1; - // Increase the size of the data buffer to make room for the new - // texture level. - size_t new_size = get_expected_ram_image_size(); - if (!_image.is_null() && new_size > _image.size()) { - _image.insert(_image.end(), new_size - _image.size(), 0); - nassertr(_image.size() == new_size, false); - } + if (!reconsider_z_size(z)) { + return false; } - nassertr(z >= 0 && z < _z_size, false); - int num_components = pnmimage.get_num_channels(); ComponentType component_type = T_unsigned_byte; - xelval maxval = pnmimage.get_maxval(); if (maxval > 255) { component_type = T_unsigned_short; } - if (!_loaded_from_disk || num_components != _num_components) { - // Come up with a default format based on the number of channels. - // But only do this the first time the file is loaded, or if the - // number of channels in the image changes on subsequent loads. - - switch (pnmimage.get_color_type()) { - case PNMImage::CT_grayscale: - _format = F_luminance; - break; - - case PNMImage::CT_two_channel: - _format = F_luminance_alpha; - break; - - case PNMImage::CT_color: - _format = F_rgb; - break; - - case PNMImage::CT_four_channel: - _format = F_rgba; - break; - - default: - // Eh? - nassertr(false, false); - _format = F_rgb; - } - } - - if (!_loaded_from_disk) { -#ifndef NDEBUG - if (_texture_type == TT_1d_texture) { - nassertr(pnmimage.get_y_size() == 1, false); - } else if (_texture_type == TT_cube_map) { - nassertr(pnmimage.get_x_size() == pnmimage.get_y_size(), false); - } -#endif - _x_size = pnmimage.get_x_size(); - _y_size = pnmimage.get_y_size(); - _num_components = num_components; - set_component_type(component_type); - - } else { - if (_x_size != pnmimage.get_x_size() || - _y_size != pnmimage.get_y_size() || - _num_components != num_components || - _component_type != component_type) { - gobj_cat.error() - << "Texture properties have changed for texture " << get_name() - << " level " << z << ".\n"; - return false; - } + if (!reconsider_image_properties(pnmimage.get_x_size(), pnmimage.get_y_size(), + pnmimage.get_num_channels(), component_type, + z)) { + return false; } _loaded_from_disk = true; @@ -856,6 +848,39 @@ set_border_color(const Colorf &color) { } } +//////////////////////////////////////////////////////////////////// +// Function: Texture::has_ram_image +// Access: Published, Virtual +// Description: Returns true if the Texture has its image contents +// available in main RAM, false if it exists only in +// texture memory or in the prepared GSG context. +// +// Note that this has nothing to do with whether +// get_ram_image() will fail or not. Even if +// has_ram_image() returns false, get_ram_image() may +// still return a valid RAM image, because +// get_ram_image() will automatically load the texture +// from disk if necessary. The only thing +// has_ram_image() tells you is whether the texture is +// available right now without hitting the disk first. +// +// Note also that if an application uses only one GSG, +// it may appear that has_ram_image() returns true if +// the texture has not yet been loaded by the GSG, but +// this correlation is not true in general and should +// not be depended on. Specifically, if an application +// ever uses multiple GSG's in its lifetime (for +// instance, by opening more than one window, or by +// closing its window and opening another one later), +// then has_ram_image() may well return false on +// textures that have never been loaded on the current +// GSG. +//////////////////////////////////////////////////////////////////// +bool Texture:: +has_ram_image() const { + return !_image.empty(); +} + //////////////////////////////////////////////////////////////////// // Function: Texture::get_ram_image // Access: Published @@ -886,19 +911,8 @@ set_border_color(const Colorf &color) { //////////////////////////////////////////////////////////////////// CPTA_uchar Texture:: get_ram_image() { - if (_loaded_from_disk && !has_ram_image() && has_filename() && - (_texture_type == TT_1d_texture || _texture_type == TT_2d_texture)) { - // Now we have to reload the texture image. - gobj_cat.info() - << "Reloading texture " << get_name() << "\n"; - - make_ram_image(); - if (has_alpha_fullpath()) { - read(get_fullpath(), get_alpha_fullpath(), - 0, _primary_file_num_channels, _alpha_file_channel); - } else { - read(get_fullpath(), 0, _primary_file_num_channels); - } + if (_loaded_from_disk && !has_ram_image() && has_filename()) { + reload_ram_image(); } return _image; @@ -914,7 +928,7 @@ get_ram_image() { //////////////////////////////////////////////////////////////////// PTA_uchar Texture:: modify_ram_image() { - if (!has_ram_image()) { + if (_image.empty()) { make_ram_image(); } @@ -968,6 +982,19 @@ clear_ram_image() { _image.clear(); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_keep_ram_image +// Access: Published, Virtual +// Description: Returns the flag that indicates whether this Texture +// is eligible to have its main RAM copy of the texture +// memory dumped when the texture is prepared for +// rendering. See set_keep_ram_image(). +//////////////////////////////////////////////////////////////////// +bool Texture:: +get_keep_ram_image() const { + return _keep_ram_image; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::prepare // Access: Published @@ -1218,6 +1245,38 @@ mark_dirty(int flags_to_set) { _all_dirty_flags |= flags_to_set; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::has_cull_callback +// Access: Public, Virtual +// Description: Should be overridden by derived classes to return +// true if cull_callback() has been defined. Otherwise, +// returns false to indicate cull_callback() does not +// need to be called for this node during the cull +// traversal. +//////////////////////////////////////////////////////////////////// +bool Texture:: +has_cull_callback() const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::cull_callback +// Access: Public, Virtual +// Description: If has_cull_callback() returns true, this function +// will be called during the cull traversal to perform +// any additional operations that should be performed at +// cull time. +// +// This is called each time the Texture is discovered +// applied to a Geom in the traversal. It should return +// true if the Geom is visible, false if it should be +// omitted. +//////////////////////////////////////////////////////////////////// +bool Texture:: +cull_callback(CullTraverser *, const CullTraverserData &) const { + return true; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::string_wrap_mode // Access: Public @@ -1271,6 +1330,41 @@ string_filter_type(const string &string) { } } +//////////////////////////////////////////////////////////////////// +// Function: Texture::reconsider_dirty +// Access: Protected, Virtual +// Description: Called by TextureContext to give the Texture a chance +// to mark itself dirty before rendering, if necessary. +//////////////////////////////////////////////////////////////////// +void Texture:: +reconsider_dirty() { +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::reload_ram_image +// Access: Protected, Virtual +// Description: Called when the Texture image is required but the ram +// image is not available, this will reload it from disk +// or otherwise do whatever is required to make it +// available, if possible. +//////////////////////////////////////////////////////////////////// +void Texture:: +reload_ram_image() { + if (_texture_type == TT_1d_texture || _texture_type == TT_2d_texture) { + gobj_cat.info() + << "Reloading texture " << get_name() << "\n"; + + make_ram_image(); + if (has_alpha_fullpath()) { + read(get_fullpath(), get_alpha_fullpath(), + 0, _primary_file_num_channels, _alpha_file_channel); + } else { + read(get_fullpath(), 0, _primary_file_num_channels); + } + } +} + + //////////////////////////////////////////////////////////////////// // Function: Texture::up_to_power_2 // Access: Protected, Static @@ -1301,6 +1395,102 @@ down_to_power_2(int value) { return x; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::reconsider_z_size +// Access: Protected +// Description: Considers whether the z_size should automatically be +// adjusted when the user loads a new page. Returns +// true if the z size is valid, false otherwise. +//////////////////////////////////////////////////////////////////// +bool Texture:: +reconsider_z_size(int z) { + if (z >= _z_size) { + // If we're loading a page past _z_size, treat it as an implicit + // request to enlarge _z_size. However, this is only legal if + // this is, in fact, a 3-d texture (cube maps always have z_size + // 6, and other types have z_size 1). + nassertr(_texture_type == Texture::TT_3d_texture, false); + + _z_size = z + 1; + // Increase the size of the data buffer to make room for the new + // texture level. + size_t new_size = get_expected_ram_image_size(); + if (!_image.is_null() && new_size > _image.size()) { + _image.insert(_image.end(), new_size - _image.size(), 0); + nassertr(_image.size() == new_size, false); + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: Texture::reconsider_image_properties +// Access: Protected +// Description: Resets the internal Texture properties when a new +// image file is loaded. Returns true if the new image +// is valid, false otherwise. +//////////////////////////////////////////////////////////////////// +bool Texture:: +reconsider_image_properties(int x_size, int y_size, int num_components, + Texture::ComponentType component_type, int z) { + if (!_loaded_from_disk || num_components != _num_components) { + // Come up with a default format based on the number of channels. + // But only do this the first time the file is loaded, or if the + // number of channels in the image changes on subsequent loads. + + switch (num_components) { + case 1: + _format = F_luminance; + break; + + case 2: + _format = F_luminance_alpha; + break; + + case 3: + _format = F_rgb; + break; + + case 4: + _format = F_rgba; + break; + + default: + // Eh? + nassertr(false, false); + _format = F_rgb; + } + } + + if (!_loaded_from_disk) { +#ifndef NDEBUG + if (_texture_type == TT_1d_texture) { + nassertr(y_size == 1, false); + } else if (_texture_type == TT_cube_map) { + nassertr(x_size == y_size, false); + } +#endif + _x_size = x_size; + _y_size = y_size; + _num_components = num_components; + set_component_type(component_type); + + } else { + if (_x_size != x_size || + _y_size != y_size || + _num_components != num_components || + _component_type != component_type) { + gobj_cat.error() + << "Texture properties have changed for texture " << get_name() + << " level " << z << ".\n"; + return false; + } + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::clear_prepared // Access: Private @@ -1323,6 +1513,7 @@ clear_prepared(PreparedGraphicsObjects *prepared_objects) { } } + //////////////////////////////////////////////////////////////////// // Function: Texture::consider_rescale // Access: Private @@ -1444,7 +1635,7 @@ make_Texture(const FactoryParams ¶ms) { if (has_rawdata) { // If the raw image data is included, then just create a Texture // and don't load from the file. - me = new Texture; + me = new Texture(""); } else { if (filename.empty()) { @@ -1473,7 +1664,7 @@ make_Texture(const FactoryParams ¶ms) { // Oops, we couldn't load the texture; we'll just return NULL. // But we do need a dummy texture to read in and ignore all of the // attributes. - PT(Texture) dummy = new Texture; + PT(Texture) dummy = new Texture(""); dummy->fillin(scan, manager, has_rawdata); } else { diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index cc2919bd31..2100217a10 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -32,6 +32,8 @@ class TextureContext; class FactoryParams; class PreparedGraphicsObjects; class HashFilename; +class CullTraverser; +class CullTraverserData; //////////////////////////////////////////////////////////////////// // Class : Texture @@ -133,8 +135,13 @@ PUBLISHED: PUBLISHED: Texture(const string &name = string()); +protected: + Texture(const Texture ©); +PUBLISHED: virtual ~Texture(); + virtual PT(Texture) make_copy(); + void setup_texture(TextureType texture_type, int x_size, int y_size, int z_size, ComponentType component_type, Format format); @@ -154,17 +161,17 @@ PUBLISHED: void generate_normalization_cube_map(int size); - bool read(const Filename &fullpath, int z = 0, - int primary_file_num_channels = 0); - bool read(const Filename &fullpath, const Filename &alpha_fullpath, - int z = 0, - int primary_file_num_channels = 0, int alpha_file_channel = 0); + virtual bool read(const Filename &fullpath, int z = 0, + int primary_file_num_channels = 0); + virtual bool read(const Filename &fullpath, const Filename &alpha_fullpath, + int z = 0, + int primary_file_num_channels = 0, int alpha_file_channel = 0); bool write(const Filename &fullpath, int z = 0) const; bool read_pages(const HashFilename &fullpath_template, int z_size = 0); bool write_pages(const HashFilename &fullpath_template); - bool load(const PNMImage &pnmimage, int z = 0); + virtual bool load(const PNMImage &pnmimage, int z = 0); bool store(PNMImage &pnmimage, int z = 0) const; INLINE bool has_filename() const; @@ -203,7 +210,7 @@ PUBLISHED: INLINE Colorf get_border_color() const; INLINE bool uses_mipmaps() const; - INLINE bool has_ram_image() const; + virtual bool has_ram_image() const; INLINE bool might_have_ram_image() const; INLINE size_t get_ram_image_size() const; INLINE size_t get_expected_ram_image_size() const; @@ -214,7 +221,7 @@ PUBLISHED: void set_ram_image(PTA_uchar image); void clear_ram_image(); INLINE void set_keep_ram_image(bool keep_ram_image); - INLINE bool get_keep_ram_image() const; + virtual bool get_keep_ram_image() const; void prepare(PreparedGraphicsObjects *prepared_objects); bool release(PreparedGraphicsObjects *prepared_objects); @@ -240,6 +247,7 @@ PUBLISHED: void set_format(Format format); void set_component_type(ComponentType component_type); INLINE void set_loaded_from_disk(); + INLINE bool get_loaded_from_disk() const; public: INLINE bool get_match_framebuffer_format() const; @@ -263,16 +271,25 @@ public: void mark_dirty(int flags_to_set); + virtual bool has_cull_callback() const; + virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const; + static WrapMode string_wrap_mode(const string &string); static FilterType string_filter_type(const string &string); protected: + virtual void reconsider_dirty(); + virtual void reload_ram_image(); + static int up_to_power_2(int value); static int down_to_power_2(int value); + bool reconsider_z_size(int z); + bool reconsider_image_properties(int x_size, int y_size, int num_components, + ComponentType component_type, int z); private: void clear_prepared(PreparedGraphicsObjects *prepared_objects); - + void consider_rescale(PNMImage &pnmimage); void consider_downgrade(PNMImage &pnmimage, int num_channels); @@ -283,7 +300,7 @@ private: INLINE double get_unsigned_byte(int &index) const; INLINE double get_unsigned_short(int &index) const; -private: +protected: Filename _filename; Filename _alpha_filename; Filename _fullpath; diff --git a/panda/src/gobj/textureContext.I b/panda/src/gobj/textureContext.I index 9d6eafd91f..3908e60b54 100644 --- a/panda/src/gobj/textureContext.I +++ b/panda/src/gobj/textureContext.I @@ -86,6 +86,7 @@ clear_dirty_flags(int flags_to_clear) { //////////////////////////////////////////////////////////////////// INLINE int TextureContext:: get_dirty_flags() const { + _texture->reconsider_dirty(); return _dirty_flags; } diff --git a/panda/src/gobj/texturePool.I b/panda/src/gobj/texturePool.I index 7c61f09209..933f5e9b3a 100644 --- a/panda/src/gobj/texturePool.I +++ b/panda/src/gobj/texturePool.I @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////// INLINE bool TexturePool:: has_texture(const string &filename) { - return get_ptr()->ns_has_texture(filename); + return get_global_ptr()->ns_has_texture(filename); } //////////////////////////////////////////////////////////////////// @@ -54,7 +54,7 @@ verify_texture(const string &filename) { //////////////////////////////////////////////////////////////////// INLINE Texture *TexturePool:: load_texture(const string &filename, int primary_file_num_channels) { - return get_ptr()->ns_load_texture(filename, primary_file_num_channels); + return get_global_ptr()->ns_load_texture(filename, primary_file_num_channels); } //////////////////////////////////////////////////////////////////// @@ -69,7 +69,7 @@ load_texture(const string &filename, int primary_file_num_channels) { INLINE Texture *TexturePool:: load_texture(const string &filename, const string &alpha_filename, int primary_file_num_channels, int alpha_file_channel) { - return get_ptr()->ns_load_texture(filename, alpha_filename, + return get_global_ptr()->ns_load_texture(filename, alpha_filename, primary_file_num_channels, alpha_file_channel); } @@ -85,7 +85,7 @@ load_texture(const string &filename, const string &alpha_filename, //////////////////////////////////////////////////////////////////// INLINE Texture *TexturePool:: load_3d_texture(const string &filename_template) { - return get_ptr()->ns_load_3d_texture(filename_template); + return get_global_ptr()->ns_load_3d_texture(filename_template); } //////////////////////////////////////////////////////////////////// @@ -99,7 +99,7 @@ load_3d_texture(const string &filename_template) { //////////////////////////////////////////////////////////////////// INLINE Texture *TexturePool:: load_cube_map(const string &filename_template) { - return get_ptr()->ns_load_cube_map(filename_template); + return get_global_ptr()->ns_load_cube_map(filename_template); } //////////////////////////////////////////////////////////////////// @@ -115,7 +115,7 @@ load_cube_map(const string &filename_template) { //////////////////////////////////////////////////////////////////// INLINE Texture *TexturePool:: get_normalization_cube_map(int size) { - return get_ptr()->ns_get_normalization_cube_map(size); + return get_global_ptr()->ns_get_normalization_cube_map(size); } //////////////////////////////////////////////////////////////////// @@ -129,7 +129,7 @@ get_normalization_cube_map(int size) { //////////////////////////////////////////////////////////////////// INLINE void TexturePool:: add_texture(Texture *texture) { - get_ptr()->ns_add_texture(texture); + get_global_ptr()->ns_add_texture(texture); } //////////////////////////////////////////////////////////////////// @@ -147,7 +147,7 @@ add_texture(Texture *texture) { //////////////////////////////////////////////////////////////////// INLINE void TexturePool:: release_texture(Texture *texture) { - get_ptr()->ns_release_texture(texture); + get_global_ptr()->ns_release_texture(texture); } //////////////////////////////////////////////////////////////////// @@ -158,7 +158,7 @@ release_texture(Texture *texture) { //////////////////////////////////////////////////////////////////// INLINE void TexturePool:: release_all_textures() { - get_ptr()->ns_release_all_textures(); + get_global_ptr()->ns_release_all_textures(); } //////////////////////////////////////////////////////////////////// @@ -171,7 +171,7 @@ release_all_textures() { //////////////////////////////////////////////////////////////////// INLINE int TexturePool:: garbage_collect() { - return get_ptr()->ns_garbage_collect(); + return get_global_ptr()->ns_garbage_collect(); } //////////////////////////////////////////////////////////////////// @@ -182,7 +182,7 @@ garbage_collect() { //////////////////////////////////////////////////////////////////// INLINE void TexturePool:: list_contents(ostream &out) { - get_ptr()->ns_list_contents(out); + get_global_ptr()->ns_list_contents(out); } //////////////////////////////////////////////////////////////////// @@ -193,7 +193,7 @@ list_contents(ostream &out) { //////////////////////////////////////////////////////////////////// INLINE void TexturePool:: set_fake_texture_image(const string &filename) { - get_ptr()->_fake_texture_image = filename; + get_global_ptr()->_fake_texture_image = filename; } //////////////////////////////////////////////////////////////////// @@ -226,17 +226,5 @@ has_fake_texture_image() { //////////////////////////////////////////////////////////////////// INLINE const string &TexturePool:: get_fake_texture_image() { - return get_ptr()->_fake_texture_image; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePool::Constructor -// Access: Private -// Description: The constructor is not intended to be called -// directly; there's only supposed to be one TexturePool -// in the universe and it constructs itself. -//////////////////////////////////////////////////////////////////// -INLINE TexturePool:: -TexturePool() { - _fake_texture_image = fake_texture_image; + return get_global_ptr()->_fake_texture_image; } diff --git a/panda/src/gobj/texturePool.cxx b/panda/src/gobj/texturePool.cxx index 7086462881..fea00b29f5 100644 --- a/panda/src/gobj/texturePool.cxx +++ b/panda/src/gobj/texturePool.cxx @@ -20,6 +20,7 @@ #include "config_gobj.h" #include "config_util.h" #include "config_express.h" +#include "string_utils.h" #include "virtualFileSystem.h" @@ -35,7 +36,79 @@ TexturePool *TexturePool::_global_ptr = (TexturePool *)NULL; //////////////////////////////////////////////////////////////////// void TexturePool:: write(ostream &out) { - get_ptr()->ns_list_contents(out); + get_global_ptr()->ns_list_contents(out); +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::register_texture_type +// Access: Public +// Description: Records a factory function that makes a Texture +// object of the appropriate type for one or more +// particular filename extensions. The string +// extensions may be a string that contains +// space-separated list of extensions, case-insensitive. +//////////////////////////////////////////////////////////////////// +void TexturePool:: +register_texture_type(MakeTextureFunc *func, const string &extensions) { + vector_string words; + extract_words(downcase(extensions), words); + + vector_string::const_iterator wi; + for (wi = words.begin(); wi != words.end(); ++wi) { + _type_registry[*wi] = func; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::make_texture +// Access: Public +// Description: Creates a new Texture object of the appropriate type +// for the indicated filename extension, according to +// the types that have been registered via +// register_texture_type(). +//////////////////////////////////////////////////////////////////// +PT(Texture) TexturePool:: +make_texture(const string &extension) { + string c = downcase(extension); + TypeRegistry::const_iterator ti; + ti = _type_registry.find(extension); + if (ti != _type_registry.end()) { + return (*ti).second(); + } + return new Texture; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::get_global_ptr +// Access: Public, Static +// Description: Initializes and/or returns the global pointer to the +// one TexturePool object in the system. +//////////////////////////////////////////////////////////////////// +TexturePool *TexturePool:: +get_global_ptr() { + if (_global_ptr == (TexturePool *)NULL) { + _global_ptr = new TexturePool; + } + return _global_ptr; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::Constructor +// Access: Private +// Description: The constructor is not intended to be called +// directly; there's only supposed to be one TexturePool +// in the universe and it constructs itself. +//////////////////////////////////////////////////////////////////// +TexturePool:: +TexturePool() { + ConfigVariableString fake_texture_image + ("fake-texture-image", "", + PRC_DESC("Set this to enable a speedy-load mode in which you don't care " + "what the world looks like, you just want it to load in minimal " + "time. This causes all texture loads via the TexturePool to use " + "the same texture file, which will presumably only be loaded " + "once.")); + _fake_texture_image = fake_texture_image; } //////////////////////////////////////////////////////////////////// @@ -91,7 +164,7 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels) { gobj_cat.info() << "Loading texture " << filename << "\n"; - PT(Texture) tex = new Texture; + PT(Texture) tex = make_texture(filename.get_extension()); if (!tex->read(filename, 0, primary_file_num_channels)) { // This texture was not found or could not be read. report_texture_unreadable(filename); @@ -139,7 +212,7 @@ ns_load_texture(const Filename &orig_filename, gobj_cat.info() << "Loading texture " << filename << " and alpha component " << alpha_filename << endl; - PT(Texture) tex = new Texture; + PT(Texture) tex = make_texture(filename.get_extension()); if (!tex->read(filename, alpha_filename, 0, primary_file_num_channels, alpha_file_channel)) { // This texture was not found or could not be read. @@ -186,7 +259,7 @@ ns_load_3d_texture(const HashFilename &filename_template) { gobj_cat.info() << "Loading 3-d texture " << hash_filename << "\n"; - PT(Texture) tex = new Texture; + PT(Texture) tex = make_texture(hash_filename.get_extension()); tex->setup_3d_texture(); if (!tex->read_pages(hash_filename)) { // This texture was not found or could not be read. @@ -231,7 +304,7 @@ ns_load_cube_map(const HashFilename &filename_template) { gobj_cat.info() << "Loading cube map texture " << hash_filename << "\n"; - PT(Texture) tex = new Texture; + PT(Texture) tex = make_texture(hash_filename.get_extension()); tex->setup_cube_map(); if (!tex->read_pages(hash_filename)) { // This texture was not found or could not be read. @@ -392,17 +465,3 @@ report_texture_unreadable(const Filename &filename) const { << "Texture \"" << filename << "\" exists but cannot be read.\n"; } } - -//////////////////////////////////////////////////////////////////// -// Function: TexturePool::get_ptr -// Access: Private, Static -// Description: Initializes and/or returns the global pointer to the -// one TexturePool object in the system. -//////////////////////////////////////////////////////////////////// -TexturePool *TexturePool:: -get_ptr() { - if (_global_ptr == (TexturePool *)NULL) { - _global_ptr = new TexturePool; - } - return _global_ptr; -} diff --git a/panda/src/gobj/texturePool.h b/panda/src/gobj/texturePool.h index f8285cb57f..659533156d 100644 --- a/panda/src/gobj/texturePool.h +++ b/panda/src/gobj/texturePool.h @@ -68,8 +68,16 @@ PUBLISHED: static void write(ostream &out); +public: + typedef PT(Texture) MakeTextureFunc(); + void register_texture_type(MakeTextureFunc *func, const string &extensions); + + PT(Texture) make_texture(const string &extension); + + static TexturePool *get_global_ptr(); + private: - INLINE TexturePool(); + TexturePool(); bool ns_has_texture(const Filename &orig_filename); Texture *ns_load_texture(const Filename &orig_filename, int primary_file_num_channels); @@ -89,14 +97,15 @@ private: void report_texture_unreadable(const Filename &filename) const; - static TexturePool *get_ptr(); - static TexturePool *_global_ptr; typedef phash_map Textures; Textures _textures; string _fake_texture_image; PT(Texture) _normalization_cube_map; + + typedef pmap TypeRegistry; + TypeRegistry _type_registry; }; #include "texturePool.I" diff --git a/panda/src/gobj/videoTexture.I b/panda/src/gobj/videoTexture.I new file mode 100644 index 0000000000..94e9e5e260 --- /dev/null +++ b/panda/src/gobj/videoTexture.I @@ -0,0 +1,149 @@ +// Filename: videoTexture.I +// Created by: drose (21Sep05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::set_power_2 +// Access: Published +// Description: Sets the flag that indicates whether a newly-loaded +// VideoTexture will be constrained to dimensions that are +// a power of 2 or not. If true, then a newly-loaded +// video stream will be set within the smallest power of +// 2 texture that will fit it; if false, a newly-loaded +// video stream will be set within a texture that +// exactly fits it, even if that means creating a +// texture whose dimensions are not a power of 2. +// +// This must be set before the first call to read(). +// The default value is false if the Config.prc variable +// textures-power-2 is "none", true otherwise. +//////////////////////////////////////////////////////////////////// +INLINE void VideoTexture:: +set_power_2(bool power_2) { + _power_2 = power_2; +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::get_power_2 +// Access: Published +// Description: Returns the flag that indicates whether a +// newly-loaded VideoTexture will be constrained to +// dimensions that are a power of 2 or not. See +// set_power_2(). +//////////////////////////////////////////////////////////////////// +INLINE bool VideoTexture:: +get_power_2() const { + return _power_2; +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::get_video_width +// Access: Published +// Description: Returns the width in texels of the source video +// stream. This is not necessarily the width of the +// actual texture, since the texture may have been +// expanded to raise it to a power of 2. +//////////////////////////////////////////////////////////////////// +INLINE int VideoTexture:: +get_video_width() const { + return _video_width; +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::get_video_height +// Access: Published +// Description: Returns the height in texels of the source video +// stream. This is not necessarily the height of the +// actual texture, since the texture may have been +// expanded to raise it to a power of 2. +//////////////////////////////////////////////////////////////////// +INLINE int VideoTexture:: +get_video_height() const { + return _video_height; +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::get_tex_scale +// Access: Published +// Description: Returns a scale pair that is suitable for applying to +// geometry via NodePath::set_tex_scale(), which will +// convert texture coordinates on the geometry from the +// range 0..1 into the appropriate range to render the +// video part of the texture. +// +// This is necessary in the event the video source is +// not a power of two and set_power_2() is true. In +// this case, the video image will be mapped to the +// lower-left corner of the texture, and the rest of the +// texture space will be unused; so we will need to +// remap any texture coordinates to fill the space +// correctly. +//////////////////////////////////////////////////////////////////// +INLINE LVecBase2f VideoTexture:: +get_tex_scale() const { + if (_video_width == 0 || _video_height == 0 || + _x_size == 0 || _y_size == 0) { + LVecBase2f(1.0f, 1.0f); + } + return LVecBase2f((float)_video_width / _x_size, + (float)_video_height / _y_size); +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::set_video_size +// Access: Protected +// Description: Should be called by a derived class to set the size +// of the video when it is loaded. +//////////////////////////////////////////////////////////////////// +INLINE void VideoTexture:: +set_video_size(int video_width, int video_height) { + _video_width = video_width; + _video_height = video_height; +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::consider_update +// Access: Protected +// Description: Calls update_frame() if the current frame has +// changed. +//////////////////////////////////////////////////////////////////// +INLINE void VideoTexture:: +consider_update() { + int this_frame = ClockObject::get_global_clock()->get_frame_count(); + if (this_frame != _last_frame_update) { + int frame = get_frame(); + if (_current_frame != frame) { + update_frame(frame); + _current_frame = frame; + } + _last_frame_update = this_frame; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::clear_current_frame +// Access: Protected +// Description: Resets the record of the current frame so that it +// will be forced to reload the next time it is +// requested. +//////////////////////////////////////////////////////////////////// +INLINE void VideoTexture:: +clear_current_frame() { + _last_frame_update = 0; + _current_frame = -1; +} diff --git a/panda/src/gobj/videoTexture.cxx b/panda/src/gobj/videoTexture.cxx new file mode 100644 index 0000000000..4cbc015ee9 --- /dev/null +++ b/panda/src/gobj/videoTexture.cxx @@ -0,0 +1,152 @@ +// Filename: videoTexture.cxx +// Created by: drose (21Sep05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "pandabase.h" + +#include "videoTexture.h" +#include "clockObject.h" +#include "config_gobj.h" + +TypeHandle VideoTexture::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +VideoTexture:: +VideoTexture(const string &name) : + Texture(name) +{ + _power_2 = (textures_power_2 != ATS_none); + _video_width = 0; + _video_height = 0; + + _last_frame_update = 0; + _current_frame = -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::Copy Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +VideoTexture:: +VideoTexture(const VideoTexture ©) : + Texture(copy), + AnimInterface(copy), + _power_2(copy._power_2), + _video_width(copy._video_width), + _video_height(copy._video_height), + _last_frame_update(copy._last_frame_update), + _current_frame(copy._current_frame) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::has_ram_image +// Access: Published, Virtual +// Description: Returns true if the Texture has its image contents +// available in main RAM, false if it exists only in +// texture memory or in the prepared GSG context. +//////////////////////////////////////////////////////////////////// +bool VideoTexture:: +has_ram_image() const { + int this_frame = ClockObject::get_global_clock()->get_frame_count(); + if (this_frame != _last_frame_update) { + return false; + } + return !_image.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::get_keep_ram_image +// Access: Published, Virtual +// Description: Returns the flag that indicates whether this Texture +// is eligible to have its main RAM copy of the texture +// memory dumped when the texture is prepared for +// rendering. See set_keep_ram_image(). +//////////////////////////////////////////////////////////////////// +bool VideoTexture:: +get_keep_ram_image() const { + // An VideoTexture should never dump its RAM image. + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::has_cull_callback +// Access: Public, Virtual +// Description: Should be overridden by derived classes to return +// true if cull_callback() has been defined. Otherwise, +// returns false to indicate cull_callback() does not +// need to be called for this node during the cull +// traversal. +//////////////////////////////////////////////////////////////////// +bool VideoTexture:: +has_cull_callback() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::cull_callback +// Access: Public, Virtual +// Description: If has_cull_callback() returns true, this function +// will be called during the cull traversal to perform +// any additional operations that should be performed at +// cull time. +// +// This is called each time the Texture is discovered +// applied to a Geom in the traversal. It should return +// true if the Geom is visible, false if it should be +// omitted. +//////////////////////////////////////////////////////////////////// +bool VideoTexture:: +cull_callback(CullTraverser *, const CullTraverserData &) const { + // Strictly speaking, the cull_callback() method isn't necessary for + // VideoTexture, since the get_ram_image() function is already + // overloaded to update itself if necessary. However, we define it + // anyway, to move the update calculation into the cull traversal + // rather than the draw traversal. + ((VideoTexture *)this)->reconsider_dirty(); + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::reconsider_dirty +// Access: Protected, Virtual +// Description: Called by TextureContext to give the Texture a chance +// to mark itself dirty before rendering, if necessary. +//////////////////////////////////////////////////////////////////// +void VideoTexture:: +reconsider_dirty() { + consider_update(); +} + +//////////////////////////////////////////////////////////////////// +// Function: VideoTexture::reload_ram_image +// Access: Protected, Virtual +// Description: Called when the Texture image is required but the ram +// image is not available, this will reload it from disk +// or otherwise do whatever is required to make it +// available, if possible. +//////////////////////////////////////////////////////////////////// +void VideoTexture:: +reload_ram_image() { + consider_update(); +} + diff --git a/panda/src/gobj/videoTexture.h b/panda/src/gobj/videoTexture.h new file mode 100644 index 0000000000..e101e9c50b --- /dev/null +++ b/panda/src/gobj/videoTexture.h @@ -0,0 +1,93 @@ +// Filename: videoTexture.h +// Created by: drose (21Sep05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef VIDEOTEXTURE_H +#define VIDEOTEXTURE_H + +#include "pandabase.h" +#include "texture.h" +#include "animInterface.h" + +//////////////////////////////////////////////////////////////////// +// Class : VideoTexture +// Description : The base class for a family of animated Textures that +// take their input from a video source, such as a movie +// file. These Textures may be stopped, started, +// etc. using the AnimInterface controls, similar to an +// animated character. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA VideoTexture : public Texture, public AnimInterface { +protected: + VideoTexture(const string &name); + VideoTexture(const VideoTexture ©); + +PUBLISHED: + INLINE void set_power_2(bool power_2); + INLINE bool get_power_2() const; + + virtual bool has_ram_image() const; + virtual bool get_keep_ram_image() const; + + INLINE int get_video_width() const; + INLINE int get_video_height() const; + INLINE LVecBase2f get_tex_scale() const; + +public: + virtual bool has_cull_callback() const; + virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const; + +protected: + INLINE void set_video_size(int video_width, int video_height); + + virtual void reconsider_dirty(); + virtual void reload_ram_image(); + + INLINE void consider_update(); + INLINE void clear_current_frame(); + virtual void update_frame(int frame)=0; + +private: + bool _power_2; + int _video_width; + int _video_height; + int _last_frame_update; + int _current_frame; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + Texture::init_type(); + AnimInterface::init_type(); + register_type(_type_handle, "VideoTexture", + Texture::get_class_type(), + AnimInterface::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 "videoTexture.I" + +#endif diff --git a/panda/src/grutil/Sources.pp b/panda/src/grutil/Sources.pp index 986e54874d..0d57ed2a8d 100644 --- a/panda/src/grutil/Sources.pp +++ b/panda/src/grutil/Sources.pp @@ -1,7 +1,7 @@ #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \ dtoolutil:c dtoolbase:c dtool:m -#define USE_PACKAGES cv +#define USE_PACKAGES opencv #begin lib_target #define TARGET grutil @@ -16,13 +16,13 @@ frameRateMeter.I frameRateMeter.h \ lineSegs.I lineSegs.h \ multitexReducer.I multitexReducer.h multitexReducer.cxx \ - aviTexture.h aviTexture.I + openCVTexture.h openCVTexture.I #define INCLUDED_SOURCES \ cardMaker.cxx \ config_grutil.cxx \ frameRateMeter.cxx \ - aviTexture.cxx \ + openCVTexture.cxx \ lineSegs.cxx @@ -31,7 +31,7 @@ frameRateMeter.I frameRateMeter.h \ lineSegs.I lineSegs.h \ multitexReducer.I multitexReducer.h \ - aviTexture.I aviTexture.h + openCVTexture.I openCVTexture.h #define IGATESCAN all diff --git a/panda/src/grutil/aviTexture.I b/panda/src/grutil/aviTexture.I deleted file mode 100755 index 81acf3e6f4..0000000000 --- a/panda/src/grutil/aviTexture.I +++ /dev/null @@ -1,134 +0,0 @@ -// Filename: aviTexture.I -// Created by: zacpavlov (19Aug05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::obtain_ram -// Access: Private -// Description: Grabs a fresh ram buffer to mess with -// -//////////////////////////////////////////////////////////////////// -INLINE bool AviTexture:: -obtain_ram() { - _buf = modify_ram_image(); - - if (_buf) { - return true; - } - return false; -} - - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::get_time -// Access: Published -// Description: returns the ratio between 0 and 1 that the movie is -// positioned at. Disabled for camera input -// -//////////////////////////////////////////////////////////////////// -INLINE float AviTexture:: -get_time() { - if (!_isCamera) { - return _time; - } - return 0.0f; -} - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::set_time -// Access: Published -// Description: sets the time on the opencv video reader. Disabled -// for camera input -// -//////////////////////////////////////////////////////////////////// -INLINE void AviTexture:: -set_time(float t) { - if (_isCamera) { - return; - } - if (t >= 0 && t <= 1) { - _time=t; - } - if (_capture) { - cvSetCaptureProperty(_capture,CV_CAP_PROP_POS_AVI_RATIO,t); - _current_frame = cvGetCaptureProperty(_capture,CV_CAP_PROP_POS_FRAMES); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::set_fps -// Access: Published -// Description: sets the fps for the movie, and affects frame receives -// from camera. Note, since frame update is controlled -// by python, this item is sort of arbitrary -//////////////////////////////////////////////////////////////////// -INLINE void AviTexture:: -set_fps(float fps) { - if (fps >= 0) { - _fps = fps; - } else { - return; - } - if (_isCamera && _capture) { - cvSetCaptureProperty(_capture,CV_CAP_PROP_FPS,int(fps)); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::get_fps -// Access: Published -// Description: returns the fps as recieved from movie -//////////////////////////////////////////////////////////////////// -INLINE float AviTexture:: -get_fps() { - return _fps; -} - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::get_total_frames -// Access: Published -// Description: returns the total amount of frames -//////////////////////////////////////////////////////////////////// -INLINE int AviTexture:: -get_total_frames() { - return _total_frames; -} - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::get_current_frame -// Access: Published -// Description: returns current frame (base 0) -//////////////////////////////////////////////////////////////////// -INLINE int AviTexture:: -get_current_frame() { - return _current_frame; -} - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::set_current_frame -// Access: Published -// Description: sets the current frame (base 0) -//////////////////////////////////////////////////////////////////// -INLINE void AviTexture:: -set_current_frame(int frame) { - if (frame>=0 && frame<_total_frames) { - _current_frame = frame; - cvSetCaptureProperty(_capture,CV_CAP_PROP_POS_FRAMES,_current_frame); - _time = cvGetCaptureProperty(_capture,CV_CAP_PROP_POS_AVI_RATIO); - } -} diff --git a/panda/src/grutil/aviTexture.cxx b/panda/src/grutil/aviTexture.cxx deleted file mode 100755 index 6ffad80883..0000000000 --- a/panda/src/grutil/aviTexture.cxx +++ /dev/null @@ -1,163 +0,0 @@ -// Filename: aviTexture.cxx -// Created by: zacpavlov (19Aug05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "pandabase.h" - -#ifdef HAVE_CV -#include "aviTexture.h" - -TypeHandle AviTexture::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::Constructor -// Access: Published -// Description: Sets up the texture to read frames from a camera -//////////////////////////////////////////////////////////////////// -AviTexture:: -AviTexture() { - _isCamera = true; - _capture = cvCaptureFromCAM(0); - _buf = NULL; - _magicNum = 0; - _time = 0.0f; - _fps = 30.0f; - _total_frames = 0; - _current_frame = 0; - - if (_capture) { - cvSetCaptureProperty(_capture, CV_CAP_PROP_FPS,_fps); - _width = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH); - _height = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT); - - if (_width < _height) { - gen_tex(_width); - } else { - gen_tex(_height); - } - } -} - - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::Constructor -// Access: Published -// Description: Defines the texture as a movie texture. -// TODO: Make this search the panda paths -//////////////////////////////////////////////////////////////////// -AviTexture:: -AviTexture(const string &filename) { - _isCamera = false; - _capture = cvCaptureFromFile(filename.c_str()); - _buf = NULL; - _magicNum = 0; - _time = 0.0f; - _fps = 30.0f; - _total_frames = 0; - _current_frame = 0; - - if (_capture) { - _fps = cvGetCaptureProperty(_capture, CV_CAP_PROP_FPS); - _total_frames = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_COUNT); - _width = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_WIDTH); - _height = cvGetCaptureProperty(_capture, CV_CAP_PROP_FRAME_HEIGHT); - - if (_width < _height) { - gen_tex(_width); - } else { - gen_tex(_height); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::Destructor -// Access: Published -// Description: Destructor. Release the camera or video stream -//////////////////////////////////////////////////////////////////// -AviTexture:: -~AviTexture() { - cvReleaseCapture(&_capture); -} - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::gen_tex -// Access: Published -// Description: Tries to find the largest texture that will fit -// inside the video stream. TODO: allow for fit around -//////////////////////////////////////////////////////////////////// -void AviTexture:: -gen_tex(int magicNum) { - int size = down_to_power_2(magicNum); - - setup_2d_texture(size, size, Texture::T_unsigned_byte, Texture::F_rgb8); - _magicNum = size; -} - -//////////////////////////////////////////////////////////////////// -// Function: AviTexture::update -// Access: Published -// Description: Grabs the next frame off the camera or avi file -// Returns false if the capture fails or reached EOF -//////////////////////////////////////////////////////////////////// -bool AviTexture:: -update() { - int begx, endx, begy, endy; - IplImage *frame = 0; - int xs, ys; - - if (_capture) { - if (_time == 1.0f) { - return false; - } - frame = cvQueryFrame( _capture ); - - if (frame) { - _time = cvGetCaptureProperty(_capture, CV_CAP_PROP_POS_AVI_RATIO); - _current_frame = cvGetCaptureProperty(_capture, CV_CAP_PROP_POS_FRAMES); - if (!obtain_ram()) { - return false; - } - begx = (_width - _magicNum) / 2.0; - endx = _width - begx; - begy = (_height - _magicNum) / 2.0; - endy = _height - begy; - - if (_buf) { - xs = get_x_size(); - ys = get_y_size(); - - if (get_num_components() != 3) { - return false; - } - - for (int i = begy; i < endy; ++i) { - memcpy(_buf + ((i - begy) * xs * 3), - frame->imageData + i * _width * 3 + begx * 3, - xs * 3); - } - - return true; - } - } - } - - return false; -} - -#endif // HAVE_CV - diff --git a/panda/src/grutil/aviTexture.h b/panda/src/grutil/aviTexture.h deleted file mode 100755 index e371fd66cb..0000000000 --- a/panda/src/grutil/aviTexture.h +++ /dev/null @@ -1,94 +0,0 @@ -// Filename: aviTexture.h -// Created by: zacpavlov (19Aug05) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef AVITEXTURE_H -#define AVITEXTURE_H - -#include "pandabase.h" -#ifdef HAVE_CV - -#include "texture.h" -#include -#include -#include - -//////////////////////////////////////////////////////////////////// -// Class : AviTexture -// Description : A specialization on Texture that takes its input -// using the CV library, to produce an animated texture, -// with its source taken from an .avi file or from a -// camera input. -// -// Presently, it is necessary for the application to -// call update() periodically to advance to the next -// frame. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA AviTexture : public Texture { -PUBLISHED: - AviTexture(); - AviTexture(const string &filename); - ~AviTexture(); - - INLINE void set_time(float t); - INLINE float get_time(); - INLINE float get_fps(); - INLINE void set_fps(float fps); - INLINE int get_total_frames(); - INLINE int get_current_frame(); - INLINE void set_current_frame(int frame); - bool update(); - -private: - void gen_tex(int magicNum); - INLINE bool obtain_ram(); - - int _magicNum; - PTA_uchar _buf; - CvCapture * _capture; - float _time; - bool _isCamera; - float _fps; - int _total_frames; - int _current_frame; - int _width; - int _height; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - Texture::init_type(); - register_type(_type_handle, "AviTexture", - Texture::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 "aviTexture.I" - -#endif // HAVE_CV - -#endif diff --git a/panda/src/grutil/config_grutil.cxx b/panda/src/grutil/config_grutil.cxx index 469e9c5b10..d759f15cc3 100644 --- a/panda/src/grutil/config_grutil.cxx +++ b/panda/src/grutil/config_grutil.cxx @@ -18,7 +18,9 @@ #include "config_grutil.h" #include "frameRateMeter.h" -#include "aviTexture.h" +#include "openCVTexture.h" +#include "pandaSystem.h" +#include "texturePool.h" #include "dconfig.h" @@ -63,8 +65,13 @@ init_libgrutil() { FrameRateMeter::init_type(); -#ifdef HAVE_CV - AviTexture::init_type(); -#endif // HAVE_CV +#ifdef HAVE_OPENCV + OpenCVTexture::init_type(); + + PandaSystem *ps = PandaSystem::get_global_ptr(); + ps->add_system("OpenCV"); + TexturePool *ts = TexturePool::get_global_ptr(); + ts->register_texture_type(OpenCVTexture::make_texture, "avi"); +#endif // HAVE_OPENCV } diff --git a/panda/src/grutil/grutil_composite1.cxx b/panda/src/grutil/grutil_composite1.cxx index 8b904a243b..c59c0816d3 100644 --- a/panda/src/grutil/grutil_composite1.cxx +++ b/panda/src/grutil/grutil_composite1.cxx @@ -2,5 +2,5 @@ #include "config_grutil.cxx" #include "lineSegs.cxx" #include "frameRateMeter.cxx" -#include "aviTexture.cxx" +#include "openCVTexture.cxx" diff --git a/panda/src/grutil/openCVTexture.I b/panda/src/grutil/openCVTexture.I new file mode 100644 index 0000000000..fc0ce0b404 --- /dev/null +++ b/panda/src/grutil/openCVTexture.I @@ -0,0 +1,70 @@ +// Filename: openCVTexture.I +// Created by: zacpavlov (19Aug05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoStream::is_valid +// Access: Public +// Description: Returns true if this stream is open and ready, false +// otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool OpenCVTexture::VideoStream:: +is_valid() const { + return (_capture != NULL); +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoStream::is_from_file +// Access: Public +// Description: Returns true if this stream takes its input from a +// video file, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool OpenCVTexture::VideoStream:: +is_from_file() const { + return !_filename.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoPage::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE OpenCVTexture::VideoPage:: +VideoPage() { +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoPage::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE OpenCVTexture::VideoPage:: +VideoPage(const OpenCVTexture::VideoPage ©) : + _color(copy._color), + _alpha(copy._alpha) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoPage::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE OpenCVTexture::VideoPage:: +~VideoPage() { +} diff --git a/panda/src/grutil/openCVTexture.cxx b/panda/src/grutil/openCVTexture.cxx new file mode 100644 index 0000000000..6c44b4ba61 --- /dev/null +++ b/panda/src/grutil/openCVTexture.cxx @@ -0,0 +1,526 @@ +// Filename: openCVTexture.cxx +// Created by: zacpavlov (19Aug05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "pandabase.h" + +#ifdef HAVE_OPENCV +#include "openCVTexture.h" +#include "clockObject.h" +#include "config_gobj.h" +#include "config_grutil.h" + +TypeHandle OpenCVTexture::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::Constructor +// Access: Published +// Description: Sets up the texture to read frames from a camera +//////////////////////////////////////////////////////////////////// +OpenCVTexture:: +OpenCVTexture(const string &name) : + VideoTexture(name) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::Copy Constructor +// Access: Protected +// Description: Use OpenCVTexture::make_copy() to make a duplicate copy of +// an existing OpenCVTexture. +//////////////////////////////////////////////////////////////////// +OpenCVTexture:: +OpenCVTexture(const OpenCVTexture ©) : + VideoTexture(copy), + _pages(copy._pages) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +OpenCVTexture:: +~OpenCVTexture() { +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::make_copy +// Access: Published, Virtual +// Description: Returns a new copy of the same Texture. This copy, +// if applied to geometry, will be copied into texture +// as a separate texture from the original, so it will +// be duplicated in texture memory (and may be +// independently modified if desired). +// +// If the Texture is an OpenCVTexture, the resulting +// duplicate may be animated independently of the +// original. +//////////////////////////////////////////////////////////////////// +PT(Texture) OpenCVTexture:: +make_copy() { + return new OpenCVTexture(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::from_camera +// Access: Published, Virtual +// Description: Sets up the OpenCVTexture (or the indicated page, if z +// is specified) to accept its input from the camera +// with the given index number, or the default camera if +// the index number is -1 or unspecified. +//////////////////////////////////////////////////////////////////// +bool OpenCVTexture:: +from_camera(int camera_index, int z) { + if (!reconsider_z_size(z)) { + return false; + } + nassertr(z >= 0 && z < get_z_size(), false); + + VideoPage &page = modify_page(z); + page._alpha.clear(); + if (!page._color.from_camera(camera_index)) { + return false; + } + + int width = cvGetCaptureProperty(page._color._capture, CV_CAP_PROP_FRAME_WIDTH); + int height = cvGetCaptureProperty(page._color._capture, CV_CAP_PROP_FRAME_HEIGHT); + + if (!reconsider_video_properties(page._color, 3, z)) { + page._color.clear(); + return false; + } + + set_loaded_from_disk(); + clear_current_frame(); + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::read +// Access: Published, Virtual +// Description: Takes the video image from the indicated filename. +// If the filename is not a video file, attempts to read +// it as a still image instead. +//////////////////////////////////////////////////////////////////// +bool OpenCVTexture:: +read(const Filename &fullpath, int z, int) { + if (!reconsider_z_size(z)) { + return false; + } + nassertr(z >= 0 && z < get_z_size(), false); + + VideoPage &page = modify_page(z); + page._alpha.clear(); + if (!page._color.read(fullpath)) { + grutil_cat.error() + << "OpenCV couldn't read " << fullpath << " as video.\n"; + return false; + } + + if (!has_name()) { + set_name(fullpath.get_basename_wo_extension()); + } + if (!has_filename()) { + set_filename(fullpath); + clear_alpha_filename(); + } + + set_fullpath(fullpath); + clear_alpha_fullpath(); + + _primary_file_num_channels = 3; + _alpha_file_channel = 0; + + if (!reconsider_video_properties(page._color, 3, z)) { + page._color.clear(); + return false; + } + + set_loaded_from_disk(); + clear_current_frame(); + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::read +// Access: Published, Virtual +// Description: Combines a color and alpha video image from the two +// indicated filenames. Both must be the same kind of +// video with similar properties. +//////////////////////////////////////////////////////////////////// +bool OpenCVTexture:: +read(const Filename &fullpath, const Filename &alpha_fullpath, + int z, int, int alpha_file_channel) { + if (!reconsider_z_size(z)) { + return false; + } + nassertr(z >= 0 && z < get_z_size(), false); + + VideoPage &page = modify_page(z); + if (!page._color.read(fullpath)) { + grutil_cat.error() + << "OpenCV couldn't read " << fullpath << " as video.\n"; + return false; + } + if (!page._alpha.read(alpha_fullpath)) { + grutil_cat.error() + << "OpenCV couldn't read " << alpha_fullpath << " as video.\n"; + page._color.clear(); + return false; + } + + if (!has_name()) { + set_name(fullpath.get_basename_wo_extension()); + } + if (!has_filename()) { + set_filename(fullpath); + set_alpha_filename(alpha_fullpath); + } + + set_fullpath(fullpath); + set_alpha_fullpath(alpha_fullpath); + + _primary_file_num_channels = 3; + _alpha_file_channel = alpha_file_channel; + + if (!reconsider_video_properties(page._color, 4, z)) { + page._color.clear(); + page._alpha.clear(); + return false; + } + + if (!reconsider_video_properties(page._alpha, 4, z)) { + page._color.clear(); + page._alpha.clear(); + return false; + } + + set_loaded_from_disk(); + clear_current_frame(); + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::load +// Access: Published, Virtual +// Description: Resets the texture (or the particular level of the +// texture) to the indicated static image. +//////////////////////////////////////////////////////////////////// +bool OpenCVTexture:: +load(const PNMImage &pnmimage, int z) { + if (z <= (int)_pages.size()) { + VideoPage &page = modify_page(z); + page._color.clear(); + page._alpha.clear(); + } + + return Texture::load(pnmimage, z); +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::modify_page +// Access: Private +// Description: Returns a reference to the zth VideoPage (level) of +// the texture. In the case of a 2-d texture, there is +// only one page, level 0; but cube maps and 3-d +// textures have more. +//////////////////////////////////////////////////////////////////// +OpenCVTexture::VideoPage &OpenCVTexture:: +modify_page(int z) { + nassertr(z < _z_size, _pages[0]); + while (z >= (int)_pages.size()) { + _pages.push_back(VideoPage()); + } + return _pages[z]; +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::reconsider_video_properties +// Access: Private +// Description: Resets the internal Texture properties when a new +// video file is loaded. Returns true if the new image +// is valid, false otherwise. +//////////////////////////////////////////////////////////////////// +bool OpenCVTexture:: +reconsider_video_properties(const OpenCVTexture::VideoStream &stream, + int num_components, int z) { + double frame_rate = 0.0f; + int num_frames = 0; + + if (stream.is_from_file()) { + frame_rate = cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FPS); + num_frames = (int)cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FRAME_COUNT); + } + int width = (int)cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FRAME_WIDTH); + int height = (int)cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FRAME_HEIGHT); + + int x_size = width; + int y_size = height; + + if (get_power_2()) { + x_size = up_to_power_2(width); + y_size = up_to_power_2(height); + } + + if (!reconsider_image_properties(x_size, y_size, num_components, + T_unsigned_byte, z)) { + return false; + } + + if (_loaded_from_disk && + (get_video_width() != width || get_video_height() != height || + get_num_frames() != num_frames || get_frame_rate() != frame_rate)) { + grutil_cat.error() + << "Video properties have changed for texture " << get_name() + << " level " << z << ".\n"; + return false; + } + + set_frame_rate(frame_rate); + set_num_frames(num_frames); + set_video_size(width, height); + + // By default, the newly-loaded video stream will immediately start + // looping. + loop(true); + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::make_texture +// Access: Public, Static +// Description: A factory function to make a new OpenCVTexture, used +// to pass to the TexturePool. +//////////////////////////////////////////////////////////////////// +PT(Texture) OpenCVTexture:: +make_texture() { + return new OpenCVTexture; +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::update_frame +// Access: Protected, Virtual +// Description: Called once per frame, as needed, to load the new +// image contents. +//////////////////////////////////////////////////////////////////// +void OpenCVTexture:: +update_frame(int frame) { + int max_z = max(_z_size, (int)_pages.size()); + for (int z = 0; z < max_z; ++z) { + VideoPage &page = _pages[z]; + if (page._color.is_valid() || page._alpha.is_valid()) { + modify_ram_image(); + } + if (page._color.is_valid()) { + nassertv(get_num_components() >= 3 && get_component_width() == 1); + + const unsigned char *source = page._color.get_frame_data(frame); + if (source != NULL) { + nassertv(get_video_width() <= _x_size && get_video_height() <= _y_size); + unsigned char *dest = _image.p() + get_expected_ram_page_size() * z; + + int dest_row_width = (_x_size * _num_components * _component_width); + int source_row_width = get_video_width() * 3; + + if (get_num_components() == 3) { + // The easy case--copy the whole thing in, row by row. + for (int y = 0; y < get_video_height(); ++y) { + memcpy(dest, source, source_row_width); + dest += dest_row_width; + source += source_row_width; + } + + } else { + // The harder case--interleave the color in with the alpha, + // pixel by pixel. + nassertv(get_num_components() == 4); + for (int y = 0; y < get_video_height(); ++y) { + int dx = 0; + int sx = 0; + for (int x = 0; x < get_video_width(); ++x) { + dest[dx] = source[sx]; + dest[dx + 1] = source[sx + 1]; + dest[dx + 2] = source[sx + 2]; + dx += 4; + sx += 3; + } + dest += dest_row_width; + source += source_row_width; + } + } + } + } + if (page._alpha.is_valid()) { + nassertv(get_num_components() == 4 && get_component_width() == 1); + + const unsigned char *source = page._alpha.get_frame_data(frame); + if (source != NULL) { + nassertv(get_video_width() <= _x_size && get_video_height() <= _y_size); + unsigned char *dest = _image.p() + get_expected_ram_page_size() * z; + + int dest_row_width = (_x_size * _num_components * _component_width); + int source_row_width = get_video_width() * 3; + + // Interleave the alpha in with the color, pixel by pixel. + // Even though the alpha will probably be a grayscale video, + // the OpenCV library presents it as RGB. + for (int y = 0; y < get_video_height(); ++y) { + int dx = 3; + int sx = _alpha_file_channel; + for (int x = 0; x < get_video_width(); ++x) { + dest[dx] = source[sx]; + dx += 4; + sx += 3; + } + dest += dest_row_width; + source += source_row_width; + } + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoStream::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +OpenCVTexture::VideoStream:: +VideoStream() : + _capture(NULL), + _camera_index(-1), + _next_frame(0) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoStream::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +OpenCVTexture::VideoStream:: +VideoStream(const OpenCVTexture::VideoStream ©) : + _capture(NULL), + _camera_index(-1) +{ + // Rather than copying the _capture pointer, we must open a new + // stream that references the same file. + if (copy.is_valid()) { + if (copy.is_from_file()) { + read(copy._filename); + } else { + from_camera(copy._camera_index); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoStream::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +OpenCVTexture::VideoStream:: +~VideoStream() { + clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoStream::get_frame_data +// Access: Public +// Description: Returns the pointer to the beginning of the +// decompressed buffer for the indicated frame number. +// It is most efficient to call this in increasing order +// of frame number. +//////////////////////////////////////////////////////////////////// +const unsigned char *OpenCVTexture::VideoStream:: +get_frame_data(int frame) { + nassertr(is_valid(), NULL); + + if (is_from_file() && _next_frame != frame) { + cvSetCaptureProperty(_capture, CV_CAP_PROP_POS_FRAMES, frame); + } + + _next_frame = frame + 1; + IplImage *image = cvQueryFrame(_capture); + if (image == NULL) { + return NULL; + } + return (const unsigned char *)image->imageData; +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoStream::read +// Access: Public +// Description: Sets up the stream to read the indicated file. +// Returns true on success, false on failure. +//////////////////////////////////////////////////////////////////// +bool OpenCVTexture::VideoStream:: +read(const Filename &filename) { + clear(); + + string os_specific = filename.to_os_specific(); + _capture = cvCaptureFromFile(os_specific.c_str()); + if (_capture == NULL) { + return false; + } + _filename = filename; + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoStream::from_camera +// Access: Public +// Description: Sets up the stream to display the indicated camera. +// Returns true on success, false on failure. +//////////////////////////////////////////////////////////////////// +bool OpenCVTexture::VideoStream:: +from_camera(int camera_index) { + clear(); + + _capture = cvCaptureFromCAM(camera_index); + if (_capture == NULL) { + return false; + } + _camera_index = camera_index; + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::VideoStream::clear +// Access: Public +// Description: Stops the video playback and frees the associated +// resources. +//////////////////////////////////////////////////////////////////// +void OpenCVTexture::VideoStream:: +clear() { + if (_capture != NULL) { + cvReleaseCapture(&_capture); + _capture = NULL; + } + _filename = Filename(); + _camera_index = -1; + _next_frame = 0; +} + +#endif // HAVE_OPENCV + diff --git a/panda/src/grutil/openCVTexture.h b/panda/src/grutil/openCVTexture.h new file mode 100644 index 0000000000..b80f66e72b --- /dev/null +++ b/panda/src/grutil/openCVTexture.h @@ -0,0 +1,125 @@ +// Filename: openCVTexture.h +// Created by: zacpavlov (19Aug05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef OPENCVTEXTURE_H +#define OPENCVTEXTURE_H + +#include "pandabase.h" +#ifdef HAVE_OPENCV + +#include "videoTexture.h" + +#include +#include +#include + +//////////////////////////////////////////////////////////////////// +// Class : OpenCVTexture +// Description : A specialization on VideoTexture that takes its input +// using the CV library, to produce an animated texture, +// with its source taken from an .avi file or from a +// camera input. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA OpenCVTexture : public VideoTexture { +PUBLISHED: + OpenCVTexture(const string &name = string()); +protected: + OpenCVTexture(const OpenCVTexture ©); +PUBLISHED: + virtual ~OpenCVTexture(); + + virtual PT(Texture) make_copy(); + + bool from_camera(int camera_index = -1, int z = 0); + + virtual bool read(const Filename &fullpath, int z = 0, + int primary_file_num_channels = 0); + virtual bool read(const Filename &fullpath, const Filename &alpha_fullpath, + int z = 0, + int primary_file_num_channels = 0, int alpha_file_channel = 0); + virtual bool load(const PNMImage &pnmimage, int z = 0); + +public: + static PT(Texture) make_texture(); + +protected: + virtual void update_frame(int frame); + +private: + class VideoPage; + class VideoStream; + + VideoPage &modify_page(int z); + bool reconsider_video_properties(const VideoStream &stream, + int num_components, int z); + void do_update(); + + class VideoStream { + public: + VideoStream(); + VideoStream(const VideoStream ©); + ~VideoStream(); + + bool read(const Filename &filename); + bool from_camera(int camera_index); + void clear(); + INLINE bool is_valid() const; + INLINE bool is_from_file() const; + const unsigned char *get_frame_data(int frame); + + CvCapture *_capture; + Filename _filename; + int _camera_index; + int _next_frame; + }; + + class VideoPage { + public: + INLINE VideoPage(); + INLINE VideoPage(const VideoPage ©); + INLINE ~VideoPage(); + + VideoStream _color, _alpha; + }; + + typedef pvector Pages; + Pages _pages; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + VideoTexture::init_type(); + register_type(_type_handle, "OpenCVTexture", + VideoTexture::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 "openCVTexture.I" + +#endif // HAVE_OPENCV + +#endif diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index 93c82a9a93..c28258d218 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -214,7 +214,12 @@ traverse_below(CullTraverserData &data) { _geoms_pcollector.add_level(num_geoms); for (int i = 0; i < num_geoms; i++) { CullableObject *object = new CullableObject(data, geom_node, i); - _cull_handler->record_object(object, this); + if (object->_state->has_cull_callback() && + !object->_state->cull_callback(this, data)) { + delete object; + } else { + _cull_handler->record_object(object, this); + } } } @@ -533,7 +538,14 @@ start_decal(const CullTraverserData &data) { int num_geoms = geom_node->get_num_geoms(); _geoms_pcollector.add_level(num_geoms); for (int i = num_geoms - 1; i >= 0; i--) { - object = new CullableObject(data, geom_node, i, object); + CullableObject *next_object = + new CullableObject(data, geom_node, i, object); + if (next_object->_state->has_cull_callback() && + !next_object->_state->cull_callback(this, data)) { + delete next_object; + } else { + object = next_object; + } } if (object != separator) { @@ -591,7 +603,14 @@ r_get_decals(CullTraverserData &data, CullableObject *decals) { int num_geoms = geom_node->get_num_geoms(); _geoms_pcollector.add_level(num_geoms); for (int i = num_geoms - 1; i >= 0; i--) { - decals = new CullableObject(data, geom_node, i, decals); + CullableObject *next_decals = + new CullableObject(data, geom_node, i, decals); + if (next_decals->_state->has_cull_callback() && + !next_decals->_state->cull_callback(this, data)) { + delete next_decals; + } else { + decals = next_decals; + } } } } diff --git a/panda/src/pgraph/renderAttrib.cxx b/panda/src/pgraph/renderAttrib.cxx index 84bd12f3a9..2c18c23fa7 100644 --- a/panda/src/pgraph/renderAttrib.cxx +++ b/panda/src/pgraph/renderAttrib.cxx @@ -125,6 +125,38 @@ lower_attrib_can_override() const { return false; } +//////////////////////////////////////////////////////////////////// +// Function: RenderAttrib::has_cull_callback +// Access: Public, Virtual +// Description: Should be overridden by derived classes to return +// true if cull_callback() has been defined. Otherwise, +// returns false to indicate cull_callback() does not +// need to be called for this node during the cull +// traversal. +//////////////////////////////////////////////////////////////////// +bool RenderAttrib:: +has_cull_callback() const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderAttrib::cull_callback +// Access: Public, Virtual +// Description: If has_cull_callback() returns true, this function +// will be called during the cull traversal to perform +// any additional operations that should be performed at +// cull time. +// +// This is called each time the RenderAttrib is +// discovered applied to a Geom in the traversal. It +// should return true if the Geom is visible, false if +// it should be omitted. +//////////////////////////////////////////////////////////////////// +bool RenderAttrib:: +cull_callback(CullTraverser *, const CullTraverserData &) const { + return true; +} + //////////////////////////////////////////////////////////////////// // Function: RenderAttrib::output // Access: Published, Virtual diff --git a/panda/src/pgraph/renderAttrib.h b/panda/src/pgraph/renderAttrib.h index 6d26c15192..679862b7da 100644 --- a/panda/src/pgraph/renderAttrib.h +++ b/panda/src/pgraph/renderAttrib.h @@ -27,6 +27,8 @@ class AttribSlots; class GraphicsStateGuardianBase; +class CullTraverser; +class CullTraverserData; //////////////////////////////////////////////////////////////////// // Class : RenderAttrib @@ -73,6 +75,9 @@ public: INLINE bool always_reissue() const; virtual void store_into_slot(AttribSlots *slots) const=0; + virtual bool has_cull_callback() const; + virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const; + PUBLISHED: INLINE int compare_to(const RenderAttrib &other) const; virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/renderState.I b/panda/src/pgraph/renderState.I index a305de50d9..271c4b7374 100644 --- a/panda/src/pgraph/renderState.I +++ b/panda/src/pgraph/renderState.I @@ -61,6 +61,23 @@ get_override(int n) const { return _attributes[n]._override; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::has_cull_callback +// Access: Published +// Description: Returns true if any of the RenderAttribs in this +// state request a cull_callback(), false if none of +// them do. +//////////////////////////////////////////////////////////////////// +INLINE bool RenderState:: +has_cull_callback() const { + if ((_flags & F_checked_cull_callback) == 0) { + // We pretend this function is const, even though it transparently + // modifies the internal shader cache. + ((RenderState *)this)->determine_cull_callback(); + } + return (_flags & F_has_cull_callback) != 0; +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::cache_ref // Access: Published diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index 9febd4d964..aadd5bbe8f 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -136,6 +136,26 @@ operator < (const RenderState &other) const { CompareTo()); } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::cull_callback +// Access: Published +// Description: Calls cull_callback() on each attrib. If any attrib +// returns false, interrupts the list and returns false +// immediately; otherwise, completes the list and +// returns true. +//////////////////////////////////////////////////////////////////// +bool RenderState:: +cull_callback(CullTraverser *trav, const CullTraverserData &data) const { + Attributes::const_iterator ai; + for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) { + const Attribute &attrib = *ai; + if (!attrib._attrib->cull_callback(trav, data)) { + return false; + } + } + + return true; +} //////////////////////////////////////////////////////////////////// // Function: RenderState::find_attrib @@ -1570,6 +1590,25 @@ determine_shader() { _flags |= F_checked_shader; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::determine_cull_callback +// Access: Private +// Description: This is the private implementation of has_cull_callback(). +//////////////////////////////////////////////////////////////////// +void RenderState:: +determine_cull_callback() { + Attributes::const_iterator ai; + for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) { + const Attribute &attrib = *ai; + if (attrib._attrib->has_cull_callback()) { + _flags |= F_has_cull_callback; + break; + } + } + + _flags |= F_checked_cull_callback; +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::update_pstats // Access: Private diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index c64acbce1f..af02bcc6e3 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -75,6 +75,9 @@ PUBLISHED: INLINE const RenderAttrib *get_attrib(int n) const; INLINE int get_override(int n) const; + INLINE bool has_cull_callback() const; + bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const; + int find_attrib(TypeHandle type) const; static CPT(RenderState) make_empty(); @@ -181,6 +184,7 @@ private: void determine_render_mode(); void determine_clip_plane(); void determine_shader(); + void determine_cull_callback(); INLINE void set_destructing(); INLINE bool is_destructing() const; @@ -282,19 +286,21 @@ private: const ShaderAttrib *_shader; enum Flags { - F_checked_bin_index = 0x0001, - F_checked_fog = 0x0002, - F_checked_bin = 0x0004, - F_checked_transparency = 0x0008, - F_checked_color = 0x0010, - F_checked_color_scale = 0x0020, - F_checked_texture = 0x0040, - F_checked_tex_gen = 0x0080, - F_checked_tex_matrix = 0x0100, - F_checked_render_mode = 0x0200, - F_checked_clip_plane = 0x0400, - F_checked_shader = 0x0800, - F_is_destructing = 0x8000, + F_checked_bin_index = 0x0001, + F_checked_fog = 0x0002, + F_checked_bin = 0x0004, + F_checked_transparency = 0x0008, + F_checked_color = 0x0010, + F_checked_color_scale = 0x0020, + F_checked_texture = 0x0040, + F_checked_tex_gen = 0x0080, + F_checked_tex_matrix = 0x0100, + F_checked_render_mode = 0x0200, + F_checked_clip_plane = 0x0400, + F_checked_shader = 0x0800, + F_checked_cull_callback = 0x1000, + F_has_cull_callback = 0x2000, + F_is_destructing = 0x8000, }; unsigned short _flags; diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index 44c2a13c63..ffb5f30dbe 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -390,6 +390,54 @@ output(ostream &out) const { } } +//////////////////////////////////////////////////////////////////// +// Function: TextureAttrib::has_cull_callback +// Access: Public, Virtual +// Description: Should be overridden by derived classes to return +// true if cull_callback() has been defined. Otherwise, +// returns false to indicate cull_callback() does not +// need to be called for this node during the cull +// traversal. +//////////////////////////////////////////////////////////////////// +bool TextureAttrib:: +has_cull_callback() const { + OnTextures::const_iterator nti; + for (nti = _on_textures.begin(); nti != _on_textures.end(); ++nti) { + Texture *texture = (*nti).second; + if (texture->has_cull_callback()) { + return true; + } + } + + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureAttrib::cull_callback +// Access: Public, Virtual +// Description: If has_cull_callback() returns true, this function +// will be called during the cull traversal to perform +// any additional operations that should be performed at +// cull time. +// +// This is called each time the RenderAttrib is +// discovered applied to a Geom in the traversal. It +// should return true if the Geom is visible, false if +// it should be omitted. +//////////////////////////////////////////////////////////////////// +bool TextureAttrib:: +cull_callback(CullTraverser *trav, const CullTraverserData &data) const { + OnTextures::const_iterator nti; + for (nti = _on_textures.begin(); nti != _on_textures.end(); ++nti) { + Texture *texture = (*nti).second; + if (!texture->cull_callback(trav, data)) { + return false; + } + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: TextureAttrib::compare_to_impl // Access: Protected, Virtual diff --git a/panda/src/pgraph/textureAttrib.h b/panda/src/pgraph/textureAttrib.h index 395767d8dc..5cb37613fe 100644 --- a/panda/src/pgraph/textureAttrib.h +++ b/panda/src/pgraph/textureAttrib.h @@ -84,6 +84,9 @@ public: virtual void output(ostream &out) const; virtual void store_into_slot(AttribSlots *slots) const; + virtual bool has_cull_callback() const; + virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const; + protected: virtual int compare_to_impl(const RenderAttrib *other) const; virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const; diff --git a/panda/src/putil/Sources.pp b/panda/src/putil/Sources.pp index bff23aaacc..8c9cacbe7f 100644 --- a/panda/src/putil/Sources.pp +++ b/panda/src/putil/Sources.pp @@ -8,6 +8,7 @@ #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx #define SOURCES \ + animInterface.h animInterface.I \ bam.h bamEndian.h \ bamReader.I bamReader.N bamReader.h bamReaderParam.I \ bamReaderParam.h bamWriter.I bamWriter.h bitMask.I \ @@ -60,6 +61,7 @@ writableParam.I writableParam.h #define INCLUDED_SOURCES \ + animInterface.cxx \ bamEndian.cxx \ bamReader.cxx bamReaderParam.cxx bamWriter.cxx bitMask.cxx \ buttonHandle.cxx buttonRegistry.cxx \ @@ -96,6 +98,7 @@ writableConfigurable.cxx writableParam.cxx #define INSTALL_HEADERS \ + animInterface.h animInterface.I \ bam.h bamEndian.h \ bamReader.I bamReader.h bamReaderParam.I bamReaderParam.h \ bamWriter.I bamWriter.h bitMask.I bitMask.h \ diff --git a/panda/src/putil/animInterface.I b/panda/src/putil/animInterface.I new file mode 100644 index 0000000000..5e455df3d2 --- /dev/null +++ b/panda/src/putil/animInterface.I @@ -0,0 +1,178 @@ +// Filename: animInterface.I +// Created by: drose (20Sep05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::play +// Access: Published +// Description: Runs the entire animation from beginning to end and +// stops. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +play() { + play(0, get_num_frames() - 1); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::loop +// Access: Published +// Description: Starts the entire animation looping. If restart is +// true, the animation is restarted from the beginning; +// otherwise, it continues from the current frame. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +loop(bool restart) { + loop(restart, 0, get_num_frames() - 1); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::pingpong +// Access: Published +// Description: Starts the entire animation bouncing back and forth +// between its first frame and last frame. If restart +// is true, the animation is restarted from the +// beginning; otherwise, it continues from the current +// frame. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +pingpong(bool restart) { + pingpong(restart, 0, get_num_frames() - 1); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::stop +// Access: Published +// Description: Stops a currently playing or looping animation right +// where it is. The animation remains posed at the +// current frame. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +stop() { + pose(get_frame()); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::set_play_rate +// Access: Published +// Description: Changes the rate at which the animation plays. 1.0 +// is the normal speed, 2.0 is twice normal speed, and +// 0.5 is half normal speed. 0.0 is legal to pause the +// animation, and a negative value will play the +// animation backwards. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +set_play_rate(double play_rate) { + internal_set_rate(_frame_rate, play_rate); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_play_rate +// Access: Published +// Description: Returns the rate at which the animation plays. See +// set_play_rate(). +//////////////////////////////////////////////////////////////////// +INLINE double AnimInterface:: +get_play_rate() const { + return _play_rate; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_frame_rate +// Access: Published +// Description: Returns the native frame rate of the animation. This +// is the number of frames per second that will elapse +// when the play_rate is set to 1.0. It is a fixed +// property of the animation and may not be adjusted by +// the user. +//////////////////////////////////////////////////////////////////// +INLINE double AnimInterface:: +get_frame_rate() const { + return _frame_rate; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_num_frames +// Access: Published +// Description: Returns the number of frames in the animation. This +// is a fixed property of the animation and may not be +// adjusted by the user. +//////////////////////////////////////////////////////////////////// +INLINE int AnimInterface:: +get_num_frames() const { + return _num_frames; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_frame +// Access: Published +// Description: Returns the current integer frame number. +// This number will be in the range 0 <= f < +// get_num_frames(). +//////////////////////////////////////////////////////////////////// +INLINE int AnimInterface:: +get_frame() const { + return cmod(get_full_frame(), get_num_frames()); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_frac +// Access: Published +// Description: Returns the fractional part of the current frame. +// Normally, this is in the range 0.0 <= f < 1.0, but in +// the one special case of an animation playing to its +// end frame and stopping, it might exactly equal 1.0. +// +// It will always be true that get_full_frame() + +// get_frac() == get_full_fframe(). +//////////////////////////////////////////////////////////////////// +INLINE double AnimInterface:: +get_frac() const { + return get_full_fframe() - (double)get_full_frame(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::set_frame_rate +// Access: Protected +// Description: Should be called by a derived class to specify the +// native frame rate of the animation. It is legal to +// call this after the animation has already started. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +set_frame_rate(double frame_rate) { + internal_set_rate(frame_rate, _play_rate); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::set_num_frames +// Access: Protected +// Description: Should be called by a derived class to specify the +// number of frames of the animation. It is legal to +// call this after the animation has already started, +// but doing so may suddenly change the apparent current +// frame number. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +set_num_frames(int num_frames) { + _num_frames = num_frames; +} + +INLINE ostream & +operator << (ostream &out, const AnimInterface &ai) { + ai.output(out); + return out; +} diff --git a/panda/src/putil/animInterface.cxx b/panda/src/putil/animInterface.cxx new file mode 100644 index 0000000000..d711f6e0f3 --- /dev/null +++ b/panda/src/putil/animInterface.cxx @@ -0,0 +1,379 @@ +// Filename: animInterface.cxx +// Created by: drose (20Sep05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "animInterface.h" +#include "clockObject.h" + +TypeHandle AnimInterface::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +AnimInterface:: +AnimInterface() : + _frame_rate(0.0), + _num_frames(0), + _play_mode(PM_pose), + _start_time(0.0), + _start_frame(0.0), + _play_frames(0.0), + _from_frame(0), + _to_frame(0), + _play_rate(1.0), + _effective_frame_rate(0.0), + _paused(true), + _paused_f(0.0) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +AnimInterface:: +AnimInterface(const AnimInterface ©) : + _frame_rate(copy._frame_rate), + _num_frames(copy._num_frames), + _play_mode(copy._play_mode), + _start_time(copy._start_time), + _start_frame(copy._start_frame), + _play_frames(copy._play_frames), + _from_frame(copy._from_frame), + _to_frame(copy._to_frame), + _play_rate(copy._play_rate), + _effective_frame_rate(copy._effective_frame_rate), + _paused(copy._paused), + _paused_f(copy._paused_f) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +AnimInterface:: +~AnimInterface() { +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::play +// Access: Published +// Description: Runs the animation from the frame "from" to and +// including the frame "to", at which point the +// animation is stopped. Both "from" and "to" frame +// numbers may be outside the range (0, +// get_num_frames()) and the animation will follow the +// range correctly, reporting numbers modulo +// get_num_frames(). For instance, play(0, +// get_num_frames() * 2) will play the animation twice +// and then stop. +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +play(double from, double to) { + if (from >= to) { + pose(from); + return; + } + + _play_mode = PM_play; + _start_time = ClockObject::get_global_clock()->get_frame_time(); + _start_frame = from; + _play_frames = to - from + 1.0; + _from_frame = (int)floor(from); + _to_frame = (int)floor(to); + _paused_f = 0.0; + + if (_effective_frame_rate < 0.0) { + // If we'll be playing backward, start at the end. + _start_time -= _play_frames / _effective_frame_rate; + } + + animation_activated(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::loop +// Access: Published +// Description: Loops the animation from the frame "from" to and +// including the frame "to", indefinitely. If restart +// is true, the animation is restarted from the +// beginning; otherwise, it continues from the current +// frame. +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +loop(bool restart, double from, double to) { + if (from >= to) { + pose(from); + return; + } + + double fframe = get_full_fframe(); + + _play_mode = PM_loop; + _start_time = ClockObject::get_global_clock()->get_frame_time(); + _start_frame = from; + _play_frames = to - from + 1.0; + _from_frame = (int)floor(from); + _to_frame = (int)floor(to); + _paused_f = 0.0; + + if (!restart) { + if (_paused) { + _paused_f = fframe - _start_frame; + } else { + _start_time -= fframe / _effective_frame_rate; + } + } + + animation_activated(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::pingpong +// Access: Published +// Description: Loops the animation from the frame "from" to and +// including the frame "to", and then back in the +// opposite direction, indefinitely. +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +pingpong(bool restart, double from, double to) { + if (from >= to) { + pose(from); + return; + } + + double fframe = get_full_fframe(); + + _play_mode = PM_pingpong; + _start_time = ClockObject::get_global_clock()->get_frame_time(); + _start_frame = from; + _play_frames = to - from + 1.0; + _from_frame = (int)floor(from); + _to_frame = (int)floor(to); + _paused_f = 0.0; + + if (!restart) { + if (_paused) { + _paused_f = fframe - _start_frame; + } else { + _start_time -= fframe / _effective_frame_rate; + } + } + + animation_activated(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::pose +// Access: Published +// Description: Sets the animation to the indicated frame and holds +// it there. +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +pose(int frame) { + _play_mode = PM_pose; + _start_time = ClockObject::get_global_clock()->get_frame_time(); + _start_frame = (double)frame; + _play_frames = 0.0; + _from_frame = frame; + _to_frame = frame; + _paused_f = 0.0; + + animation_activated(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_full_frame +// Access: Published +// Description: Returns the current integer frame number. +// +// Unlike the value returned by get_frame(), this frame +// number may extend beyond the range of +// get_num_frames() if the frame range passed to play(), +// loop(), etc. did. +// +// Unlike the value returned by get_full_fframe(), this +// return value will never exceed the value passed to +// to_frame in the play() method. +//////////////////////////////////////////////////////////////////// +int AnimInterface:: +get_full_frame() const { + int frame = (int)floor(get_full_fframe()); + if (_play_mode == PM_play) { + // In play mode, we never let the return value exceed + // (_from_frame, _to_frame). + frame = min(max(frame, _from_frame), _to_frame); + } + return frame; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_full_fframe +// Access: Published +// Description: Returns the current floating-point frame number. +// +// Unlike the value returned by get_frame(), this frame +// number may extend beyond the range of +// get_num_frames() if the frame range passed to play(), +// loop(), etc. did. +// +// Unlike the value returned by get_full_frame(), this +// return value may equal (to_frame + 1.0), when the +// animation has played to its natural end. However, in +// this case the return value of get_full_frame() will +// be to_frame, not (to_frame + 1). +//////////////////////////////////////////////////////////////////// +double AnimInterface:: +get_full_fframe() const { + switch (_play_mode) { + case PM_pose: + return _start_frame; + + case PM_play: + return min(max(get_f(), 0.0), _play_frames) + _start_frame; + + case PM_loop: + return cmod(get_f(), _play_frames) + _start_frame; + + case PM_pingpong: + { + double f = cmod(get_f(), _play_frames * 2.0); + if (f > _play_frames) { + return (_play_frames * 2.0 - f) + _start_frame; + } else { + return f + _start_frame; + } + } + } + + return _start_frame; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::is_playing +// Access: Published +// Description: Returns true if the animation is currently playing, +// false if it is stopped (e.g. because stop() or pose() +// was called, or because it reached the end of the +// animation after play() was called). +//////////////////////////////////////////////////////////////////// +bool AnimInterface:: +is_playing() const { + switch (_play_mode) { + case PM_pose: + return false; + + case PM_play: + return get_f() < _play_frames; + + case PM_loop: + case PM_pingpong: + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::output +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +output(ostream &out) const { + switch (_play_mode) { + case PM_pose: + out << "pose, frame " << get_frame(); + return; + + case PM_play: + out << "play, frame " << get_frame(); + return; + + case PM_loop: + out << "loop, frame " << get_frame(); + return; + + case PM_pingpong: + out << "pingpong, frame " << get_frame(); + return; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::animation_activated +// Access: Protected, Virtual +// Description: This is provided as a callback method for when the +// user calls one of the play/loop/pose type methods to +// start the animation playing. +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +animation_activated() { +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_f +// Access: Private +// Description: Returns the current floating-point frame number, +// elapsed since _start_frame. +//////////////////////////////////////////////////////////////////// +double AnimInterface:: +get_f() const { + if (_paused) { + return _paused_f; + + } else { + double now = ClockObject::get_global_clock()->get_frame_time(); + double elapsed = now - _start_time; + return (elapsed * _effective_frame_rate); + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::internal_set_rate +// Access: Private +// Description: Called internally to adjust either or both of the +// frame_rate or play_rate without changing the current +// frame number if the animation is already playing. +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +internal_set_rate(double frame_rate, double play_rate) { + double f = get_f(); + + _frame_rate = frame_rate; + _play_rate = play_rate; + _effective_frame_rate = frame_rate * play_rate; + + if (_effective_frame_rate == 0.0) { + _paused_f = f; + _paused = true; + + } else { + // Compute a new _start_time that will keep f the same value with + // the new play_rate. + double new_elapsed = f / _effective_frame_rate; + double now = ClockObject::get_global_clock()->get_frame_time(); + _start_time = now - new_elapsed; + _paused = false; + } +} diff --git a/panda/src/putil/animInterface.h b/panda/src/putil/animInterface.h new file mode 100644 index 0000000000..76c9477262 --- /dev/null +++ b/panda/src/putil/animInterface.h @@ -0,0 +1,111 @@ +// Filename: animInterface.h +// Created by: drose (20Sep05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef ANIMINTERFACE_H +#define ANIMINTERFACE_H + +#include "pandabase.h" +#include "typeHandle.h" +#include "register_type.h" + +//////////////////////////////////////////////////////////////////// +// Class : AnimInterface +// Description : This is the fundamental interface for things that +// have a play/loop/stop type interface for frame-based +// animation, such as animated characters. This is the +// base class for AnimControl and other, similar +// classes. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA AnimInterface { +protected: + AnimInterface(); + AnimInterface(const AnimInterface ©); + +PUBLISHED: + virtual ~AnimInterface(); + INLINE void play(); + void play(double from, double to); + INLINE void loop(bool restart); + void loop(bool restart, double from, double to); + INLINE void pingpong(bool restart); + void pingpong(bool restart, double from, double to); + INLINE void stop(); + void pose(int frame); + + INLINE void set_play_rate(double play_rate); + INLINE double get_play_rate() const; + INLINE double get_frame_rate() const; + INLINE int get_num_frames() const; + + INLINE int get_frame() const; + INLINE double get_frac() const; + int get_full_frame() const; + double get_full_fframe() const; + bool is_playing() const; + + virtual void output(ostream &out) const; + +protected: + INLINE void set_frame_rate(double frame_rate); + INLINE void set_num_frames(int num_frames); + virtual void animation_activated(); + +private: + double get_f() const; + void internal_set_rate(double frame_rate, double play_rate); + +private: + enum PlayMode { + PM_pose, + PM_play, + PM_loop, + PM_pingpong, + }; + + double _frame_rate; + int _num_frames; + + PlayMode _play_mode; + double _start_time; + double _start_frame; + double _play_frames; + int _from_frame; + int _to_frame; + + double _play_rate; + double _effective_frame_rate; + bool _paused; + double _paused_f; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + register_type(_type_handle, "AnimInterface"); + } + +private: + static TypeHandle _type_handle; +}; + +INLINE ostream &operator << (ostream &out, const AnimInterface &ai); + +#include "animInterface.I" + +#endif diff --git a/panda/src/putil/config_util.cxx b/panda/src/putil/config_util.cxx index 708a5e396e..2626e24ffd 100644 --- a/panda/src/putil/config_util.cxx +++ b/panda/src/putil/config_util.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "config_util.h" +#include "animInterface.h" #include "bamReaderParam.h" #include "cachedTypedWritableReferenceCount.h" #include "clockObject.h" @@ -67,6 +68,7 @@ ConfigVariableSearchPath sound_path PRC_DESC("The directories to search for sound and music files to be loaded.")); ConfigureFn(config_util) { + AnimInterface::init_type(); BamReaderParam::init_type(); CachedTypedWritableReferenceCount::init_type(); Configurable::init_type(); diff --git a/panda/src/putil/putil_composite1.cxx b/panda/src/putil/putil_composite1.cxx index 0a2beeb973..32a02e088f 100644 --- a/panda/src/putil/putil_composite1.cxx +++ b/panda/src/putil/putil_composite1.cxx @@ -1,3 +1,4 @@ +#include "animInterface.cxx" #include "bamEndian.cxx" #include "bamReader.cxx" #include "bamReaderParam.cxx" diff --git a/panda/src/recorder/config_recorder.cxx b/panda/src/recorder/config_recorder.cxx index 87ae9a24f9..7778c4d74e 100644 --- a/panda/src/recorder/config_recorder.cxx +++ b/panda/src/recorder/config_recorder.cxx @@ -43,7 +43,7 @@ ConfigureFn(config_recorder) { RecorderHeader::register_with_read_factory(); RecorderTable::register_with_read_factory(); -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL SocketStreamRecorder::init_type(); SocketStreamRecorder::register_with_read_factory(); #endif diff --git a/panda/src/recorder/socketStreamRecorder.cxx b/panda/src/recorder/socketStreamRecorder.cxx index 3b6da50fda..e7315891b1 100644 --- a/panda/src/recorder/socketStreamRecorder.cxx +++ b/panda/src/recorder/socketStreamRecorder.cxx @@ -21,7 +21,7 @@ #include "bamReader.h" #include "bamWriter.h" -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL TypeHandle SocketStreamRecorder::_type_handle; @@ -159,4 +159,4 @@ fillin_recorder(DatagramIterator &scan, BamReader *manager) { RecorderBase::fillin_recorder(scan, manager); } -#endif // HAVE_SSL +#endif // HAVE_OPENSSL diff --git a/panda/src/recorder/socketStreamRecorder.h b/panda/src/recorder/socketStreamRecorder.h index ac81ec9b1f..3db85b9346 100644 --- a/panda/src/recorder/socketStreamRecorder.h +++ b/panda/src/recorder/socketStreamRecorder.h @@ -31,7 +31,7 @@ class FactoryParams; // available, since in that case socketStream.h is not compiled // either. -#ifdef HAVE_SSL +#ifdef HAVE_OPENSSL //////////////////////////////////////////////////////////////////// // Class : SocketStreamRecorder @@ -104,6 +104,6 @@ private: #include "socketStreamRecorder.I" -#endif // HAVE_SSL +#endif // HAVE_OPENSSL #endif // SOCKETSTREAMRECORDER_H