# Houdini 表达式基础

### 语言

Houdini可以让你使用两种语言写表达式：传统 HScript 表达式 和 Python. 此外，一些特殊节点可以让你编写 [VEX snippets](http://www.sidefx.com/docs/houdini/vex/snippets.html) （VEX短代码）控制节点行为。

<div id="bkmrk-hscript-%E8%A1%A8%E8%BE%BE%E5%BC%8F-%E4%BD"><div><table class="table"><tbody><tr><td>HScript 表达式

</td><td>使用 [expression functions](http://www.sidefx.com/docs/houdini/expressions/index.html "Expression functions let you compute the value of parameters.")（表达式函数）编写表达式的传统方法

</td></tr><tr><td>Python

</td><td>更强大 但是也更繁琐的方式。使用 [Houdini Object Model](http://www.sidefx.com/docs/houdini/hom/index.html "How to script Houdini using Python and the Houdini Object Model.") API 和任何 Python 本身的函数。

</td></tr><tr><td>VEX

</td><td>一种快速编译的语言，只用在特定节点的特定参数上

</td></tr></tbody></table>

</div></div>默认使用 HScript 表达式语言，如果要使用 Python，请参照 [Python parameter expressions](http://www.sidefx.com/docs/houdini/hom/expressions.html "You can write parameter expressions in Python instead of the default Hscript expression language.").

## 字符串参数

<div id="bkmrk-%E5%9C%A8%C2%A0%E6%95%B0%E5%AD%97%E5%8F%82%E6%95%B0%C2%A0%EF"><div>- 在 **数字参数** （例如 位置，缩放，旋转）中，参数中填写的文本作为表达式计算。
- 在 **字符串参数** 中（例如文件名，和由 [Font node](http://www.sidefx.com/docs/houdini/nodes/sop/font.html "Creates 3D text from Type 1, TrueType and OpenType fonts.") 创建的文本），参数中填写的文本被视为文字。Variables are expanded，但是若要通过表达式生成文字内容，需要把表达式放入 **反引号** 中。例如：
    
    <div><div><div>```
    frame`padzero(5, $F)`.pic
    ```
    
    </div></div></div>…可以给你像 `frame00001.pic`, `frame00002.pic`, 这样的文件名，诸如此类。

</div></div>（浏览 [expressions in filenames](http://www.sidefx.com/docs/houdini/render/expressions.html "How to use variables and expressions in file path fields to generate numbered and unique filenames.") 了解在文件名中使用表达式和变量）。

## 变量和属性

你的表达式可以使用 Houdini 提供的变量：

<div id="bkmrk-%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%C2%A0%E6%AF%94%E5%A6%82"><div>- **全局变量** 比如 `$F` (the current frame number) 和 `$T` (the current time in seconds). 详情见 [list of global variables](http://www.sidefx.com/docs/houdini/network/expressions.html#globals) （全局变量表格）。
- **几何体属性 -** 在几何体的 HScript 表达式中，你可以用 `@属性名称` 引用几何属性的值。比如，你可以用 `@pscale` 获取到当前点的 `pscale` (点缩放) 属性。
- 对于像 `P` (position) 这样的**矢量属性**，你可以用点表示法来抓取其中一个值，例如 `@P.x` 。你可以用 `.x/.y/.z` 或者 `.1/.2/.3` 或 `.r/.g/.b`。
- **本地变量。**节点通常会提供与节点类型相同的变量，对表达式很有用。比如，一个操纵几何体Point（点）的节点会提供 `@ptnum` 变量输出当前点的编号。节点帮助文档将会列出所有可用变量。
- **环境变量** 例如 `$HIP` （场景文件所在的目录）也可以被表达式使用。

</div></div>## 通道/参数引用

在 HScript 中你可以用 [ch](http://www.sidefx.com/docs/houdini/expressions/ch.html "Returns the value of a parameter.") 函数引用节点中的参数的值。这可以用来让一个节点中的数字随着另外一个节点发生改变。

<p class="callout info">你可以创建自己的参数并引用它。详见 [spare parameters](http://www.sidefx.com/docs/houdini/network/spare.html "How to add extra parameters to an individual node.").（备用参数）</p>

<div id="bkmrk-%E8%A6%81...-%E8%BF%99%E6%A0%B7%E5%81%9A-%E8%87%AA"><div><table class="tasks" style="width: 810px;"><tbody><tr><th style="width: 110.5px;">要...</th><th style="width: 696.5px;">这样做</th></tr><tr><td class="label task-desc " style="width: 110.5px;">自动创建参数引用

</td><td class="content task-howto " style="width: 696.5px;">1. 源参数上右键选择 **Copy parameter**.（复制参数）
2. 目标参数上右键选择 **Paste relative reference**.（粘贴对应参数）
    
    Houdini 会输入正确的 `ch("")` 语法让后一个参数引用前一个参数的值。

</td></tr><tr><td class="label task-desc " style="width: 110.5px;">手动创建通道引用

</td><td class="content task-howto " style="width: 696.5px;">用 HScrpt 表达式时，使用 [ch](http://www.sidefx.com/docs/houdini/expressions/ch.html "Returns the value of a parameter.") 获得另外一个参数的值。

 `ch` 会从当前节点的（可能的相对）路径到参数。 比如，要得到当前节点的 Z 变换属性：

<div>```
<span class="line"><span class="nb">ch</span><span class="o">(</span><span class="s2">"tz"</span><span class="o">)</span>
</span>
```

</div>获得 `lamp` 物体的 X 变换属性：

<div>```
<span class="line"><span class="nb">ch</span><span class="o">(</span><span class="s2">"/obj/lamp/tx"</span><span class="o">)</span>
</span>
```

</div>获得处于相同网络的 `grid1` 节点的 Y 旋转属性：

<div>```
<span class="line"><span class="nb">ch</span><span class="o">(</span><span class="s2">"../grid1/ry"</span><span class="o">)</span>
</span>
```

</div>(要获得字符串的值，使用 [chs](http://www.sidefx.com/docs/houdini/expressions/chs.html "Evaluates the string value of a parameter at the current time.").)

</td></tr><tr><td class="label task-desc " style="width: 110.5px;">查询参数的内部名称

</td><td class="content task-howto " style="width: 696.5px;">要手动引用参数，你必须知道参数的内部名称，你可以将鼠标悬停在参数框上方 或 通过参数编辑器中的 **设置** **▸ 编辑参数** 界面 **，**点击参数然后查看 **Name** 区域。

</td></tr></tbody></table>

</div></div>## 提示

在几何节点中使用 HScript表达式和本地变量 在参数中修改几何体很容易。但是，在 [Point Wrangle（点围栏）](http://www.sidefx.com/docs/houdini/nodes/sop/pointwrangle.html)或 [Attribute Wrangle（属性围栏）](http://www.sidefx.com/docs/houdini/nodes/sop/attribwrangle.html "Runs a VEX snippet to modify attribute values.")中通过 [VEX snippet](http://www.sidefx.com/docs/houdini/vex/snippets.html) 修改几何体的 **性能更高**。

未来的版本中会更鼓励使用 VEX短代码 修改几何体。

你可以通过 **Window ▸ HScript Textport** 输入下面的命令查看一个表达式的值：

<div id="bkmrk-echo-%60expression%60%C2%A0"><div><div><div>```
<span class="line"><span class="nb">echo</span> <span class="sb">`expression`</span></span> 
```

</div></div></div></div>Houdini 总是用网络（Network）的“配方”“从头开始”创建每一帧。表达式总是使用初始值 而不是前一帧的值来操作数值。

例如，如果你设置了一个 [Point geometry node](http://www.sidefx.com/docs/houdini/nodes/sop/point.html "Manually adds or edits point attributes.")（点几何节点）给网格中的每个点添加随机的 Y 偏移值：

<div id="bkmrk-position-y-%40p.y-%2B-ra"><div><div><div><table class="table" style="width: 789px;"><tbody><tr><th style="width: 128.297px;">Position Y

</th><td style="width: 659.703px;"><div>```
@P.y + rand(@Frame * @ptnum)
```

</div></td></tr></tbody></table>

</div></div></div></div>…当你回放时，点将上下随机跳跃，而不是平滑运动。这是因为每一帧时，网格都会从平整的网格开始，然后再应用随机移动给它。这个表达式不会从前一帧的几何体状态开始运行。

## HScript表达式的括号用法

<div id="bkmrk-%E5%AD%97%E7%AC%A6%E4%B8%B2-%E5%9C%A8%E5%8D%95%E5%BC%95%E5"><section class="heading pull left ">### 字符串

在单引号 (`'`) 中的字符is not expanded. Text inside double quotes (`"`) has variables expanded. A double-quoted string is considered one argument.

A backslash character (`\`) escapes the next character. For example, to use double-quotes in a string:

<div><div><div>```
"I had a \"great\" time."
```

</div></div></div>When a string doesn’t require variable expansion, use single quotes to speed up evaluation.

If you have two quoted strings next to each other with no spaces, they are considered a single argument. In this example…

<div><div><div>```
set foo = "Hello world"
echo '$foo='"$foo"
$foo=Hello world
```

</div></div></div>…the echo command has one argument: `'$foo=Hello world'`.

</section><section class="heading pull left ">### Embedding

In the HScript command language, text inside backticks is evaluated as an expression. For example:

<div><div><div>```
echo `strlen("$foo")`
```

</div><div><div></div></div></div></div>Tip

Scripting using the HScript command language is deprecated. You should use [Python](http://www.sidefx.com/docs/houdini/hom/index.html "How to script Houdini using Python and the Houdini Object Model.") instead.

The string parser cannot decode nested quotes such as in the following (horribly contrived) example:

<div><div><div>```
echo `system("echo `ls`")`
```

</div></div></div>…however, it is possible to accomplish this with very careful usage of backquotes (and sometimes multiple backquotes in a row) to protect quote symbols from various levels of evaluation:

<div><div>```
echo `system('echo \`ls\`')`
```

</div></div></section></div>