HoudiniでStringとUTF8を行き来しよう。

#はじめに
###概要
HoudiniでのString Attributeや諸々でのUnicodeの取り扱いについての雑記。
※基本的にはずっとVEX-Wrangleの説明になります。少し癖のある記述ををすることもあるかと思いますが、そこは手癖ということで見逃して...。
※基礎的な部分はスキップしてるのでご了承ください。ニッチな需要向けになります、きっと。

###環境
Houdini18.0.460


#関数を使わない取り回し
##シンプルな方法
Houdiniで文字列は**"\"**を使うことで、Unicodeから文字列を作成することが出来ます。

```C#:vex
string test1 = "Houdini"; //=> Houdini
string test2 = "\72\111\117\100\105\110\105"; //=> Houdini
string test3 = "\x48\x6F\x75\x64\x69\x6E\x69"; //=> Houdini
```
この場合、上記の*test1*と*test2*と*test3*は同じ文字を表しています。(信じがたいです...)
*test1*は基本的な形ですね。
*test2*は\を使用して10進数(Unicode)で記入しています。10進数では一応あらゆる文字に対応しています。
*test3*は*test2*の数値を16進数(Unicode)で記入しています。16進数の場合は(U+00000－U+0007F)に対応してます。

(Unicode周りの検索は[こちら](https://decodeunicode.org/en)を使うと便利です。DECIMAL VALUE/10進数,UTF-8 HEX VALUE=16進数)

##FontSOPを使う方法
ちなみにFontSOPでもUnicode形式は使用できます。
FontSOPの場合は**"",''**が必要ありません。

```C#:Font_SOP
Houdini //=> Houdini
\13077 //=> ㌕
\12845 //=> ㈭
\969 //=> ω
```
※表示文字は使用するFontに依存します。

少し話は脱線しますが、FontSOPのParameterの一番下にある*Add Text Attribute*で追加されるtextsymbol(primitive)は文字に対応したUnicodeを表示します。なので、FontSOPを使えばUnicodeを取得できます。便利ですね...？

##アトリビュートを使う方法
ちなみにこの入力法は普通の文字と併用も出来ますし、Unicodeのアトリビュート参照とかもできます。

下記のサンプルはAttribWrangle[Detail(only once)]を2つ繋げます。

```C#:attribwrangle1
i@index1 = 64;
s@index2 = "x40";
```

```C#:attribwrangle2
string1 = "\@Cd.x=0.0";
string2 = "\64Cd.x=0.0";
string3 = "\x40Cd.x=0.0";
string4 = "\\`detail(0,'index1',0)`Cd.x=0.0";
string5 = "\\`details(0,'index2')`Cd.x=0.0";
//=>@Cd.x=0.0
```

*string1*から*string5*は全て同じ文字列を表示します(正直訳が分からないよ。)
バッククォートの使い方は[公式ドキュメント](https://www.sidefx.com/ja/docs/houdini/network/expressions.html)を参照。

#関数を使う取り回し
平打ちだと使いにくいですね。ここでUnicode変換に関する関数を紹介します。[ord関数](https://www.sidefx.com/ja/docs/houdini/vex/functions/ord.html)と[chr関数](https://www.sidefx.com/ja/docs/houdini/vex/functions/chr.html)です。
ord関数は文字列からUTF8に変換します。
chr関数はUTF8から文字列に変換します。
勘のいい方はお気付きかもですが、pythonの関数なんかと同じです。

```C#:Capitals
string Capital_list[];
string  Capital_string;
int start = ord("A");
int end = ord("Z");
for(int i = start; i < end+1; i++){
    append(Capital_list,chr(i));
    Capital_string+=chr(i);
}
//Capital_list=>[ A, B, C,.., X, Y, Z ]
//Capital_string=>ABCDEFGHIJKLMNOPQRSTUVWXYZ
```
```C#:Randoms
string Random_list[];
for(int i = 0; i < 20; i++){
    int num = rint(fit01(rand(i),65,90));
    append(Random_list,chr(num));
}
//Random_list=>[ K, A, U, H, A, F, D, P, X, N, C, D, Y, X, E, C, U, W, W, B ]
```

#文字をトランジションしよう。
ここまで、色々な手段で文字とUnicodeを行き来してきましたが、「いったい何に使えるんだ？」という感じになりそうなので最後に文字をトランジションする方法を紹介しておきます。
AttribWrangle[Detail(only once)]とFontSOPをそれぞれ用意します。（何にも繋げないで大丈夫です。）

```C#:lerpText
string start = "Houdini";
string end = "Tanoshii";
int start_len = len(start);
int end_len = len(end);
int length = (start_len>end_len)?start_len:end_len;
float bias = chf("bias");
s@main;
for (int i=0; i<length;i++){
    int t = rint(lerp(ord(start[i]),ord(end[i]),bias));
    @main += chr(t);
}
```
```C#:FontSOP
`details("../lerpText","main")`
```
lerpTextのbiasパラメータを動かすと文字が変化します。
文字をそのまま線形補間することは出来ないですが、数値に変換することで線形補間させることが出来ます。 (*>△<)<うゎー便利
<details><summary>サンプルの詳しい解説</summary>
string start = "Houdini";
string end = "Tanoshii";
//最初と最後の文字列を指定します。ここは日本語でも大丈夫です。
//-------------------------
int start_len = len(start);
int end_len = len(end);
//文字列の長さを取得します。
//----------------------------
int length = (start_len>end_len)?start_len:end_len;
//文字列の長い方を長さとして設定します。
//三項演算子を使って書いていますが、普通にif文でも大丈夫です。
//int length;
//if(start_len>end_len){length = start_len;}
//else{length = end_len;}
//---------------------------
float bias = chf("bias");
//パラメーターを作成します。
s@main;
//stringアトリビュートの設定
for (int i=0; i<length;i++){
    int t = rint(lerp(ord(start[i]),ord(end[i]),bias));
//文字をUTF8に変換します。文字が無い部分は-1が返されますが問題ないです。数値化されているのでlerpを使用できます。
    @main += chr(t);
//UTF8を文字に復元します。-1が返された場合(該当しない数値)には空白を返します。
}
</details>

#おわりに
ここら辺の文字列の扱いは~~需要~~、情報が無かったので簡単にまとめました。
使い方次第では色々トリッキーなことが出来そうな気がしますね。
例えば2バイト文字も入力しないで2バイト文字を扱うとか...そんな場面は無いのか？
それでは、しゃーした～。