1use crate::{AtomMaterial, ColorPalette, DEFAULT_ATOM_MATERIAL};
2use bevy::color::Color;
3use std::sync::LazyLock;
4
5const METAL_MATERIAL: AtomMaterial = AtomMaterial::new(0.5, 0.2);
6
7pub const JMOL: ColorPalette = {
8 let mut colors = [None; 110];
9 let materials = [None; 110];
10 colors[1] = Some(Color::srgb_u8(255, 255, 255));
11 colors[2] = Some(Color::srgb_u8(217, 255, 255));
12 colors[3] = Some(Color::srgb_u8(204, 128, 255));
13 colors[4] = Some(Color::srgb_u8(194, 255, 0));
14 colors[5] = Some(Color::srgb_u8(255, 181, 181));
15 colors[6] = Some(Color::srgb_u8(144, 144, 144));
16 colors[7] = Some(Color::srgb_u8(48, 80, 248));
17 colors[8] = Some(Color::srgb_u8(255, 13, 13));
18 colors[9] = Some(Color::srgb_u8(144, 224, 80));
19 colors[10] = Some(Color::srgb_u8(179, 227, 245));
20 colors[11] = Some(Color::srgb_u8(171, 92, 242));
21 colors[12] = Some(Color::srgb_u8(138, 255, 0));
22 colors[13] = Some(Color::srgb_u8(191, 166, 166));
23 colors[14] = Some(Color::srgb_u8(240, 200, 160));
24 colors[15] = Some(Color::srgb_u8(255, 128, 0));
25 colors[16] = Some(Color::srgb_u8(255, 255, 48));
26 colors[17] = Some(Color::srgb_u8(31, 240, 31));
27 colors[18] = Some(Color::srgb_u8(128, 209, 227));
28 colors[19] = Some(Color::srgb_u8(143, 64, 212));
29 colors[20] = Some(Color::srgb_u8(61, 255, 0));
30 colors[21] = Some(Color::srgb_u8(230, 230, 230));
31 colors[22] = Some(Color::srgb_u8(191, 194, 199));
32 colors[23] = Some(Color::srgb_u8(166, 166, 171));
33 colors[24] = Some(Color::srgb_u8(138, 153, 199));
34 colors[25] = Some(Color::srgb_u8(156, 122, 199));
35 colors[26] = Some(Color::srgb_u8(224, 102, 51));
36 colors[27] = Some(Color::srgb_u8(240, 144, 160));
37 colors[28] = Some(Color::srgb_u8(80, 208, 80));
38 colors[29] = Some(Color::srgb_u8(200, 128, 51));
39 colors[30] = Some(Color::srgb_u8(125, 128, 176));
40 colors[31] = Some(Color::srgb_u8(194, 143, 143));
41 colors[32] = Some(Color::srgb_u8(102, 143, 143));
42 colors[33] = Some(Color::srgb_u8(189, 128, 227));
43 colors[34] = Some(Color::srgb_u8(255, 161, 0));
44 colors[35] = Some(Color::srgb_u8(166, 41, 41));
45 colors[36] = Some(Color::srgb_u8(92, 184, 209));
46 colors[37] = Some(Color::srgb_u8(112, 46, 176));
47 colors[38] = Some(Color::srgb_u8(0, 255, 0));
48 colors[39] = Some(Color::srgb_u8(148, 255, 255));
49 colors[40] = Some(Color::srgb_u8(148, 224, 224));
50 colors[41] = Some(Color::srgb_u8(115, 194, 201));
51 colors[42] = Some(Color::srgb_u8(84, 181, 181));
52 colors[43] = Some(Color::srgb_u8(59, 158, 158));
53 colors[44] = Some(Color::srgb_u8(36, 143, 143));
54 colors[45] = Some(Color::srgb_u8(10, 125, 140));
55 colors[46] = Some(Color::srgb_u8(0, 105, 133));
56 colors[47] = Some(Color::srgb_u8(192, 192, 192));
57 colors[48] = Some(Color::srgb_u8(255, 217, 143));
58 colors[49] = Some(Color::srgb_u8(166, 117, 115));
59 colors[50] = Some(Color::srgb_u8(102, 128, 128));
60 colors[51] = Some(Color::srgb_u8(158, 99, 181));
61 colors[52] = Some(Color::srgb_u8(212, 122, 0));
62 colors[53] = Some(Color::srgb_u8(148, 0, 148));
63 colors[54] = Some(Color::srgb_u8(66, 158, 176));
64 colors[55] = Some(Color::srgb_u8(87, 23, 143));
65 colors[56] = Some(Color::srgb_u8(0, 201, 0));
66 colors[57] = Some(Color::srgb_u8(112, 212, 255));
67 colors[58] = Some(Color::srgb_u8(255, 255, 199));
68 colors[59] = Some(Color::srgb_u8(217, 255, 199));
69 colors[60] = Some(Color::srgb_u8(199, 255, 199));
70 colors[61] = Some(Color::srgb_u8(163, 255, 199));
71 colors[62] = Some(Color::srgb_u8(143, 255, 199));
72 colors[63] = Some(Color::srgb_u8(97, 255, 199));
73 colors[64] = Some(Color::srgb_u8(69, 255, 199));
74 colors[65] = Some(Color::srgb_u8(48, 255, 199));
75 colors[66] = Some(Color::srgb_u8(31, 255, 199));
76 colors[67] = Some(Color::srgb_u8(0, 255, 156));
77 colors[68] = Some(Color::srgb_u8(0, 230, 117));
78 colors[69] = Some(Color::srgb_u8(0, 212, 82));
79 colors[70] = Some(Color::srgb_u8(0, 191, 56));
80 colors[71] = Some(Color::srgb_u8(0, 171, 36));
81 colors[72] = Some(Color::srgb_u8(77, 194, 255));
82 colors[73] = Some(Color::srgb_u8(77, 166, 255));
83 colors[74] = Some(Color::srgb_u8(33, 148, 214));
84 colors[75] = Some(Color::srgb_u8(38, 125, 171));
85 colors[76] = Some(Color::srgb_u8(38, 102, 150));
86 colors[77] = Some(Color::srgb_u8(23, 84, 135));
87 colors[78] = Some(Color::srgb_u8(208, 208, 224));
88 colors[79] = Some(Color::srgb_u8(255, 209, 35));
89 colors[80] = Some(Color::srgb_u8(184, 184, 208));
90 colors[81] = Some(Color::srgb_u8(166, 84, 77));
91 colors[82] = Some(Color::srgb_u8(87, 89, 97));
92 colors[83] = Some(Color::srgb_u8(158, 79, 181));
93 colors[84] = Some(Color::srgb_u8(171, 92, 0));
94 colors[85] = Some(Color::srgb_u8(117, 79, 69));
95 colors[86] = Some(Color::srgb_u8(66, 130, 150));
96 colors[87] = Some(Color::srgb_u8(66, 0, 102));
97 colors[88] = Some(Color::srgb_u8(0, 125, 0));
98 colors[89] = Some(Color::srgb_u8(112, 171, 250));
99 colors[90] = Some(Color::srgb_u8(0, 186, 255));
100 colors[91] = Some(Color::srgb_u8(0, 161, 255));
101 colors[92] = Some(Color::srgb_u8(0, 143, 255));
102 colors[93] = Some(Color::srgb_u8(0, 128, 255));
103 colors[94] = Some(Color::srgb_u8(0, 107, 255));
104 colors[95] = Some(Color::srgb_u8(84, 92, 242));
105 colors[96] = Some(Color::srgb_u8(120, 92, 227));
106 colors[97] = Some(Color::srgb_u8(138, 79, 227));
107 colors[98] = Some(Color::srgb_u8(161, 54, 212));
108 colors[99] = Some(Color::srgb_u8(179, 31, 212));
109 colors[100] = Some(Color::srgb_u8(179, 31, 186));
110 colors[101] = Some(Color::srgb_u8(179, 13, 166));
111 colors[102] = Some(Color::srgb_u8(189, 13, 135));
112 colors[103] = Some(Color::srgb_u8(199, 0, 102));
113 colors[104] = Some(Color::srgb_u8(204, 0, 89));
114 colors[105] = Some(Color::srgb_u8(209, 0, 79));
115 colors[106] = Some(Color::srgb_u8(217, 0, 69));
116 colors[107] = Some(Color::srgb_u8(224, 0, 56));
117 colors[108] = Some(Color::srgb_u8(230, 0, 46));
118 colors[109] = Some(Color::srgb_u8(235, 0, 38));
119
120 let fallback = Color::srgb_u8(255, 255, 255);
121 let fallback_material = DEFAULT_ATOM_MATERIAL;
122
123 ColorPalette {
124 colors,
125 materials,
126 fallback,
127 fallback_material,
128 }
129};
130
131pub static JMOL_METALLIC: LazyLock<ColorPalette> = LazyLock::new(|| {
132 let mut materials = [None; 110];
133
134 for atomic_number in [
135 3_u8, 4, 11, 12, 13, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 37, 38, 39, 40,
136 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
137 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 87, 88, 89, 90, 91, 92, 93,
138 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
139 ] {
140 materials[atomic_number as usize] = Some(METAL_MATERIAL);
141 }
142
143 ColorPalette {
144 colors: JMOL.colors,
145 materials,
146 fallback: JMOL.fallback,
147 fallback_material: JMOL.fallback_material,
148 }
149});
150
151#[cfg(test)]
152mod tests {
153 use super::{JMOL, JMOL_METALLIC};
154 use crate::AtomMaterial;
155 use ak_core::geometry::AtomicNumber;
156
157 #[test]
158 fn default_jmol_palette_uses_default_atom_material() {
159 let iron = AtomicNumber::new(26).unwrap();
160
161 assert_eq!(JMOL.material(iron), AtomMaterial::default());
162 }
163
164 #[test]
165 fn metallic_jmol_palette_marks_metals_without_affecting_nonmetals() {
166 let gold = AtomicNumber::new(79).unwrap();
167 let oxygen = AtomicNumber::new(8).unwrap();
168
169 assert!((JMOL_METALLIC.material(gold).metallic - 0.5).abs() < 1e-6);
170 assert_eq!(JMOL_METALLIC.material(oxygen), AtomMaterial::default());
171 }
172}