Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py94
-rw-r--r--source/blender/blenkernel/BKE_particle.h14
-rw-r--r--source/blender/blenkernel/intern/particle.c84
-rw-r--r--source/blender/blenloader/intern/versioning_280.c10
-rw-r--r--source/blender/makesdna/DNA_particle_types.h28
-rw-r--r--source/blender/makesrna/intern/rna_particle.c115
6 files changed, 15 insertions, 330 deletions
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index c85b8004808..3d25829c3d2 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -1480,98 +1480,6 @@ class PARTICLE_PT_render_collection_use_count(ParticleButtonsPanel, Panel):
row.prop(weight, "count")
-class PARTICLE_PT_render_billboards_alignment(ParticleButtonsPanel, Panel):
- bl_label = "Billboard Alignment"
- bl_parent_id = "PARTICLE_PT_render"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- part = particle_get_settings(context)
- return part.render_type == 'BILLBOARD'
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- part = particle_get_settings(context)
-
- col = layout.column()
-
- col.prop(part, "billboard_align", text="Align To")
- col.prop(part, "lock_billboard", text="Lock Axis")
- col.prop(part, "billboard_object")
-
-
-class PARTICLE_PT_render_billboards_tilt(ParticleButtonsPanel, Panel):
- bl_label = "Billboard Tilt"
- bl_parent_id = "PARTICLE_PT_render"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- part = particle_get_settings(context)
- return part.render_type == 'BILLBOARD'
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- part = particle_get_settings(context)
-
- col = layout.column()
-
- sub = col.column(align=True)
- sub.prop(part, "billboard_tilt", text="Angle", slider=True)
- sub.prop(part, "billboard_tilt_random", text="Random", slider=True)
-
- sub = col.column(align=True)
- sub.prop(part, "billboard_offset")
- col.prop(part, "billboard_size", text="Scale")
- if part.billboard_align == 'VEL':
- col = col.column(align=True)
- col.prop(part, "billboard_velocity_head", text="Velocity ScaleHead")
- col.prop(part, "billboard_velocity_tail", text="Tail")
-
-
-class PARTICLE_PT_render_billboards_uv(ParticleButtonsPanel, Panel):
- bl_label = "Billboard UVs"
- bl_parent_id = "PARTICLE_PT_render"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- part = particle_get_settings(context)
- return part.render_type == 'BILLBOARD'
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- psys = context.particle_system
- ob = context.object
- part = particle_get_settings(context)
-
- col = layout.column()
-
- if psys:
- col.prop_search(psys, "billboard_normal_uv", ob.data, "uv_layers")
- col.prop_search(psys, "billboard_time_index_uv", ob.data, "uv_layers")
-
- col.prop(part, "billboard_uv_split", text="Split UVs")
-
- if psys:
- sub = col.column()
- sub.active = part.billboard_uv_split > 1
- sub.prop_search(psys, "billboard_split_uv", ob.data, "uv_layers")
-
- sub.prop(part, "billboard_animation")
- sub.prop(part, "billboard_offset_split")
-
-
class PARTICLE_PT_render_trails(ParticleButtonsPanel, Panel):
bl_label = "Trails"
bl_parent_id = "PARTICLE_PT_render"
@@ -2186,8 +2094,6 @@ classes = (
PARTICLE_PT_render_object,
PARTICLE_PT_render_collection,
PARTICLE_PT_render_collection_use_count,
- PARTICLE_PT_render_billboards_tilt,
- PARTICLE_PT_render_billboards_uv,
PARTICLE_PT_render_trails,
PARTICLE_PT_render_extra,
PARTICLE_PT_draw,
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 19036e63a8c..56f64829eb1 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -172,19 +172,6 @@ typedef struct ParticleTask {
int begin, end;
} ParticleTask;
-typedef struct ParticleBillboardData {
- struct Object *ob;
- float vec[3], vel[3];
- float offset[2];
- float size[2];
- float tilt, random, time;
- int uv[3];
- int lock, num;
- int totnum;
- int lifetime;
- short align, uv_split, anim, split_offset;
-} ParticleBillboardData;
-
typedef struct ParticleCollisionElement {
/* pointers to original data */
float *x[3], *v[3];
@@ -391,7 +378,6 @@ void psys_thread_context_free(struct ParticleThreadContext *ctx);
void psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int endpart, struct ParticleTask **r_tasks, int *r_numtasks);
void psys_tasks_free(struct ParticleTask *tasks, int numtasks);
-void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
void psys_apply_hair_lattice(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
/* particle_system.c */
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index da2975d8efc..bdf0b239917 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -3150,8 +3150,6 @@ static void default_particle_settings(ParticleSettings *part)
part->draw_as = PART_DRAW_REND;
part->ren_as = PART_DRAW_HALO;
part->bb_uv_split = 1;
- part->bb_align = PART_BB_VIEW;
- part->bb_split_offset = PART_BB_OFF_LINEAR;
part->flag = PART_EDISTR | PART_TRAND | PART_HIDE_ADVANCED_HAIR;
part->sta = 1.0;
@@ -4207,88 +4205,6 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa
*scale = len;
}
-void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3])
-{
- float onevec[3] = {0.0f, 0.0f, 0.0f}, tvec[3], tvec2[3];
-
- xvec[0] = 1.0f; xvec[1] = 0.0f; xvec[2] = 0.0f;
- yvec[0] = 0.0f; yvec[1] = 1.0f; yvec[2] = 0.0f;
-
- /* can happen with bad pointcache or physics calculation
- * since this becomes geometry, nan's and inf's crash raytrace code.
- * better not allow this. */
- if (!is_finite_v3(bb->vec) || !is_finite_v3(bb->vec)) {
- zero_v3(bb->vec);
- zero_v3(bb->vel);
-
- zero_v3(xvec);
- zero_v3(yvec);
- zero_v3(zvec);
- zero_v3(center);
-
- return;
- }
-
- if (bb->align < PART_BB_VIEW)
- onevec[bb->align] = 1.0f;
-
- if (bb->lock && (bb->align == PART_BB_VIEW)) {
- normalize_v3_v3(xvec, bb->ob->obmat[0]);
- normalize_v3_v3(yvec, bb->ob->obmat[1]);
- normalize_v3_v3(zvec, bb->ob->obmat[2]);
- }
- else if (bb->align == PART_BB_VEL) {
- float temp[3];
-
- normalize_v3_v3(temp, bb->vel);
-
- sub_v3_v3v3(zvec, bb->ob->obmat[3], bb->vec);
-
- if (bb->lock) {
- float fac = -dot_v3v3(zvec, temp);
-
- madd_v3_v3fl(zvec, temp, fac);
- }
- normalize_v3(zvec);
-
- cross_v3_v3v3(xvec, temp, zvec);
- normalize_v3(xvec);
-
- cross_v3_v3v3(yvec, zvec, xvec);
- }
- else {
- sub_v3_v3v3(zvec, bb->ob->obmat[3], bb->vec);
- if (bb->lock)
- zvec[bb->align] = 0.0f;
- normalize_v3(zvec);
-
- if (bb->align < PART_BB_VIEW)
- cross_v3_v3v3(xvec, onevec, zvec);
- else
- cross_v3_v3v3(xvec, bb->ob->obmat[1], zvec);
- normalize_v3(xvec);
-
- cross_v3_v3v3(yvec, zvec, xvec);
- }
-
- copy_v3_v3(tvec, xvec);
- copy_v3_v3(tvec2, yvec);
-
- mul_v3_fl(xvec, cosf(bb->tilt * (float)M_PI));
- mul_v3_fl(tvec2, sinf(bb->tilt * (float)M_PI));
- add_v3_v3(xvec, tvec2);
-
- mul_v3_fl(yvec, cosf(bb->tilt * (float)M_PI));
- mul_v3_fl(tvec, -sinf(bb->tilt * (float)M_PI));
- add_v3_v3(yvec, tvec);
-
- mul_v3_fl(xvec, bb->size[0]);
- mul_v3_fl(yvec, bb->size[1]);
-
- madd_v3_v3v3fl(center, bb->vec, xvec, bb->offset[0]);
- madd_v3_v3fl(center, yvec, bb->offset[1]);
-}
-
void psys_apply_hair_lattice(Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys)
{
ParticleSimulationData sim = {0};
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index b0b389c6c2d..71341b47c6e 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -2910,5 +2910,15 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
/* Versioning code until next subversion bump goes here. */
+
+ LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) {
+ /* Replace deprecated PART_DRAW_BB by PART_DRAW_NOT */
+ if (part->ren_as == PART_DRAW_BB) {
+ part->ren_as = PART_DRAW_NOT;
+ }
+ if (part->draw_as == PART_DRAW_BB) {
+ part->draw_as = PART_DRAW_NOT;
+ }
+ }
}
}
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index dc6e9dd05a1..68bc79d4543 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -206,8 +206,8 @@ typedef struct ParticleSettings {
short kink, kink_axis;
/* billboards */
- short bb_align, bb_uv_split, bb_anim, bb_split_offset;
- float bb_tilt, bb_rand_tilt, bb_offset[2], bb_size[2], bb_vel_head, bb_vel_tail;
+ short bb_align, bb_uv_split, bb_anim, bb_split_offset DNA_DEPRECATED;
+ float bb_tilt, bb_rand_tilt, bb_offset[2], bb_size[2], bb_vel_head, bb_vel_tail DNA_DEPRECATED;
/* draw color */
float color_vec_max;
@@ -362,7 +362,7 @@ typedef struct ParticleSystem {
char _pad1[6];
/** Billboard uv name, MAX_CUSTOMDATA_LAYER_NAME. */
- char bb_uvname[3][64];
+ char bb_uvname[3][64] DNA_DEPRECATED;
/* if you change these remember to update array lengths to PSYS_TOT_VG! */
/** Vertex groups, 0==disable, 1==starting index. */
@@ -412,7 +412,7 @@ typedef enum eParticleDrawFlag {
PART_DRAW_HEALTH = (1 << 4),
PART_ABS_PATH_TIME = (1 << 5),
PART_DRAW_COUNT_GR = (1 << 6),
- PART_DRAW_BB_LOCK = (1 << 7), /* used with billboards */
+ PART_DRAW_BB_LOCK = (1 << 7), /* used with billboards */ /* DEPRECATED */
PART_DRAW_ROTATE_OB = (1 << 7), /* used with instance object/collection */
PART_DRAW_PARENT = (1 << 8),
PART_DRAW_NUM = (1 << 9),
@@ -530,24 +530,6 @@ typedef enum eParticleShapeFlag {
/* part->time_flag */
#define PART_TIME_AUTOSF 1 /* Automatic subframes */
-/* part->bb_align */
-#define PART_BB_X 0
-#define PART_BB_Y 1
-#define PART_BB_Z 2
-#define PART_BB_VIEW 3
-#define PART_BB_VEL 4
-
-/* part->bb_anim */
-#define PART_BB_ANIM_NONE 0
-#define PART_BB_ANIM_AGE 1
-#define PART_BB_ANIM_ANGLE 2
-#define PART_BB_ANIM_FRAME 3
-
-/* part->bb_split_offset */
-#define PART_BB_OFF_NONE 0
-#define PART_BB_OFF_LINEAR 1
-#define PART_BB_OFF_RANDOM 2
-
/* part->draw_as */
/* part->ren_as*/
#define PART_DRAW_NOT 0
@@ -560,7 +542,7 @@ typedef enum eParticleShapeFlag {
#define PART_DRAW_PATH 6
#define PART_DRAW_OB 7
#define PART_DRAW_GR 8
-#define PART_DRAW_BB 9
+#define PART_DRAW_BB 9 /* deprecated */
#define PART_DRAW_REND 10
/* part->integrator */
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 4e1a539fe69..57533862c99 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -108,7 +108,6 @@ static const EnumPropertyItem part_ren_as_items[] = {
{PART_DRAW_PATH, "PATH", 0, "Path", ""},
{PART_DRAW_OB, "OBJECT", 0, "Object", ""},
{PART_DRAW_GR, "COLLECTION", 0, "Collection", ""},
- {PART_DRAW_BB, "BILLBOARD", 0, "Billboard", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -2062,30 +2061,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
- static const EnumPropertyItem bb_align_items[] = {
- {PART_BB_X, "X", 0, "X", ""},
- {PART_BB_Y, "Y", 0, "Y", ""},
- {PART_BB_Z, "Z", 0, "Z", ""},
- {PART_BB_VIEW, "VIEW", 0, "View", ""},
- {PART_BB_VEL, "VEL", 0, "Velocity", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem bb_anim_items[] = {
- {PART_BB_ANIM_NONE, "NONE", 0, "None", ""},
- {PART_BB_ANIM_AGE, "AGE", 0, "Age", ""},
- {PART_BB_ANIM_FRAME, "FRAME", 0, "Frame", ""},
- {PART_BB_ANIM_ANGLE, "ANGLE", 0, "Angle", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem bb_split_offset_items[] = {
- {PART_BB_OFF_NONE, "NONE", 0, "None", ""},
- {PART_BB_OFF_LINEAR, "LINEAR", 0, "Linear", ""},
- {PART_BB_OFF_RANDOM, "RANDOM", 0, "Random", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
static const EnumPropertyItem draw_col_items[] = {
{PART_DRAW_COL_NONE, "NONE", 0, "None", ""},
{PART_DRAW_COL_MAT, "MATERIAL", 0, "Material", ""},
@@ -2481,79 +2456,12 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Axis", "Which axis to use for offset");
RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
- /* billboards */
- prop = RNA_def_property(srna, "lock_billboard", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_BB_LOCK);
- RNA_def_property_ui_text(prop, "Lock Billboard", "Lock the billboards align axis");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_align", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "bb_align");
- RNA_def_property_enum_items(prop, bb_align_items);
- RNA_def_property_ui_text(prop, "Align to", "In respect to what the billboards are aligned");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_uv_split", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "bb_uv_split");
- RNA_def_property_range(prop, 1, 100);
- RNA_def_property_ui_range(prop, 1, 10, 1, -1);
- RNA_def_property_ui_text(prop, "UV Split", "Number of rows/columns to split UV coordinates for billboards");
-
- prop = RNA_def_property(srna, "billboard_animation", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "bb_anim");
- RNA_def_property_enum_items(prop, bb_anim_items);
- RNA_def_property_ui_text(prop, "Animate", "How to animate billboard textures");
-
- prop = RNA_def_property(srna, "billboard_offset_split", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "bb_split_offset");
- RNA_def_property_enum_items(prop, bb_split_offset_items);
- RNA_def_property_ui_text(prop, "Offset", "How to offset billboard textures");
-
- prop = RNA_def_property(srna, "billboard_tilt", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "bb_tilt");
- RNA_def_property_range(prop, -1.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Tilt", "Tilt of the billboards");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
prop = RNA_def_property(srna, "color_maximum", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "color_vec_max");
RNA_def_property_range(prop, 0.01f, 100.0f);
RNA_def_property_ui_text(prop, "Color Maximum", "Maximum length of the particle color vector");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
- prop = RNA_def_property(srna, "billboard_tilt_random", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "bb_rand_tilt");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Random Tilt", "Random tilt of the billboards");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_offset", PROP_FLOAT, PROP_TRANSLATION);
- RNA_def_property_float_sdna(prop, NULL, "bb_offset");
- RNA_def_property_array(prop, 2);
- RNA_def_property_range(prop, -100.0f, 100.0f);
- RNA_def_property_ui_range(prop, -1.0, 1.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "Billboard Offset", "");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_size", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "bb_size");
- RNA_def_property_array(prop, 2);
- RNA_def_property_range(prop, 0.001f, 10.0f);
- RNA_def_property_ui_text(prop, "Billboard Scale", "Scale billboards relative to particle size");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_velocity_head", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "bb_vel_head");
- RNA_def_property_range(prop, 0.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Billboard Velocity Head", "Scale billboards by velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_velocity_tail", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "bb_vel_tail");
- RNA_def_property_range(prop, 0.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Billboard Velocity Tail", "Scale billboards by velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
/* general values */
prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "sta"); /*optional if prop names are the same */
@@ -3123,13 +3031,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Instance Object", "Show this Object in place of particles");
RNA_def_property_update(prop, 0, "rna_Particle_redo_dependency");
- prop = RNA_def_property(srna, "billboard_object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "bb_ob");
- RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Billboard Object", "Billboards face this object (default is active camera)");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
/* boids */
prop = RNA_def_property(srna, "boids", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "BoidSettings");
@@ -3381,22 +3282,6 @@ static void rna_def_particle_system(BlenderRNA *brna)
"rna_ParticleSystem_active_particle_target_index_range");
RNA_def_property_ui_text(prop, "Active Particle Target Index", "");
- /* billboard */
- prop = RNA_def_property(srna, "billboard_normal_uv", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "bb_uvname[0]");
- RNA_def_property_string_maxlength(prop, 32);
- RNA_def_property_ui_text(prop, "Billboard Normal UV", "UV map to control billboard normals");
-
- prop = RNA_def_property(srna, "billboard_time_index_uv", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "bb_uvname[1]");
- RNA_def_property_string_maxlength(prop, 32);
- RNA_def_property_ui_text(prop, "Billboard Time Index UV", "UV map to control billboard time index (X-Y)");
-
- prop = RNA_def_property(srna, "billboard_split_uv", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "bb_uvname[2]");
- RNA_def_property_string_maxlength(prop, 32);
- RNA_def_property_ui_text(prop, "Billboard Split UV", "UV map to control billboard splitting");
-
/* vertex groups */
/* note, internally store as ints, access as strings */