?? gameswf_impl.cpp
字號:
// gameswf_impl.cpp -- Thatcher Ulrich <tu@tulrich.com> 2003// This source code has been donated to the Public Domain. Do// whatever you want with it.// Some implementation for SWF player.// Useful links://// http://sswf.sourceforge.net/SWFalexref.html// http://www.openswf.org// @@ Need to break this file into pieces#include "base/tu_file.h"#include "base/utility.h"#include "gameswf_action.h"#include "gameswf_button.h"#include "gameswf_impl.h"#include "gameswf_font.h"#include "gameswf_fontlib.h"#include "gameswf_log.h"#include "gameswf_morph2.h"#include "gameswf_render.h"#include "gameswf_shape.h"#include "gameswf_stream.h"#include "gameswf_styles.h"#include "gameswf_dlist.h"#include "gameswf_timers.h"#include "base/image.h"#include "base/jpeg.h"#include "base/zlib_adapter.h"#include <string.h> // for memset#include <typeinfo>#include <float.h>#if TU_CONFIG_LINK_TO_ZLIB#include <zlib.h>#endif // TU_CONFIG_LINK_TO_ZLIBnamespace gameswf{ bool s_verbose_action = false; bool s_verbose_parse = false;#ifndef NDEBUG bool s_verbose_debug = true;#else bool s_verbose_debug = false;#endif void set_verbose_action(bool verbose) // Enable/disable log messages re: actions. { s_verbose_action = verbose; } void set_verbose_parse(bool verbose) // Enable/disable log messages re: parsing the movie. { s_verbose_parse = verbose; } static bool s_use_cache_files = true; void set_use_cache_files(bool use_cache) // Enable/disable attempts to read cache files when loading // movies. { s_use_cache_files = use_cache; } // Keep a table of loader functions for the different tag types. static hash<int, loader_function> s_tag_loaders; void register_tag_loader(int tag_type, loader_function lf) // Associate the specified tag type with the given tag loader // function. { assert(s_tag_loaders.get(tag_type, NULL) == false); assert(lf != NULL); s_tag_loaders.add(tag_type, lf); } // // file_opener callback stuff // static file_opener_callback s_opener_function = NULL; void register_file_opener_callback(file_opener_callback opener) // Host calls this to register a function for opening files, // for loading movies. { s_opener_function = opener; } // // progress callback stuff (from Vitaly) // static progress_callback s_progress_function = NULL; void register_progress_callback(progress_callback progress_handle) // Host calls this to register a function for progress bar handling // during loading movies. { s_progress_function = progress_handle; } // // some utility stuff // static void execute_actions(as_environment* env, const array<action_buffer*>& action_list) // Execute the actions in the action list, in the given // environment. { for (int i = 0; i < action_list.size(); i++) { action_list[i]->execute(env); } } static void dump_tag_bytes(stream* in) // Log the contents of the current tag, in hex. { static const int ROW_BYTES = 16; char row_buf[ROW_BYTES]; int row_count = 0; while(in->get_position() < in->get_tag_end_position()) { int c = in->read_u8(); log_msg("%02X", c); if (c < 32) c = '.'; if (c > 127) c = '.'; row_buf[row_count] = c; row_count++; if (row_count >= ROW_BYTES) { log_msg(" "); for (int i = 0; i < ROW_BYTES; i++) { log_msg("%c", row_buf[i]); } log_msg("\n"); row_count = 0; } else { log_msg(" "); } } if (row_count > 0) { log_msg("\n"); } } character* character_def::create_character_instance(movie* parent, int id) // Default. Make a generic_character. { return new generic_character(this, parent, id); } // // ref_counted // ref_counted::ref_counted() : m_ref_count(0), m_weak_proxy(0) { } ref_counted::~ref_counted() { assert(m_ref_count == 0); if (m_weak_proxy) { m_weak_proxy->notify_object_died(); m_weak_proxy->drop_ref(); } } void ref_counted::add_ref() const { assert(m_ref_count >= 0); m_ref_count++; } void ref_counted::drop_ref() const { assert(m_ref_count > 0); m_ref_count--; if (m_ref_count <= 0) { // Delete me! delete this; } } weak_proxy* ref_counted::get_weak_proxy() const { assert(m_ref_count > 0); // By rights, somebody should be holding a ref to us. if (m_weak_proxy == NULL) { m_weak_proxy = new weak_proxy; m_weak_proxy->add_ref(); } return m_weak_proxy; } // // character // void character::do_mouse_drag() // Implement mouse-dragging for this movie. { drag_state st; get_drag_state(&st); if (this == st.m_character) { // We're being dragged! int x, y, buttons; get_root_movie()->get_mouse_state(&x, &y, &buttons); point world_mouse(PIXELS_TO_TWIPS(x), PIXELS_TO_TWIPS(y)); if (st.m_bound) { // Clamp mouse coords within a defined rect. world_mouse.m_x = fclamp(world_mouse.m_x, st.m_bound_x0, st.m_bound_x1); world_mouse.m_y = fclamp(world_mouse.m_y, st.m_bound_y0, st.m_bound_y1); } if (st.m_lock_center) { matrix world_mat = get_world_matrix(); point local_mouse; world_mat.transform_by_inverse(&local_mouse, world_mouse); matrix parent_world_mat; if (m_parent) { parent_world_mat = m_parent->get_world_matrix(); } point parent_mouse; parent_world_mat.transform_by_inverse(&parent_mouse, world_mouse); // Place our origin so that it coincides with the mouse coords // in our parent frame. matrix local = get_matrix(); local.m_[0][2] = parent_mouse.m_x; local.m_[1][2] = parent_mouse.m_y; set_matrix(local); } else { // Implement relative drag... } } } // // Helper for movie_def_impl // struct import_info { tu_string m_source_url; int m_character_id; tu_string m_symbol; import_info() : m_character_id(-1) { } import_info(const char* source, int id, const char* symbol) : m_source_url(source), m_character_id(id), m_symbol(symbol) { } }; // // movie_def_impl // // This class holds the immutable definition of a movie's // contents. It cannot be played directly, and does not hold // current state; for that you need to call create_instance() // to get a movie_instance. // struct movie_def_impl : public movie_definition_sub { hash<int, smart_ptr<character_def> > m_characters; hash<int, smart_ptr<font> > m_fonts; hash<int, smart_ptr<bitmap_character_def> > m_bitmap_characters; hash<int, smart_ptr<sound_sample> > m_sound_samples; array<array<execute_tag*> > m_playlist; // A list of movie control events for each frame. array<array<execute_tag*> > m_init_action_list; // Init actions for each frame. stringi_hash<int> m_named_frames; // 0-based frame #'s stringi_hash<smart_ptr<resource> > m_exports; // Items we import. array<import_info> m_imports; // Movies we import from; hold a ref on these, to keep them alive array<smart_ptr<movie_definition> > m_import_source_movies; // Bitmaps used in this movie; collected in one place to make // it possible for the host to manage them as textures. array<smart_ptr<bitmap_info> > m_bitmap_list; create_bitmaps_flag m_create_bitmaps; create_font_shapes_flag m_create_font_shapes; rect m_frame_size; float m_frame_rate; int m_frame_count; int m_version; int m_loading_frame; uint32 m_file_length; jpeg::input* m_jpeg_in; movie_def_impl(create_bitmaps_flag cbf, create_font_shapes_flag cfs) : m_create_bitmaps(cbf), m_create_font_shapes(cfs), m_frame_rate(30.0f), m_frame_count(0), m_version(0), m_loading_frame(0), m_jpeg_in(0) { } ~movie_def_impl() { // Release our playlist data. {for (int i = 0, n = m_playlist.size(); i < n; i++) { for (int j = 0, m = m_playlist[i].size(); j < m; j++) { delete m_playlist[i][j]; } }} // Release init action data. {for (int i = 0, n = m_init_action_list.size(); i < n; i++) { for (int j = 0, m = m_init_action_list[i].size(); j < m; j++) { delete m_init_action_list[i][j]; } }} assert(m_jpeg_in == NULL); // It's supposed to be cleaned up in read() } movie_interface* create_instance(); // ... int get_frame_count() const { return m_frame_count; } float get_frame_rate() const { return m_frame_rate; } float get_width_pixels() const { return ceilf(TWIPS_TO_PIXELS(m_frame_size.width())); } float get_height_pixels() const { return ceilf(TWIPS_TO_PIXELS(m_frame_size.height())); } virtual int get_version() const { return m_version; } virtual int get_loading_frame() const { return m_loading_frame; } uint32 get_file_bytes() const { return m_file_length; } /* movie_def_impl */ virtual create_bitmaps_flag get_create_bitmaps() const // Returns DO_CREATE_BITMAPS if we're supposed to // initialize our bitmap infos, or DO_NOT_INIT_BITMAPS // if we're supposed to create blank placeholder // bitmaps (to be init'd later explicitly by the host // program). { return m_create_bitmaps; } /* movie_def_impl */ virtual create_font_shapes_flag get_create_font_shapes() const // Returns DO_LOAD_FONT_SHAPES if we're supposed to // initialize our font shape info, or // DO_NOT_LOAD_FONT_SHAPES if we're supposed to not // create any (vector) font glyph shapes, and instead // rely on precached textured fonts glyphs. { return m_create_font_shapes; } virtual void add_bitmap_info(bitmap_info* bi) // All bitmap_info's used by this movie should be // registered with this API. { m_bitmap_list.push_back(bi); } virtual int get_bitmap_info_count() const { return m_bitmap_list.size(); } virtual bitmap_info* get_bitmap_info(int i) const { return m_bitmap_list[i].get_ptr(); } virtual void export_resource(const tu_string& symbol, resource* res) // Expose one of our resources under the given symbol, // for export. Other movies can import it. { // SWF sometimes exports the same thing more than once! m_exports.set(symbol, res); } virtual smart_ptr<resource> get_exported_resource(const tu_string& symbol) // Get the named exported resource, if we expose it. // Otherwise return NULL. { smart_ptr<resource> res; m_exports.get(symbol, &res); return res; } virtual void add_import(const char* source_url, int id, const char* symbol) // Adds an entry to a table of resources that need to // be imported from other movies. Client code must // call resolve_import() later, when the source movie // has been loaded, so that the actual resource can be // used. { assert(in_import_table(id) == false); m_imports.push_back(import_info(source_url, id, symbol)); } bool in_import_table(int character_id) // Debug helper; returns true if the given // character_id is listed in the import table. { for (int i = 0, n = m_imports.size(); i < n; i++) { if (m_imports[i].m_character_id == character_id) { return true; } } return false; } virtual void visit_imported_movies(import_visitor* visitor) // Calls back the visitor for each movie that we // import symbols from. { stringi_hash<bool> visited; // ugh! for (int i = 0, n = m_imports.size(); i < n; i++) { import_info& inf = m_imports[i]; if (visited.find(inf.m_source_url) == visited.end()) { // Call back the visitor. visitor->visit(inf.m_source_url.c_str()); visited.set(inf.m_source_url, true); } } } virtual void resolve_import(const char* source_url, movie_definition* source_movie) // Grabs the stuff we want from the source movie. { // @@ should be safe, but how can we verify // it? Compare a member function pointer, or // something? movie_def_impl* def_impl = static_cast<movie_def_impl*>(source_movie); movie_definition_sub* def = static_cast<movie_definition_sub*>(def_impl); // Iterate in reverse, since we remove stuff along the way. for (int i = m_imports.size() - 1; i >= 0; i--) { const import_info& inf = m_imports[i]; if (inf.m_source_url == source_url) { // Do the import.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -