//############################################################################ // // LaserBoy !!! // // by James Lehman // Extra Stimulus Inc. // james@akrobiz.com // // began: October 2003 // // Copyright 2003 to 2025 James Lehman. // This source is distributed under the terms of the GNU General Public License. // // LaserBoy_frame_set.hpp is part of LaserBoy. // // LaserBoy is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // LaserBoy is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with LaserBoy. If not, see . // //############################################################################ #ifndef __LASERBOY_FRAME_SET_DEFINITIONS__ #define __LASERBOY_FRAME_SET_DEFINITIONS__ //############################################################################ #include "LaserBoy_frame.hpp" //############################################################################ class LaserBoy_frame_set : public vector { public: LaserBoy_frame_set() : vector() , p_frame_set (this) , frame_set_error (LASERBOY_OK) , num_2D_frames ( 0) , num_3D_frames ( 0) , frame_index ( 0) , frame_select_start (-1) , frame_select_end (-1) , null_frame () , ild_file_GUID ("--------") { null_frame.palette_index = LASERBOY_ILDA_DEFAULT; null_frame.push_back(LaserBoy_vertex(0, 0, 0, 255, 255, 255, 64, 55)); null_frame.push_back(LaserBoy_vertex(0, 0, 0, 255, 255, 255, 64, 55)); null_frame.is_2D(); null_frame.quantity = null_frame.size(); null_frame.shrink_to_fit(); } //------------------------------------------------------------------------ LaserBoy_frame_set(const LaserBoy_frame_set& fs) : vector() , p_frame_set (this) , frame_set_error (fs.frame_set_error) , num_2D_frames (fs.num_2D_frames) , num_3D_frames (fs.num_3D_frames) , frame_index (fs.frame_index) , frame_select_start (fs.frame_select_start) , frame_select_end (fs.frame_select_end) , null_frame () , ild_file_GUID (fs.ild_file_GUID) { null_frame.palette_index = LASERBOY_ILDA_DEFAULT; null_frame.push_back(LaserBoy_vertex(0, 0, 0, 255, 255, 255, 64, 55)); null_frame.push_back(LaserBoy_vertex(0, 0, 0, 255, 255, 255, 64, 55)); null_frame.is_2D(); null_frame.quantity = null_frame.size(); null_frame.shrink_to_fit(); clear(); reserve(fs.size()); insert(begin(), fs.begin(), fs.end()); } //------------------------------------------------------------------------ LaserBoy_frame_set(const LaserBoy_real_segment_set& rss) : vector() , p_frame_set (this) , frame_set_error (rss.real_segment_set_error) , frame_index (rss.frame_index) , frame_select_start (rss.frame_select_start) , frame_select_end (rss.frame_select_end) , null_frame () , ild_file_GUID ("--------") { LaserBoy_frame frame; null_frame.palette_index = LASERBOY_ILDA_DEFAULT; null_frame.push_back(LaserBoy_vertex(0, 0, 0, 255, 255, 255, 64, 55)); null_frame.push_back(LaserBoy_vertex(0, 0, 0, 255, 255, 255, 64, 55)); null_frame.is_2D(); null_frame.quantity = null_frame.size(); null_frame.shrink_to_fit(); reserve(rss.size()); for(size_t i = 0; i < rss.size(); i++) { frame = rss[i]; push_back(frame); } count_frames(); } //------------------------------------------------------------------------ ~LaserBoy_frame_set() {} //------------------------------------------------------------------------ LaserBoy_frame& frame(int index) //sets frame_index { if(size()) { if(index < 0) index = size() - 1; else if(index >= (int)size()) index = 0; frame_index = index; return at(frame_index); } return null_frame; } //------------------------------------------------------------------------ LaserBoy_frame& next_frame() //sets frame_index { if(size()) { frame_index++; if(frame_index >= size()) frame_index = 0; return at(frame_index); } return null_frame; } //------------------------------------------------------------------------ LaserBoy_frame& previous_frame() //sets frame_index { if(size()) { if(frame_index == 0) frame_index = size() - 1; else frame_index--; return at(frame_index); } return null_frame; } //------------------------------------------------------------------------ LaserBoy_frame& frame_picker(int index) // does not set frame_index { if(size()) { if(index < 0) index = size() - 1; else if(index >= (int)size()) index = 0; return at(index); } return null_frame; } //------------------------------------------------------------------------ LaserBoy_frame& current_frame() { if(size()) return at(frame_index); return null_frame; } //------------------------------------------------------------------------ void delete_current_frame() { if(size() > 1) { erase(begin() + frame_index); if(frame_index > 0) frame_index--; } else { clear(); push_back(null_frame); } normalize_cursors(); return; } //------------------------------------------------------------------------ void delete_frame(u_int index) { if(size() > 1) { if(index < size()) { erase(begin() + index); if(frame_index >= index) { if(frame_index == 0) frame_index = size() - 1; else frame_index--; } } } else { clear(); push_back(null_frame); } normalize_cursors(); return; } //------------------------------------------------------------------------ void copy_frame() { insert(begin() + frame_index, frame_picker(frame_index)); frame_index++; return; } //------------------------------------------------------------------------ void new_frame() { insert(begin() + frame_index, LaserBoy_frame()); //frame_index++; return; } //------------------------------------------------------------------------ void push_back_frame(const LaserBoy_frame& frame) { push_back(frame); return; } //------------------------------------------------------------------------ void count_frames() { num_2D_frames = num_3D_frames = 0; for(size_t i = 0; i < size(); i++) at(i).is_2D() ? num_2D_frames++ : num_3D_frames++; return; } //------------------------------------------------------------------------ int total_vertices() const { size_t i, vertices = 0; for(i = 0; i < size(); i++) vertices += (at(i).size()); return vertices; } //------------------------------------------------------------------------ LaserBoy_frame& pre_incr_current_frame() { if(size()) { frame_index++; if(frame_index >= size()) frame_index = 0; return at(frame_index); } return null_frame; } //------------------------------------------------------------------------ LaserBoy_frame& pre_decr_current_frame() { if(size()) { if(frame_index == 0) frame_index = size() - 1; else frame_index--; return at(frame_index); } return null_frame; } //------------------------------------------------------------------------ LaserBoy_frame& post_incr_current_frame(int) { if(size()) { u_int frame_return = frame_index; frame_index++; if(frame_index >= size()) frame_index = 0; return at(frame_return); } return null_frame; } //------------------------------------------------------------------------ LaserBoy_frame& post_decr_current_frame(int) { if(size()) { u_int frame_return = frame_index; if(frame_index == 0) frame_index = size() - 1; else frame_index--; return at(frame_return); } return null_frame; } //------------------------------------------------------------------------ LaserBoy_frame_set& operator = (const LaserBoy_frame_set& fs) { clear(); reserve(fs.size()); insert(begin(), fs.begin(), fs.end()); frame_set_error = fs.frame_set_error; frame_index = fs.frame_index; frame_select_start = fs.frame_select_start; frame_select_end = fs.frame_select_end; num_2D_frames = fs.num_2D_frames; num_3D_frames = fs.num_3D_frames; ild_file_GUID = fs.ild_file_GUID; shrink_to_fit(); return *this; } //------------------------------------------------------------------------ LaserBoy_frame_set& operator = (const LaserBoy_real_segment_set& rss) { LaserBoy_frame frame; frame_set_error = rss.real_segment_set_error; frame_index = rss.frame_index; frame_select_start = rss.frame_select_start; frame_select_end = rss.frame_select_end; clear(); reserve(rss.size()); for(size_t i = 0; i < rss.size(); i++) { frame = rss[i]; push_back(frame); } count_frames(); shrink_to_fit(); return *this; } //------------------------------------------------------------------------ LaserBoy_frame_set& operator += (const LaserBoy_real_segment_set& rss) { LaserBoy_frame frame; for(size_t i = 0; i < rss.size(); i++) { frame = rss[i]; push_back(frame); } count_frames(); return *this; } //------------------------------------------------------------------------ LaserBoy_frame_set& operator += (const LaserBoy_frame_set& frames) { reserve(size() + frames.size()); insert(end(), frames.begin(), frames.end()); count_frames(); shrink_to_fit(); return *this; } //------------------------------------------------------------------------ LaserBoy_frame_set& operator = (const LaserBoy_frame& frame) { clear(); frame_select_start = -1; frame_select_end = -1; push_back(frame); count_frames(); return *this; } //------------------------------------------------------------------------ LaserBoy_frame_set& operator += (const LaserBoy_frame& frame); //------------------------------------------------------------------------ LaserBoy_frame_set& operator += (const LaserBoy_segment& segment) { LaserBoy_ild_header header; header.format = segment.is_2D(); push_back(LaserBoy_frame(header, segment)); count_frames(); shrink_to_fit(); return *this; } //------------------------------------------------------------------------ LaserBoy_frame_set selected_frames() { LaserBoy_frame_set selected; for(size_t i = 0; i < size(); i++) if(at(i).is_selected) selected.push_back(at(i)); return selected; } //------------------------------------------------------------------------ LaserBoy_frame_set operator + (const LaserBoy_frame_set& frames) const { LaserBoy_frame_set sum(*this); sum += frames; sum.count_frames(); return sum; } //------------------------------------------------------------------------ LaserBoy_frame& operator [] (u_int index) // does not set frame_index { if(size()) { if(index >= size()) index = 0; return at(index); } return null_frame; } //------------------------------------------------------------------------ LaserBoy_frame selected_frame_index(u_int index) { if(size()) { u_int selected_count = 0, i; if(index < size()) { for(i = 0; i < size(); i++) { if(at(i).is_selected) { if(index == selected_count) return at(i); selected_count++; } } } } return null_frame; } //------------------------------------------------------------------------ LaserBoy_segment sum_of_frames() { bool same_palettes = true; size_t i; LaserBoy_segment segment(front().palette_index, false); for(i = 1; i < size(); i++) if(segment.palette_index != at(i).palette_index) { same_palettes = false; break; } if(!same_palettes) { segment.promote_to_true_color(); promote_to_true_color(); } for(i = 0; i < size(); i++) segment += at(i); return segment; } //------------------------------------------------------------------------ size_t number_of_frames() const { return size(); } //------------------------------------------------------------------------ int index_of_name(const string& name) const { for(int i = 0; i < (int)size(); i++) if(at(i).name == name) return i; return -1; } //------------------------------------------------------------------------ int number_of_selected_frames() const { int selected_count = 0; for(int i = 0; i < (int)size(); i++) if(at(i).is_selected) selected_count++; return selected_count; } //------------------------------------------------------------------------ int number_of_ild_color_tables() const { int true_color_count = 0; for(int i = 0; i < (int)size(); i++) if(at(i).palette_index == LASERBOY_TRUE_COLOR) true_color_count++; return true_color_count; } //------------------------------------------------------------------------ int number_of_ild_palettes() const { int palette_count = 0; bool in_true_color = false, default_palette_needed = false; for(int i = 0; i < (int)size(); i++) { if(at(i).palette_index == LASERBOY_TRUE_COLOR) { if(!in_true_color) { palette_count++; in_true_color = true; default_palette_needed = true; } } else if(at(i).palette_index != LASERBOY_ILDA_DEFAULT) { palette_count++; in_true_color = false; default_palette_needed = true; } else if(default_palette_needed) { palette_count++; default_palette_needed = false; } } return palette_count; } //------------------------------------------------------------------------ bool font_index_to_frames (const string& utf8_path, string& report, bool cleanup = false ); LaserBoy_Error_Code get_unicode_index (u32string& characters); bool save_utf8_frame_index (const string& utf8_path, string& report, bool cleanup = false ); LaserBoy_Error_Code order_frames_by_name (string& report, bool cleanup = false ); //------------------------------------------------------------------------ void render_frame (const int& index, struct LaserBoy_bmp *bmp ) const ; //------------------------------------------------------------------------ u_short max_dimension () const ; double relative_volume () const ; double relative_volume_to_origin () const ; size_t closest_x_to_edge () const ; size_t closest_y_to_edge () const ; size_t closest_z_to_edge () const ; int frame_set_palette_index () ; bool true_color_frames () ; //------------------------------------------------------------------------ LaserBoy_frame_set& reverse (); LaserBoy_frame_set& make_current_first (); LaserBoy_frame_set& swap_frames (int i, int j); LaserBoy_frame_set& reverse_selected (); LaserBoy_frame_set& random_order (); LaserBoy_frame_set& frame_reverse (); //------------------------------------------------------------------------ LaserBoy_frame_set& center_x (bool individually = false); LaserBoy_frame_set& center_y (bool individually = false); LaserBoy_frame_set& center_z (bool individually = false); LaserBoy_frame_set& center (bool individually = false); //------------------------------------------------------------------------ LaserBoy_frame_set& normalize (double scale); LaserBoy_frame_set& normalize_vectors (double scale); LaserBoy_frame_set& normalize_vectors_with_origin (double scale); //------------------------------------------------------------------------ LaserBoy_real_segment_set to_real_segment_set (bool add_origin) const ; //------------------------------------------------------------------------ bool from_nothing (); //------------------------------------------------------------------------ LaserBoy_Error_Code from_ild_file (const string& file); //------------------------------------------------------------------------ LaserBoy_Error_Code from_ild_file (const string& file, long int& bytes_skipped, LaserBoy_ild_header_count& counter ); //------------------------------------------------------------------------ LaserBoy_Error_Code from_txt_file (const string& file, bool append = false ); //------------------------------------------------------------------------ LaserBoy_Error_Code from_ctn_file (const string& file, long int& bytes_skipped ); //------------------------------------------------------------------------ void superimpose_frame_set (LaserBoy_frame_set& overlay); //------------------------------------------------------------------------ LaserBoy_Error_Code superimpose_from_txt_file (const string& file, int &new_frame_count, int &new_palette_count ); //------------------------------------------------------------------------ LaserBoy_Error_Code from_dxf_file (const string& file, bool append = false ); //------------------------------------------------------------------------ bool from_dxf_directory (const string& file, bool append = false ); //------------------------------------------------------------------------ LaserBoy_Error_Code from_dxf_font (const string& file, bool append = false ); //------------------------------------------------------------------------ LaserBoy_Error_Code from_ifstream_ild (std::ifstream& in, long int& bytes_skipped, LaserBoy_ild_header_count& counter ); //------------------------------------------------------------------------ LaserBoy_Error_Code from_ifstream_ctn (std::ifstream& in, long int& bytes_skipped ); //------------------------------------------------------------------------ bool from_LaserBoy_wav_file (const string& file, bool append = false ); //------------------------------------------------------------------------ bool from_qm_wav_file (const string& file, bool global_polarity, bool append = false ); //------------------------------------------------------------------------ bool from_unformatted_wav_file (const string& file, bool global_polarity, bool append = false ); //------------------------------------------------------------------------ bool from_headerless_LB_wav_file (const string& file, bool global_polarity, bool append = false ); //------------------------------------------------------------------------ LaserBoy_Error_Code from_fstream_LaserBoy_wav (LaserBoy_wav_header header, std::fstream& in, bool append = false ); //------------------------------------------------------------------------ LaserBoy_Error_Code from_fstream_qm_wav (LaserBoy_wav_header header, std::fstream& in, bool global_polarity, bool append = false ); //------------------------------------------------------------------------ LaserBoy_Error_Code from_fstream_unformatted_wav (LaserBoy_wav_header header, std::fstream& in, bool global_polarity, bool append = false ); //------------------------------------------------------------------------ LaserBoy_Error_Code from_fstream_headerless_LB_wav (LaserBoy_wav_header header, std::fstream& in, bool global_polarity, bool append = false ); //------------------------------------------------------------------------ void normalize_cursors() { if(frame_index >= size()) frame_index = 0; if(frame_select_start >= (int)size()) frame_select_start = -1; if(frame_select_end >= (int)size()) frame_select_end = -1; } //------------------------------------------------------------------------ bool is_ild_busted ( ) ; bool is_2D (bool silent = false ) ; void flatten_z ( ) ; void flat_to_2D ( ) ; void z_order_vertices (unsigned short span ) ; void unblank_all_vertices ( ) ; void convert_black_to_blank ( ) ; void convert_black_to_color ( ) ; void convert_blank_to_black ( ) ; void impose_black_level ( ) ; void reduce_blank_vectors ( ) ; void remove_dots ( ) ; //------------------------------------------------------------------------ LaserBoy_Error_Code enhance_dots ( ) ; //------------------------------------------------------------------------ void remove_dwell_vertices ( ) ; void remove_short_vectors ( ) ; void reduce_lit_vectors ( ) ; void minimize ( ) ; void to_dots ( ) ; void impose_bit_resolution ( ) ; void explode_current_frame ( ) ; void explode_all_frames ( ) ; //------------------------------------------------------------------------ LaserBoy_Error_Code collapse_selected_frames( ) ; //------------------------------------------------------------------------ void delete_every_nth_frame (unsigned short n ) ; void keep_every_nth_frame (unsigned short n ) ; //------------------------------------------------------------------------ LaserBoy_Error_Code fracture_segments ( ) ; //------------------------------------------------------------------------ void omit_equivalent_vectors ( ) ; //------------------------------------------------------------------------ LaserBoy_Error_Code bond_segments ( ) ; LaserBoy_Error_Code reorder_segments( ) ; //------------------------------------------------------------------------ void randomize_segments ( ) ; void conglomerate_lit_segments ( ) ; //------------------------------------------------------------------------ LaserBoy_Error_Code add_dwell ( ) ; LaserBoy_Error_Code add_lit_span_vertices ( ) ; LaserBoy_Error_Code add_blank_span_vertices( ) ; //------------------------------------------------------------------------ void delete_redundant_frames ( ) ; //------------------------------------------------------------------------ LaserBoy_Error_Code optimize ( ) ; LaserBoy_Error_Code color_from_bmp (const string& file ) ; void color_from_bmp (struct LaserBoy_bmp* bmp) ; LaserBoy_Error_Code subtract_bmp (const string& file ) ; void subtract_bmp (struct LaserBoy_bmp* bmp) ; //------------------------------------------------------------------------ void sync_rgb_and_palette ( ) ; //------------------------------------------------------------------------ void index_palette ( ) ; void index_segments_palette ( ) ; void span_palette ( ) ; void span_x_palette ( ) ; void span_y_palette ( ) ; void span_z_palette ( ) ; void span_radial_palette ( ) ; void span_axial_palette ( ) ; void span_segments_palette ( ) ; void random_color_vectors_palette ( ) ; void random_color_segments_palette ( ) ; //------------------------------------------------------------------------ void index_hues ( ) ; void index_segments_hues ( ) ; void span_hues ( ) ; void span_x_hues ( ) ; void span_y_hues ( ) ; void span_z_hues ( ) ; void span_radial_hues ( ) ; void span_axial_hues ( ) ; void span_segments_hues ( ) ; void random_color_vectors_hues ( ) ; void random_color_segments_hues ( ) ; //------------------------------------------------------------------------ void quarter_turn (u_int plane, u_int turns) ; double max_distance_from_origin ( ) const ; double max_distance_from_origin_xy ( ) const ; double max_distance_from_origin_zy ( ) const ; double min_distance_from_origin ( ) const ; double min_distance_from_origin_xy ( ) const ; //------------------------------------------------------------------------ LaserBoy_Bounds apply_view ( ) ; LaserBoy_Bounds scale_around_origin (LaserBoy_3D_double f ) ; LaserBoy_Bounds scale_around_origin ( ) ; LaserBoy_Bounds rotate_around_origin (LaserBoy_3D_double f ) ; LaserBoy_Bounds rotate_around_origin ( ) ; LaserBoy_Bounds move (LaserBoy_3D_double f ) ; LaserBoy_Bounds move ( ) ; //------------------------------------------------------------------------ void toggle_frame_select_start ( ) ; void toggle_frame_select_end ( ) ; void invert_frame_selections ( ) ; void delete_selected_frames ( ) ; void trim_to_selected_frames ( ) ; void bit_reduce_to_palette ( ) ; void best_reduce_to_palette ( ) ; void best_reduce_all_to_palette ( ) ; void promote_to_true_color ( ) ; void best_match_palette (u_int index ) ; void best_match_target_palette ( ) ; void strip_color ( ) ; void strip_color_or ( ) ; void strip_color_avg ( ) ; void to_palette_by_index (u_int index ) ; void to_target_palette_by_index ( ) ; void flip (int plane ) ; void renumber ( ) ; bool save_as_ild (const string& file, LaserBoy_ild_header_count& counter); bool save_as_ctn (const string& file ) ; bool save_as_txt (const string& file ) ; void to_ofstream_ild (std::ofstream& out, LaserBoy_ild_header_count& counter); void to_ofstream_ctn (std::ofstream& out ) ; void to_ofstream_txt (std::ofstream& out ) ; //------------------------------------------------------------------------ bool save_as_wav (const string& file, bool optimized, bool timed ) ; //------------------------------------------------------------------------ void to_fstream_wav (std::fstream& out, bool optimized, bool timed ) ; //------------------------------------------------------------------------ void save_as_bmp_directory (const string& dir, const string& name ) const ; //------------------------------------------------------------------------ void save_as_bmp_view (u_int frame_index, const string& file ) const ; //------------------------------------------------------------------------ void save_as_bmp_directory_view (const string& dir, const string& name ) const ; //------------------------------------------------------------------------ bool save_as_dxf_directory (const string& dir, const string& name ) const ; //------------------------------------------------------------------------ LaserBoy_frame_set* p_frame_set ; LaserBoy_Error_Code frame_set_error ; u_int num_2D_frames , num_3D_frames , frame_index ; int frame_select_start, frame_select_end ; LaserBoy_frame null_frame ; string ild_file_GUID ; }; //############################################################################ typedef LaserBoy_Bounds(*LaserBoy_frame_effect) (LaserBoy_frame* ); // function prototyes typedef LaserBoy_Bounds(*LaserBoy_selected_frames_effect) (LaserBoy_frame_set*); typedef LaserBoy_Bounds(*LaserBoy_frame_set_effect) (LaserBoy_frame_set*); //############################################################################ #endif //############################################################################ ////////////////////////////////////////////////////////////////////////////// //############################################################################