Rev 2110 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* number.cc
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/
#include "number.h"
#include "vector2d.h"
#include "ui_list.h"
#include "multi_curve.h"
#include "tcl_interp.h"
#include <vector>
#include <fstream>
using namespace std;
extern ui_list uis;
number::number () : slw (255), slh (10), sl_red (0, slw, slh), sl_green (0, slw, slh), sl_blue (0, slw, slh) {
name = "Number";
uchar = 'A';
short_ = 666;
int_ = 1729;
float_ = 3.141592;
double_ = 2.71828183;
ucolor.r = 128; ucolor.g = 128; ucolor.b = 255;
type = CHAR;
make_shapeform = 1;
y[1]=1.0f;
y[0]=0.0f;
}
number::~number () {
widget_save ("d_number", ctrls);
save_params ();
}
void number::load_params () {
ifstream f (make_fname().c_str(), ios::in);
string ignore;
f >> ignore >> type;
f >> ignore;
slider<int>* sl [] = {&sl_red, &sl_green, &sl_blue};
int s;
for (int i = 0; i < 3; ++i) {f >> s; sl[i]->set_val (s);}
f >> ignore >> double_;
f >> ignore >> float_;
f >> ignore >> int_;
f >> ignore >> short_;
f >> ignore >> uchar;
float v;
spinner<float>* sp[] = {&sp_0equals, &sp_1equals};
for (int i = 0; i < 2; ++i) {
f >> ignore >> v; sp[i]->set_value (v);
y[i] = v;
}
f >> ignore >> v; sp_scale.set_value (v);
f >> ignore >> make_shapeform; cb_make_shapeform.set_state (make_shapeform);
int w; f >> ignore >> w; cb_wrap.set_state (w);
}
void number::save_params () {
ofstream f (make_fname().c_str(), ios::out);
f << "type " << type << endl;
f << "color " << (int) ucolor.r << ' ' << (int) ucolor.g << ' ' << (int) ucolor.b << endl;
f << "double " << double_ << endl;
f << "float " << float_ << endl;
f << "int " << int_ << endl;
f << "short " << short_ << endl;
f << "char " << (char) uchar << endl;
f << "0_equals " << sp_0equals.value << endl;
f << "1_equals " << sp_1equals.value << endl;
f << "scale " << sp_scale.value << endl;
f << "make_shapeform " << (int) cb_make_shapeform.state << endl;
f << "wrap " << (int) cb_wrap.state << endl;
}
void number::setup () {
plugin::setup ();
ol_bitsof.set_listener (this);
const char* const _types [] = {"char", "short", "int", "float", "double", "colour"};
for (int i = 0, num_types = 6; i < num_types; ++i) types.push_back (_types[i]);
widget* _ctrls [] = {&ol_bitsof, &lf_value, &sp_1equals, &sp_0equals, &sp_scale, &cb_make_shapeform, &bd_bits, &sl_red, &sl_green, &sl_blue, &b_flip, &b_left_shift, &b_right_shift, &cb_wrap};
for (int i = 0; i < 14; ++i) ctrls.push_back (_ctrls[i]);
num_ctrls = ctrls.size ();
button* btn [] = {&b_flip, &b_left_shift, &b_right_shift};
const char* const l[] = {"Flip", "<<", ">>"};
for (int i = 0; i < 3; ++i) {
button* bi = btn[i];
bi->set_text (l[i]);
bi->set_listener (this);
}
cb_wrap.set_text ("Rotate");
b_left_shift.click_repeat = b_right_shift.click_repeat = 1;
slider<int>* sl[] = {&sl_red, &sl_green, &sl_blue};
for (int i = 0; i < 3; ++i) {
slider<int>* si = sl[i];
si->set_limits (0, 255);
si->set_listener (this);
}
unsigned char c = 255, b = 0;
sl_red.set_color (c, b, b);
sl_green.set_color (b, c, b);
sl_blue.set_color (b, b, c);
lf_value.set_label ("Value");
lf_value.set_listener (this);
spinner<float>* spn [] = {&sp_1equals, &sp_0equals};
const char* spnl [] = {"1 = ", "0 = "};
float spnv [] = {1.0f, 0.1f};
for (int i = 0; i < 2; ++i) {
spinner<float>* spi = spn[i];
spi->set (spnl[i], 0.01f, -MILLION, MILLION, this, 0);
spi->set_value (spnv[i]);
}
cb_make_shapeform.set_text ("Make shapeform");
sp_scale.set ("Scale", 0.01f, 0.0f, MILLION, this, 0);
sp_scale.set_value (1.0f);
widget_load ("d_number", ctrls);
bd_bits.lsnr = this;
load_params ();
make_value_from_color ();
set_type (type);
cb_make_shapeform.set_listener (this);
}
void number::render () {
shapeform = cb_make_shapeform.state;
vector<unsigned char>& bits = bd_bits.bits;
int num_bits = bd_bits.num_bits;
points.clear ();
float scale = sp_scale.value;
float cx = 0.5, cy = 0;
if (shapeform) {
extern const float TWO_PI;
float da = TWO_PI / num_bits, hda = da / 2.0;
float pa = -hda, a = 0, na = hda;
float cos_pa = cos(pa), sin_pa = sin(pa);
float cos_na, sin_na;
float cos_a, sin_a;
int pbi = -1, b0 = bits[0], bl = bits[bd_bits.last_bit];
for (int i = 0; i < num_bits; ++i) {
int bi = bits[i];
cos_a = cos(a);
sin_a = sin(a);
float R = scale * y[bi];
float x = cx + R * cos_a;
float y = cy + R * sin_a;
cos_na = cos(na);
sin_na = sin(na);
float xn = cx + R * cos_na;
float yn = cy + R * sin_na;
if (bi != pbi) {
float xp = cx + R * cos_pa;
float yp = cy + R * sin_pa;
points.push_back (point<float>(xp,yp));
}
cos_pa = cos_na;
sin_pa = sin_na;
points.push_back (point<float>(x, y));
points.push_back (point<float>(xn, yn));
a += da;
na += da;
pbi = bi;
}
if (b0 != bl) {
point<float>& p0 = *points.begin ();
points.push_back (p0);
}
} else {
float beat_pos = 0.0f;
float beat = scale / bd_bits.num_bits;
float half_beat = beat / 2.0;
point<float> p0;
for (int i = 0, j = bd_bits.num_bits; i < j; ++i) {
int bi = bits[i];
points.push_back (point<float>(beat_pos, 0.0f));
point<float> pi (beat_pos + half_beat, y[bi]);
points.push_back (pi);
beat_pos += beat;
}
points.push_back (point<float>(beat_pos, 0.0f));
}
ss.clear(); ss.str(""); ss << "number_" << lf_value.fld.text;
gen_pts ();
}
void number::flip () {
vector<unsigned char>& bits = bd_bits.bits;
int num_bits = bd_bits.num_bits;
for (int i = 0; i < num_bits; ++i) bits[i]=!bits[i];
changed (bd_bits);
}
void number::shift (int i, int d) {
vector<unsigned char>& bits = bd_bits.bits;
int j = i;
int n = bd_bits.last_bit;
unsigned char w = bits[i];
for (int m = 0; m < n; ++m) {
int id = i + d;
bits[i]=bits[id];
i = id;
}
int wb = j + d * n;
if (cb_wrap.state) bits[wb] = w; else bits[wb] = 0;
changed (bd_bits);
}
void number::make_value_from_color () {
ucolor.r = sl_red (); ucolor.g = sl_green (); ucolor.b = sl_blue ();
if (type == COLOR) {
ss.clear (); ss.str(""); ss << int(ucolor.r) << spc << int(ucolor.g) << spc << int(ucolor.b);
lf_value.set_text (ss.str());
bd_bits.set (&ucolor, 3);
}
bd_bits.set_color (ucolor.r, ucolor.g, ucolor.b);
}
void number::set_type (int t) {
type = t;
wrap<int> (CHAR, type, COLOR);
ol_bitsof.set_text (" Bits of " + types[type]);
lf_value.fld.expr = 1;
if (type == COLOR) {
make_value_from_color ();
lf_value.fld.expr = 0;
} else if (type == CHAR) {
set_value (uchar);
lf_value.fld.expr = 0;
} else if (type == SHORT) {
set_value (short_);
} else if (type == INT) {
set_value (int_);
} else if (type == FLOAT) {
set_value (float_);
} else if (type == DOUBLE) {
set_value (double_);
}
do_render ();
}
extern tcl_interp interpreter;
string eval_expression (const string& e) {
string cmd ("expr "); cmd += e;
interpreter (cmd);
if (interpreter.result_status == TCL_OK) return interpreter.result; else return ("error");
}
void eval_expression (field& f) {
f.set_text (eval_expression (f.text));
}
void number::reverse (unsigned char* reversed, unsigned char* original, int n) {
for (int i = 0, j = n - 1; i < n; ++i, --j) reversed[i] = original[j];
}
void number::changed (slider<int>& s) {
make_value_from_color ();
do_render ();
}
void number::picked (label& lbl, int dir) {
int t = type + dir;
set_type (t);
}
void number::changed (field& f) {
if (&f == &lf_value.fld) {
if (type == INT) {
eval_expression (f);
int_ = int (f);
int int__ = int_;
set_bit_display (&int__);
} else if (type == FLOAT) {
eval_expression (f);
float_ = float (f);
float float__ = float_;
set_bit_display (&float__);
} else if (type == DOUBLE) {
eval_expression (f);
double_ = double (f);
double double__ = double_;
set_bit_display (&double__);
} else if (type == CHAR) {
if (f.text.length () == 0) {
uchar = 'A';
f.set_text (uchar);
} else uchar = f.text[0];
unsigned char uchar_ = uchar;
set_bit_display (&uchar_);
} else if (type == SHORT) {
eval_expression (f);
short_ = short (f);
short short__ = short_;
set_bit_display (&short__);
} else if (type == COLOR) {
ss.clear (); ss.str(""); ss << f.text;
string comp[3];
for (int i = 0; i < 3; ++i) {
string& ci = comp[i];
ss >> ci;
ci = eval_expression (ci);
}
int sv = 0;
slider<int>* sld[3] = {&sl_red, &sl_green, &sl_blue};
for (int i = 0; i < 3; ++i) {
ss.clear (); ss.str(""); ss << comp[i];
ss >> sv;
sld[i]->set_val (sv); // set slider
}
make_value_from_color ();
}
} else if (&f == &sp_1equals.f_value) {
y[1] = sp_1equals.value;
} else if (&f == &sp_0equals.f_value) {
y[0] = sp_0equals.value;
}
do_render ();
}
void number::changed (bit_display& bd) {
if (type == COLOR) {
bd.get_color (&ucolor);
sl_red.set_val (ucolor.r); sl_green.set_val (ucolor.g); sl_blue.set_val (ucolor.b);
make_value_from_color ();
} else if (type == CHAR) {
bd.get_data (&uchar);
if (uchar > 31 && uchar < 127) set_value_ (uchar);
} else if (type == SHORT) {
bd.get_data (&short_);
set_value_ (short_);
} else if (type == INT) {
bd.get_data (&int_);
set_value_ (int_);
} else if (type == FLOAT) {
bd.get_data (&float_);
set_value_ (float_);
} else if (type == DOUBLE) {
bd.get_data (&double_);
set_value_ (double_);
}
do_render ();
}
void number::changed (checkbutton& cb) {
if (&cb == &cb_make_shapeform) do_render ();
else return plugin::changed (cb);
}
void number::clicked (button& b) {
if (&b == &b_flip) {
flip ();
} else if (&b == &b_left_shift) {
shift (0, +1);
} else if (&b == &b_right_shift) {
shift (bd_bits.last_bit, -1);
} else plugin::clicked (b);
}