//############################################################################
//
// LaserBoy !!!
//
// by James Lehman
// Extra Stimulus Inc.
// james@akrobiz.com
//
// began: October 2003
//
// Copyright 2003 to 2024 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
//############################################################################
//////////////////////////////////////////////////////////////////////////////
//############################################################################