{"id":4469,"date":"2024-12-09T05:47:49","date_gmt":"2024-12-09T11:47:49","guid":{"rendered":"https:\/\/lab.rapternet.us\/?p=4469"},"modified":"2024-12-03T22:03:50","modified_gmt":"2024-12-04T04:03:50","slug":"custom-printed-keycaps","status":"publish","type":"post","link":"https:\/\/lab.rapternet.us\/?p=4469","title":{"rendered":"Custom Printed Keycaps"},"content":{"rendered":"\n<p>So far I&#8217;ve been using relegendable key caps for my macro pads and ESP Decks, but I&#8217;ve recently found another way. There is an open source keycap generator that can create multi color key caps that can be printed on my Bambu printers. There are a lot of pre-generated caps included with the repository, but I&#8217;d like to be able to generate my own custom ones too.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">3d Printed Keycap Options<\/h2>\n\n\n\n<p>I found a number of 3d printable keycap sets. <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/braindefender\/KLP-Lame-Keycaps\">KLP Lame Keycaps<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.printables.com\/model\/399607-complete-cherry-mx-stem-keycap-set-optimized-for-3\">Riskable Complete Cherry MX Stem Gem Profile Keycap Set<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.printables.com\/model\/1018594-des-profile-mx-keycaps-separate-stems-and-keys\/files\">Craig Andrews DES Profile MX Keycaps<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/rsheldiii\/KeyV2\" target=\"_blank\" rel=\"noreferrer noopener\">Key v2 OpenSCAD library<\/a><\/li>\n<\/ul>\n\n\n\n<p>Craig Andrews&#8217; keycap set has no legends, just the various row sizes and u sizes for keycaps. The KLP Lame keycaps don&#8217;t have cool characters or multi color options in general, so maybe not as cool but still pretty cool. I was intrigued by the keyv2 OpenSCAD software, but it didn&#8217;t seem quite as capable as the one I picked in the end (lack of multi color support was the big missing piece).<\/p>\n\n\n\n<p>The one that caught my eye though was generated by an open source keycap generator. This intrigued me as I can use it to generate my own caps, with whatever text or icons I want to. This one ended up being it&#8217;s own adventure as I struggled to run the provided scripts successfully.<\/p>\n\n\n\n<p>I decided to go with the keycap playground based keycaps as I could make use of the openscad based generator to customize my own keycaps.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing and the Included Caps<\/h2>\n\n\n\n<p>I first started out by printing out a number of the keycaps generated by the creator of the scripts. Since I planned on using these on my macropads, I picked a number of icon keycaps to print out instead of lettered keycaps.<\/p>\n\n\n\n<p>We&#8217;ll start by pulling all the key caps into Bambu Studio and opening the objects menu. This is a part of the left hand side bar.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"409\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-6.png\" alt=\"\" class=\"wp-image-4524\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-6.png 680w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-6-300x180.png 300w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><figcaption class=\"wp-element-caption\">Set to Objects<\/figcaption><\/figure>\n\n\n\n<p>Once the objects listing is open, we&#8217;ll go to the assembly view. In this view we can select filament colors for each individual object being printed.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"158\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-7-1024x158.png\" alt=\"\" class=\"wp-image-4525\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-7-1024x158.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-7-300x46.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-7-768x118.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-7.png 1534w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Select Assembly<\/figcaption><\/figure>\n\n\n\n<p>Once in the view, all the keycaps will be shown in a big blob (even if arranged nicely on the build plate). This is fine since we can use the object interface to select which parts of the caps we want which colors. In these keycaps, the [1,1,1,1] object is the outer shell and main body of the keycap. The other object in there is the legend of the keycap.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"631\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-8-1024x631.png\" alt=\"\" class=\"wp-image-4526\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-8-1024x631.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-8-300x185.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-8-768x473.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-8-1536x946.png 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-8.png 2013w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Changing colors<\/figcaption><\/figure>\n\n\n\n<p>In my case, I changed all the shells to blue and left the legends orange. After this we can clock the return button in the upper left corner (just outside the side pane with the object list) to get back to our build plate where we&#8217;ll see the keycap colors in full now. Or we will once they&#8217;re arranged. Just right click on the build plate and hit arrange and let Bambu Studio do the work for you.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"675\" height=\"563\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-9.png\" alt=\"\" class=\"wp-image-4527\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-9.png 675w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-9-300x250.png 300w\" sizes=\"auto, (max-width: 675px) 100vw, 675px\" \/><figcaption class=\"wp-element-caption\">Arrange<\/figcaption><\/figure>\n\n\n\n<p>Now we can get an initial look at our legend and cap colors.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"962\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-10-1024x962.png\" alt=\"\" class=\"wp-image-4529\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-10-1024x962.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-10-300x282.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-10-768x722.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-10.png 1114w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Fully arranged<\/figcaption><\/figure>\n\n\n\n<p>I used a silky blue and copper I had around from some previous work for my demo prints. I think the silky&#8217;s look great in some instances, but in this case, I think a matte filament would look better at least for the legend in the keycap, if not for the whole thing.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"771\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1138463928712136914274180988-1024x771.jpg\" alt=\"\" class=\"wp-image-4472\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1138463928712136914274180988-1024x771.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1138463928712136914274180988-300x226.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1138463928712136914274180988-768x578.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1138463928712136914274180988-1536x1157.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1138463928712136914274180988.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Silky materials give maybe too much gloss<\/figcaption><\/figure>\n\n\n\n<p>Even so, I&#8217;m happy with the results and will absolutely start using them for my ESP Deck and NFC Deck macro pads. They&#8217;ll give my builds a bit more personality.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"771\" data-id=\"4477\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1829301329049168730653430892-1024x771.jpg\" alt=\"\" class=\"wp-image-4477\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1829301329049168730653430892-1024x771.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1829301329049168730653430892-300x226.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1829301329049168730653430892-768x578.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1829301329049168730653430892-1536x1157.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1829301329049168730653430892.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Custom Printed Keycaps<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"2000\" height=\"1506\" data-id=\"4471\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1251082246921587815931873215.jpg\" alt=\"\" class=\"wp-image-4471\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1251082246921587815931873215.jpg 2000w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1251082246921587815931873215-300x226.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1251082246921587815931873215-1024x771.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1251082246921587815931873215-768x578.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/pxl_20241004_1251082246921587815931873215-1536x1157.jpg 1536w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Relegendable Keycaps<\/figcaption><\/figure>\n<\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Setting up Keycap Playground<\/h2>\n\n\n\n<p>There are a few dependencies needed to run the <a href=\"https:\/\/github.com\/riskable\/keycap_playground\">keycap playground software <\/a>(and a few more to use the automated scripts with it).<\/p>\n\n\n\n<p>Dependencies:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/3MFConsortium\/lib3mf\">lib3mf-dev<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/openscad.org\/\">openscad<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/jschobben\/colorscad\">colorscad<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/jschobben\/colorscad\/tree\/master\/3mfmerge\" target=\"_blank\" rel=\"noreferrer noopener\">3mfmerge<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Install lib3mf-dev from the standard apt repos:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">apt-get install lib3mf-dev<\/pre>\n\n\n\n<p>Colorscad can be retrieved from GitHub:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">git clone https:\/\/github.com\/jschobben\/colorscad.git<\/pre>\n\n\n\n<p>Building <a href=\"https:\/\/github.com\/jschobben\/colorscad\/tree\/master\/3mfmerge\" target=\"_blank\" rel=\"noreferrer noopener\">3mfmerge is done from the colorscad repository<\/a>. Just start from the 3mfmerge folder in the repo and run the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">mkdir build<br>cd build<br>cmake .. -DLIB3MF_TESTS=OFF<br>cmake --build .<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Font Installation<\/h2>\n\n\n\n<p>I&#8217;m running things on Ubuntu through WSL. For my ubuntu install, I downloaded the material design desktop ttf font from <a href=\"https:\/\/github.com\/Templarian\/MaterialDesign-Font\" target=\"_blank\" rel=\"noreferrer noopener\">Templarian on GitHub<\/a>.<\/p>\n\n\n\n<p><a href=\"https:\/\/askubuntu.com\/questions\/3697\/how-do-i-install-fonts\" target=\"_blank\" rel=\"noreferrer noopener\">Installing the font<\/a> itself is pretty simple. Copy the font to <code>\/usr\/local\/share\/fonts<\/code> or a subfolder (such as <code>\/usr\/local\/share\/fonts\/TTF<\/code>) and then run <code>sudo fc-cache -fv<\/code>. There are some graphical programs you can install to make this easier, but I didn&#8217;t need to use them. The Ubuntu wiki page on Fonts <a href=\"https:\/\/wiki.ubuntu.com\/Fonts\">here<\/a> may be of help too.<\/p>\n\n\n\n<p>Now do note the font name is not exactly the same as in the gem_full.py script, so we&#8217;ll need to edit the script to use the desktop font&#8217;s name instead (from &#8220;Material Design Icons&#8221; to &#8220;Material Design Icons Desktop&#8221;).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Keycap Playground Tweaks<\/h2>\n\n\n\n<p>Let&#8217;s go over the entire set of file tweaks so far that we need to make<\/p>\n\n\n\n<p>While the key cap generator does work well once you get it working, it does take a few modifications to run depending on your setup.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The -P argument is no longer in colorscad, so remove it to from the keycap.py script.The &#8211;enable=fast-csg isn&#8217;t in stable openscad builds (2021 builds and earlier) yet, but it is in 2022 builds and later. If your OpenSCAD version is 2021 or older, remove the flag from keycap.py, otherwise leave it in.<\/li>\n\n\n\n<li>The &#8211;enable=fast-csg isn&#8217;t in stable openscad builds (2021 builds and earlier) yet, but it is in 2022 builds and later. If your OpenSCAD version is 2021 or older, remove the flag from keycap.py, otherwise leave it in.<\/li>\n\n\n\n<li>The stem type is defaulted to &#8216;alp&#8217; which is not a stem type that I have key switches for. This can be replaced with &#8216;box_cherry&#8217; to get the more common output.<\/li>\n\n\n\n<li>Change the font name in gem_full.py script to use the desktop font&#8217;s name instead (from &#8220;Material Design Icons&#8221; to &#8220;Material Design Icons Desktop&#8221;).<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Running the Python Generation Script<\/h2>\n\n\n\n<p>Generates a whole keyboard&#8217;s worth of keycaps (and a few extras). Best way<br>to use this script is from within the <code>keycap_playground<\/code> directory.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ .\/scripts\/gem_full.py --out \/tmp\/output_dir<\/pre>\n\n\n\n<p>I did notice that the .3mf files generated are a bit different from the ones generated by it from other people, mine aren&#8217;t able to be loaded in microsoft 3d builder. There are no problems though loading them into Bambu Studio.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"545\" height=\"373\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image.png\" alt=\"\" class=\"wp-image-4483\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image.png 545w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-300x205.png 300w\" sizes=\"auto, (max-width: 545px) 100vw, 545px\" \/><\/figure>\n\n\n\n<p>The keycaps I generated also have different object names in bambu studio than the ones provided in the sample output.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"612\" height=\"207\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-1.png\" alt=\"\" class=\"wp-image-4484\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-1.png 612w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-1-300x101.png 300w\" sizes=\"auto, (max-width: 612px) 100vw, 612px\" \/><figcaption class=\"wp-element-caption\">Object 1 is the sample, F_dot is my generated cap<\/figcaption><\/figure>\n\n\n\n<p>Bambu studio at least seems to handle them for coloring the legends and slicing without any issues. Other than this looking a bit funny, it doesn&#8217;t affect the output.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Manipulating Unicode<\/h2>\n\n\n\n<p>I plan on making a number of custom icon keycaps different from the defaults provided in the script. I also haven&#8217;t used Unicode much in the past, so let&#8217;s cover using it in a few different places.<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\">Libre Office Writer<\/h3>\n\n\n\n<p>I decided to create all the icons I wanted in <a href=\"https:\/\/wiki.documentfoundation.org\/ReleaseNotes\/5.1#Writer\" target=\"_blank\" rel=\"noreferrer noopener\">libre office writer<\/a>, then copy paste them out into my scripts in order to know my Unicode was correct. To insert a Unicode character into it is easy enough, type the character code in to the document and hit ALT-X afterwards. Libre office will then replace the code with the character.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">F0460 Alt X<\/pre>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\">Sublime Text<\/h3>\n\n\n\n<p>Using Sublime text to insert Unicode into files is not much different than using libre office. Instead of typing the hex followed by a key combo in libre office, it&#8217;s a key combo followed by the hex and a space for sublime text.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Ctrl-Alt-Shift-U + hex + Space<\/pre>\n\n\n\n<p>With that you have the Unicode character inserted into your text document.<\/p>\n\n\n\n<p>When I started out updating the script for some custom keycaps, I inserted the characters into libre office, then copied them into the script via notepad++, though I ended up installing sublime text and just inserted them directly using that text editor instead to be a bit more efficient. I could also copy them out of the font&#8217;s <a href=\"https:\/\/github.com\/Templarian\/MaterialDesign-Font\/blob\/master\/cheatsheet.html\">helper html <\/a>and into the text document which helped too.<\/p>\n<\/div><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"547\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-12-1024x547.png\" alt=\"\" class=\"wp-image-4598\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-12-1024x547.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-12-300x160.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-12-768x410.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-12.png 1357w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Cheatsheet<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Debugging Stems<\/h3>\n\n\n\n<p>One of these things is not like the rest, if you generate some keycaps and notice the stems are wrong, it&#8217;s probably due to an odd default in the software to do &#8220;alp&#8221; stems. This can be rectified by just changing the stem type to &#8220;box_cherry&#8221;and regenerating the keycaps.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"769\" height=\"500\" data-id=\"4485\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-2.png\" alt=\"\" class=\"wp-image-4485\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-2.png 769w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-2-300x195.png 300w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Wait a Second&#8230;&#8230;<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"747\" height=\"566\" data-id=\"4487\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-3.png\" alt=\"\" class=\"wp-image-4487\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-3.png 747w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-3-300x227.png 300w\" sizes=\"auto, (max-width: 706px) 89vw, (max-width: 767px) 82vw, 740px\" \/><figcaption class=\"wp-element-caption\">Alp vs Cherry Stems<\/figcaption><\/figure>\n<\/figure>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\"><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Debugging Fonts<\/h3>\n<\/div><\/div>\n\n\n\n<p>When the script failed to generate valid legends on the keycaps, I decided to try out the web font instead of the desktop font. This however didn&#8217;t change the output. In this case, I didn&#8217;t even get the &#8220;invalid character&#8221; box as the legend on my keycap, so something else must be going on.<\/p>\n\n\n\n<p>Figuring out what&#8217;s going wrong with the fonts can be a little more tedious. I ran into a few problems with my fonts that manifested in slightly different ways. Square boxes instead of characters like below meant the font was missing from my system entirely.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"764\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-4-1024x764.png\" alt=\"\" class=\"wp-image-4489\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-4-1024x764.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-4-300x224.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-4-768x573.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-4.png 1338w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Faulty Icons<\/figcaption><\/figure>\n\n\n\n<p>If nothing was generated in the legends, no box, character, etc. That meant the character was invalid in the font that was being used. In my case, there was quite the rabbit hole of figuring out why the characters I was giving it were invalid even after installing the right fonts.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Still Failing to Generate a Keycap with Icon<\/h2>\n\n\n\n<p>I ended up going down quite the rabbit hole with this one. I ran into issues with being able to generate an MDI keycap despite multiple attempts and modifications etc. After I installed my font, I didn&#8217;t even get the error box anymore. All I got was an empty keycap with no legend at all.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><br>Create a separate .3mf file for each color<br>1\/2 [1, 1, 1, 1] Starting<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Starting<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Geometries in cache: 211<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Geometry cache size in bytes: 37913760<br>2\/2 [0.313726, 0.313726, 0.313726, 1] CGAL Polyhedrons in cache: 7<br>2\/2 [0.313726, 0.313726, 0.313726, 1] CGAL cache size in bytes: 55510320<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Total rendering time: 0:00:31.248<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Current top level object is empty.<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Warning: output is empty, removing it!<br>2\/2 [0.313726, 0.313726, 0.313726, 1] rm: cannot remove '.\/tmp.AODdBP\/[0.313726, 0.313726, 0.313726, 1].3mf': No such file or directory<\/pre>\n\n\n\n<p>However I could generate lettered keycaps without any issues. I was able to generate the entire alphabet of keys, legends intact, but no icons. Below is a log from when I generated the &#8220;A&#8221; keycap.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Create a separate .3mf file for each color<br>1\/2 [1, 1, 1, 1] Starting<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Starting<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Geometries in cache: 219<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Geometry cache size in bytes: 37947200<br>2\/2 [0.313726, 0.313726, 0.313726, 1] CGAL Polyhedrons in cache: 9<br>2\/2 [0.313726, 0.313726, 0.313726, 1] CGAL cache size in bytes: 66755696<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Total rendering time: 0:00:32.873<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Top level object is a 3D object:<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Simple:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 yes<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Vertices:\u00a0\u00a0\u00a0\u00a0 3130<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Halfedges:\u00a0\u00a0 12860<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Edges:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 6430<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Halffacets:\u00a0\u00a0 6600<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Facets:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 3300<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Volumes:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 2<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Finished at .\/tmp.P3hmeK\/[0.313726, 0.313726, 0.313726, 1].3mf<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Running OpenSCAD Nightly<\/h2>\n\n\n\n<p>I thought it might be the version of OpenSCAD that I&#8217;m using causing the issues that I was running into generating the icon legends. I decided to try running a dev build of it instead of the stable build (which is over 3 years old). I first started by trying to build it myself, but after a few days working on that without any successful builds, I decided to try another option.<\/p>\n\n\n\n<p>Since the quest to compile OpenSCAD from source was going to be a bit longer of a detour than I expected and may not help me out anyway. I decided to try and find a Ubuntu PPA or some other source for a beta or nightly build of it.<\/p>\n\n\n\n<p>OpenSCAD provides a snap package for the Dev builds as well that I could use, however snap didn&#8217;t want to run on my WSL instance, so I decided to try the app images instead.<\/p>\n\n\n\n<p>I ended up finding the <a href=\"https:\/\/openscad.org\/downloads.html#snapshots\" target=\"_blank\" rel=\"noreferrer noopener\">development built snapshots of OpenSCAD<\/a> which were in an app image format, something I had never used before.<\/p>\n\n\n\n<p>These ended up being easy enough, I downloaded the app image using wget, ensured it was executable (chmod +x on it), and then tried running it. It complained about fuse being missing from my machine, so I installed that and it was off to the races.<\/p>\n\n\n\n<p>To simplify things for the script though, I also decided to symlink the app image to my user\/bin folder as openscad.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo ln -s \/path\/to\/appimage \/usr\/bin\/openscad<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Shell Environment<\/h2>\n\n\n\n<p>To validate the inputs that the script was generating, I tried putting all of the script&#8217;s inputs directly into the keycap_playground.osc through OpenSCAD and run the generation. When I did this, it all worked without any issues, generating my keycap with a good looking legend, no boxes.<\/p>\n\n\n\n<p>Maybe it&#8217;s my shell environment instead, I could try using ZSH instead of bash, but I thought running things manually through the shell instead of the Python script would help me isolate the problem first. I finally got one keycap to generate using this method. I took the commands output by the script, copied them into my shell, and modified the legend character being passed into OpenSCAD. I also noticed a lack of &#8220;\\ublah\\ublah&#8221; on the console, so I&#8217;m thinking it&#8217;s related to how python is handling the Unicode character before passing it off to OpenSCAD.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Create a separate .3mf file for each color<br>1\/2 [1, 1, 1, 1] Starting<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Starting<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Geometries in cache: 219<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Geometry cache size in bytes: 23419520<br>2\/2 [0.313726, 0.313726, 0.313726, 1] CGAL Polyhedrons in cache: 9<br>2\/2 [0.313726, 0.313726, 0.313726, 1] CGAL cache size in bytes: 74999520<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Total rendering time: 0:00:20.628<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Top level object is a 3D object (Nef polyhedron):<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Simple:\u00a0\u00a0\u00a0\u00a0 yes<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Vertices:\u00a0\u00a0\u00a0\u00a0 5813<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Halfedges:\u00a0\u00a0 22126<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Edges:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 11063<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Halffacets:\u00a0 10480<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Facets:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 5240<br>2\/2 [0.313726, 0.313726, 0.313726, 1]\u00a0\u00a0\u00a0 Volumes:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 4<br>2\/2 [0.313726, 0.313726, 0.313726, 1] Finished at .\/tmp.1PiS9z\/[0.313726, 0.313726, 0.313726, 1].3mf<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>So something is wrong with my Unicode in the script, or in how the script is handling that before sending it to OpenSCAD.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Python Environment<\/h2>\n\n\n\n<p>Since the script is python, it&#8217;s time to investigate the Python environment I&#8217;m running to see if I can find a misconfiguration there before digging into the script itself. This ended up being a no-op though as <a href=\"https:\/\/stackoverflow.com\/questions\/6289474\/working-with-utf-8-encoding-in-python-source#6289494\" target=\"_blank\" rel=\"noreferrer noopener\">Python3 supports Unicode<\/a> <a href=\"https:\/\/docs.python.org\/3\/howto\/unicode.html\" target=\"_blank\" rel=\"noreferrer noopener\">natively without any configuration changes<\/a>. In Python 3, UTF-8 is the default source encoding (see PEP 3120), so Unicode characters can be used anywhere.<\/p>\n\n\n\n<p>If it were running Python 2,&nbsp; it would work after declaring in the source code header:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># -*- coding: utf-8 -*-<\/pre>\n\n\n\n<p>I wonder if Python is string-ify-ing things weirdly to Unicode instead of just outputting what I put in.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Unicode in a Shell Environment<\/h2>\n\n\n\n<p>In a shell environment (Bash and ZSH should support this out of the box), Unicode can be used in the following way using tools like echo. <br><br>% echo -e &#8216;\\u2620&#8217;&nbsp;&nbsp;&nbsp;&nbsp; # \\u takes four hexadecimal digits<br>\u2620<br>% echo -e &#8216;\\U0001f602&#8217; # \\U takes eight hexadecimal digits<br>\ud83d\ude02<\/p>\n\n\n\n<p>I was able to get the script to successfully generate keycaps when I modified the shell commands going into openscad rather than using the output from python directly. This lead me to believe something in python was messing with the output and preventing my keycaps from generating correctly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Real Fix<\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"988\" height=\"645\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-5.png\" alt=\"\" class=\"wp-image-4516\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-5.png 988w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-5-300x196.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/image-5-768x501.png 768w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Successful Icon Generation<\/figcaption><\/figure>\n\n\n\n<p>Adding some print statements in the right places and with the right arguments finally gave me the info I needed. I found that the json dump function was editing the string to UTF-8 and passing it in, which was causing issues as the icons were being modified by that. I needed to add one <a href=\"https:\/\/stackoverflow.com\/questions\/18337407\/saving-utf-8-texts-with-json-dumps-as-utf-8-not-as-a-u-escape-sequence\" target=\"_blank\" rel=\"noreferrer noopener\">argument to the function call and everything started working<\/a>.<\/p>\n\n\n\n<p>The json.dumps call needed to be:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> json.dumps(legend, ensure_ascii=False)<\/pre>\n\n\n\n<p>This one little argument was enough to convert the Unicode that could be used by openscad to a useless utf-8 character that couldn&#8217;t be deciphered (especially since it was converted from one Unicode character into two utf-8 characters). The final new quote function is below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">    def quote(self, legends):<br>        \"\"\"<br>        Checks for the edge case of a single quote (') legend and converts it<br>        into `\"'\"'\"'\"` so that bash will pass it correclty to OpenSCAD via<br>        `getstatusoutput()`.  Also covers the slash (\\\\) legend for<br>        completeness.<br><br>        .. note::<br><br>            Example of what it should look like: `LEGENDS=[\"'\"'\"'\", \"\", \"\\\"\"];`<br>        \"\"\"<br>        properly_escaped_quote = r'''\"'\"'\"'\"'''<br>        out = \"[\"<br>        for i, legend in enumerate(legends):<br>            if legend == \"'\":<br>                out += properly_escaped_quote + \",\"<br>            elif legend == '\"':<br>                out += r'\"\\\"\"'<br>            else:<br>                out += json.dumps(legend, ensure_ascii=False) + \",\"<br>        out = out.rstrip(',') # Get rid of trailing comma<br>        return out + \"]\"<\/pre>\n\n\n\n<p>After finding the bug in the script, I documented it in an issue I had opened on the GitHub and submitted a PR to fix it. The maintainer may not have touched it in a while but hopefully anyone else who finds it will be able to make use of the findings.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"771\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241012_213732460-1024x771.jpg\" alt=\"\" class=\"wp-image-4542\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241012_213732460-1024x771.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241012_213732460-300x226.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241012_213732460-768x578.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241012_213732460-1536x1157.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241012_213732460-2048x1542.jpg 2048w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Printed Media Keycaps<\/figcaption><\/figure>\n\n\n\n<p>I may have considered editing it to create keycaps for EVERY icon in material design icons, but that&#8217;s nearly 7500 unique caps. How would someone even go about uploading something like that archive to a 3d printing website? Though it would be fun to try at some point. I&#8217;ve also only generated gem keycaps so far but the generator can create any form of keycap. They do turn out well when printed and I&#8217;m happy with the results even if the journey to get here was frustrating.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Drawbacks<\/h2>\n\n\n\n<p>I did install some of these on my keypads and noticed one drawback rather quickly. When using LED backlighting (for notifications and such), it&#8217;s much less noticeable using the printed key caps vs the relegendable ones. There is a PR on the main repo to allow keycap playground to provide glow through capabilities with the right materials. I may look into this and try generating some new keycaps that way (though I&#8217;ll also need some clear material to run on my printers as well for that).<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"771\" height=\"1024\" data-id=\"4600\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241109_163806996-771x1024.jpg\" alt=\"\" class=\"wp-image-4600\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241109_163806996-771x1024.jpg 771w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241109_163806996-226x300.jpg 226w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241109_163806996-768x1020.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241109_163806996-1157x1536.jpg 1157w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241109_163806996-1542x2048.jpg 1542w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2024\/10\/PXL_20241109_163806996-scaled.jpg 1928w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Backlighting comparison between various keycaps<\/figcaption><\/figure>\n<\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Resources<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/riskable\/keycap_playground\">Keycap Playground GitHub<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.printables.com\/model\/399607-complete-cherry-mx-stem-keycap-set-optimized-for-3\">Original Gem Key cap Set<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.printables.com\/model\/1037546-multi-color-media-keycaps\">My Gem Media Keycap Set<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/openscad.org\/\">OpenSCAD<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/jschobben\/colorscad\/\">ColorSCAD<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/Templarian\/MaterialDesign-Font\/tree\/master\">Material Design Icons Font GitHub<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>So far I&#8217;ve been using relegendable key caps for my macro pads and ESP Decks, but I&#8217;ve recently found another way. There is an open source keycap generator that can create multi color key caps that can be printed on my Bambu printers. There are a lot of pre-generated caps included with the repository, but &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/lab.rapternet.us\/?p=4469\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Custom Printed Keycaps&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":4542,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[56],"tags":[18,95,76,81,75,103],"class_list":["post-4469","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-making","tag-3d-printing","tag-bambu","tag-espdeck","tag-keyboards","tag-macropad","tag-nfcdeck"],"_links":{"self":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/4469","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4469"}],"version-history":[{"count":53,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/4469\/revisions"}],"predecessor-version":[{"id":4602,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/4469\/revisions\/4602"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/media\/4542"}],"wp:attachment":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4469"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4469"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4469"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}