Difference between revisions of "Reference:Declare and Local Directives"

From POV-Wiki
Jump to navigation Jump to search
(→‎Identifier Name Collisions: added global() and local() pseudo-functions)
m (Precision about 40 char limited version number)
 
(9 intermediate revisions by 2 users not shown)
Line 8: Line 8:
 
changes many values. There are several built-in identifiers which POV-Ray
 
changes many values. There are several built-in identifiers which POV-Ray
 
declares for you. See the sections: [[Reference:Numeric Expressions#Built-in Variables|:Float, built-in variables|Built-in Variables]] and [[Reference:Numeric Expressions#Built-in Constants|:Vector, built-in identifiers|Built-in Vector Identifiers]] for details.</p>
 
declares for you. See the sections: [[Reference:Numeric Expressions#Built-in Variables|:Float, built-in variables|Built-in Variables]] and [[Reference:Numeric Expressions#Built-in Constants|:Vector, built-in identifiers|Built-in Vector Identifiers]] for details.</p>
 +
 +
==Declaring identifiers==
 
{{#indexentry:Identifiers, declaring}}
 
{{#indexentry:Identifiers, declaring}}
 
{{#indexentry:Directives, language, identifiers}}
 
{{#indexentry:Directives, language, identifiers}}
 
{{#indexentry:#declare}}
 
{{#indexentry:#declare}}
 
{{#indexentry:declare}}
 
{{#indexentry:declare}}
==Declaring identifiers==
 
 
<p>An identifier is declared as follows.</p>
 
<p>An identifier is declared as follows.</p>
 
<pre>
 
<pre>
Line 26: Line 27:
 
</pre>
 
</pre>
 
<p class="Note"><strong>Note:</strong> See the section on [[Reference:Declare and Local Directives#Deprecation Support|Deprecation Support]] for more information</p>
 
<p class="Note"><strong>Note:</strong> See the section on [[Reference:Declare and Local Directives#Deprecation Support|Deprecation Support]] for more information</p>
<p>Where <em>IDENTIFIER</em> is the name of the identifier up to 40
+
<p>Where <em>IDENTIFIER</em> is the name of the identifier that is at least one character long and <em>RVALUE</em> is any of the listed items.</p>
characters long and <em>RVALUE</em> is any of the listed items. They are
+
<p>The syntax for each is in the corresponding section of this language reference.</p>
called that because they are values that can appear to the <em>right</em> of
+
<p class="Note"><strong>Note:</strong> In versions prior to 3.6.2, identifier names <em>were</em> limited to 40 characters. There has been a {{Change}} removing that restriction.</p>
the equals sign. The syntax for each is in the corresponding section of this
+
<p>Here are some examples.</p>
language reference. Here are some examples.</p>
 
 
<pre>
 
<pre>
 
#declare Rows = 5;
 
#declare Rows = 5;
Line 50: Line 50:
 
</pre>
 
</pre>
  
<p class="Note"><strong>Note:</strong> There should be a semi-colon after the expression in all float,
+
<p class="Note"><strong>Note:</strong> There should be a semi-colon after the expression in all float,vector and color identifier declarations. This semi-colon is introduced in POV-Ray v3.1. If omitted, it generates a warning and some macros may not work properly. Semicolons after other declarations are optional.</p>
vector and color identifier declarations. This semi-colon is introduced in POV-Ray
+
<p>Declarations, like most language directives, can appear almost anywhere in the file, even within other statements. For example:</p>
version 3.1. If omitted, it generates a warning and some macros may not work
 
properly. Semicolons after other declarations are optional.</p>
 
<p>
 
Declarations, like most language directives, can appear almost anywhere in the file
 
- even within other statements. For example:</p>
 
 
<pre>
 
<pre>
 
#declare Here=&lt;1,2,3&gt;;
 
#declare Here=&lt;1,2,3&gt;;
Line 69: Line 64:
 
</pre>
 
</pre>
  
<p>As this example shows, you can re-declare an identifier and may use
+
<p>As this example shows, you can re-declare an identifier and may use previously declared values in that re-declaration.</p>
previously declared values in that re-declaration.</p>
+
<p class="Note"><strong>Note:</strong> Object identifiers use the generic wrapper statement <code>object{</code> ... <code>}</code>. You do not need to know what kind of object it is.</p>
<p class="Note"><strong>Note:</strong> Object identifiers use the generic wrapper statement <code>
+
<p>Declarations may be nested inside each other within limits. In the example in the previous section you could declare the entire union as a object. However for technical reasons there are instances where you may not use any language directive inside the declaration of floats, vectors or color expressions. Although these limits have been loosened somewhat since POV-Ray
object{</code> ... <code>}</code>. You do not need to know what kind of
+
v3.1, they still exist.</p>
object it is.</p>
+
<p>Identifiers declared within <code>[[Reference:User Defined Macros#The macro Directive|:#macro|#macro]]</code> ...
<p>
+
<code>[[Reference:Conditional Directives#The if...else...end Directives|:#end|#end]]</code> blocks are not created at the time the macro is defined. They are only created at the time the macro is actually invoked. Like all other items inside such a <code>#macro</code> definition, they are ignored when the macro is defined.</p>
Declarations may be nested inside each other within limits. In the example
+
 
in the previous section you could declare the entire union as a object.
+
<p>To help simplify passing multiple values out of a macro {{New}} tuple-style syntax extensions have been added to the <code>#declare</code> and <code>#local</code> directives:</p>
However for technical reasons there are instances where you may not use any
+
 
language directive inside the declaration of floats, vectors or color
+
<pre>
expressions. Although these limits have been loosened somewhat since POV-Ray
+
#declare ( ID1, ID2, ...) = ( EXPR1, EXPR2, ... );
3.1, they still exist.</p>
+
 
<p>
+
//This statement is fully equivalent to:
Identifiers declared within <code>[[Reference:User Defined Macros#The macro Directive|:#macro|#macro]]</code> ...
+
#declare ID1 = EXPR1;
<code>[[Reference:Conditional Directives#The if...else...end Directives|:#end|#end]]</code> blocks are not created at the time the macro is defined. They are only created at the time the macro is  
+
#declare ID1 = EXPR2;
actually invoked. Like all other items inside such a #macro definition,  
+
</pre>
they are ignored when the macro is defined.</p>
+
 
 +
<p class="Note"><strong>Note:</strong> This equivalence holds true even for constructs like <code>#declare (A,B) = (B,A);</code> which does <em>not</em> swap the contents of A and B as you might expect. The terminating semicolon is <strong><em>optional</em></strong>.</p>
 +
 
 +
<p>In addition, a similar syntax extension has been added for easier assignment of vector components to individual variables:</p>
 +
 
 +
<pre>
 +
// Is this valid? ie: &lt; and &gt; if so just remove this line
 +
#declare &lt; ID1, ID2, ... &gt; = VECTOR_EXPR;
 +
 
 +
//This statement is fully equivalent to:
 +
#local TEMP = VECTOR_EXPR;
 +
#declare ID1 = TEMP.x;
 +
#declare IDY = TEMP.y;
 +
</pre>
 +
 
 +
<p class="Note"><strong>Note:</strong> The new syntax does <em>not</em> actually define the local variable <em>TEMP</em>. The terminating semicolon is <strong><em>mandatory</em></strong>.</p>
 +
 
 +
<p>The <code>#local</code> statement syntax has also been extended accordingly. The <code>deprecated</code> keyword can be used with these new syntax variants by placing it right before the respective identifier:</p>
 +
 
 +
<pre>
 +
#declare (A, deprecated B) = (47, 11);
 +
</pre>
 +
 
 +
<p>Extended <code>#declare</code> and <code>#local</code> tuple syntax to also support assignment from arrays, and to support assignment to mismatching number of identifiers. Using ...</p>
 +
 
 +
<pre>
 +
#declare { IDENTIFIER_LIST } = ARRAY_EXPRESSION
 +
</pre>
 +
 
 +
<p>... will assign the first elements of the array expression (either an array identifier or an array declaration <em>with</em> initializer) to the given identifiers. The IDENTIFIER_LIST may now contain empty elements, in which case the corresponding element from the right-hand side will be skipped accordingly.</p>
 +
 
 +
<p>Extended tuple assignment syntax to allow for omission of right-hand side elements; extend array initializer syntax to allow for omission of elements.</p>
 +
 
 +
<p>Left-hand side elements in tuple assignments can now be prepended with the <code>optional</code> keyword. If an element is flagged this way, or left empty, the corresponding right-hand side element may be an uninitialized identifier or left empty. In this case, the respective left-hand side element remains unchanged (it is NOT undefined).</p>
 +
 
 +
<p>An array initializer may now be prepended with the <code>optional</code> keyword ...</p>
 +
 
 +
<pre>
 +
#declare A = array[10] optional { ... }
 +
</pre>
 +
 
 +
<p>... in this case, each individual element of the initializer may be an uninitialized identifier or left empty.</p>
 +
 
 +
<p class="Note"><strong>Note:</strong> Due to parser limitations, <em>uninitialized identifiers</em> do <em>not</em> encompass uninitialized array elements. This limitation also applies to optional macro parameters.</p>
  
 +
==declare vs. local==
 
{{#indexentry:Directives, language, #declare vs. #local}}
 
{{#indexentry:Directives, language, #declare vs. #local}}
==declare vs. local==
 
 
<p>Identifiers may be declared either global using <code>[[Reference:Declare and Local Directives#Declaring identifiers|:#declare|#declare]]</code> or local using the <code>[[Reference:Declare and Local Directives#Declaring identifiers|:#local|#local]]</code> directive.</p>
 
<p>Identifiers may be declared either global using <code>[[Reference:Declare and Local Directives#Declaring identifiers|:#declare|#declare]]</code> or local using the <code>[[Reference:Declare and Local Directives#Declaring identifiers|:#local|#local]]</code> directive.</p>
 
<p>
 
<p>
Line 123: Line 161:
 
Local identifiers may be specifically released early using <code>[[Reference:Declare and Local Directives#Destroying Identifiers with undef|:#undef|#undef]]</code> but in general there is no need to do so. See [[Reference:Declare and Local Directives#Destroying Identifiers with undef|:#undef|Destroying Identifiers]].</p>
 
Local identifiers may be specifically released early using <code>[[Reference:Declare and Local Directives#Destroying Identifiers with undef|:#undef|#undef]]</code> but in general there is no need to do so. See [[Reference:Declare and Local Directives#Destroying Identifiers with undef|:#undef|Destroying Identifiers]].</p>
  
 +
==Identifier Name Collisions==
 
{{#indexentry:Directives, name collisions}}
 
{{#indexentry:Directives, name collisions}}
 
==Identifier Name Collisions==
 
 
<p>Local identifiers may have the same names as previously declared
 
<p>Local identifiers may have the same names as previously declared
 
identifiers. In this instance, the most recent, most local identifier takes
 
identifiers. In this instance, the most recent, most local identifier takes
Line 166: Line 203:
 
<p>The main version of <code>A</code> is hidden and a new <code>A</code> is
 
<p>The main version of <code>A</code> is hidden and a new <code>A</code> is
 
created. This new <code>A</code> is also available inside <code>
 
created. This new <code>A</code> is also available inside <code>
MyMacro</code> because <code>MyMacro</code> is nested inside <code>
+
MyMacro</code> because <code>MyMacro</code> is called from inside <code>
 
myinc.inc</code>. Once you exit <code>myinc.inc</code>, the local <code>
 
myinc.inc</code>. Once you exit <code>myinc.inc</code>, the local <code>
 
A</code> is destroyed and the original <code>A</code> with its value of
 
A</code> is destroyed and the original <code>A</code> with its value of
Line 235: Line 272:
 
identifiers and &quot;most recent&quot; for existing identifiers.</p>
 
identifiers and &quot;most recent&quot; for existing identifiers.</p>
  
{{#indexentry:keyword, global, function}}
+
<p>{{New}} in version 3.8: To circumvent the pitfalls of identifier name collisions, two <em>pseudo-dictionaries</em> are provided to specifically refer to identifiers at either the global or the most local scope. See also the [[Reference:Array|Array]] section for more information.</p>
{{#indexentry:keyword, local, function}}
 
{{#indexentry:global, function}}
 
{{#indexentry:local, function}}
 
<p>{{New.3.7.1}} To circumvent the pitfalls of identifier name collisions,
 
two pseudo-functions are provided to specifically refer to identifiers
 
at either the global or the most local scope:</p>
 
<pre>
 
IDENTIFIER:
 
  GLOBAL_IDENTIFIER | LOCAL_IDENTIFIER | GENERIC_IDENTIFIER
 
GLOBAL_IDENTIFIER:
 
  global ( GENERIC_IDENTIFIER )
 
LOCAL_IDENTIFIER:
 
  local ( GENERIC_IDENTIFIER )
 
</pre>
 
<p>Both pseudo-functions can be used anywhere an identifier is allowed.
 
They do not simply retrieve the cooresponding value, but refer to the
 
identifiers themselves, allowing for constructs like the following:</p>
 
<pre>
 
#ifdef(local(Foo))
 
  #declare global(Foo) = Foo;
 
#else
 
  #undef global(Foo)
 
#end
 
</pre>
 
<p>This example tests whether the identifier <code>Foo</code> is in use
 
at the most local scope, and if so, copies its value to the global variable
 
of the same name; otherwise, it discards any value the global variable may
 
have held before.
 
</p>
 
  
 +
==Destroying Identifiers with undef==
 
{{#indexentry:Identifiers, destroying}}
 
{{#indexentry:Identifiers, destroying}}
 
{{#indexentry:Directives, language, identifiers, destroying}}
 
{{#indexentry:Directives, language, identifiers, destroying}}
Line 271: Line 280:
 
{{#indexentry:#undef}}
 
{{#indexentry:#undef}}
 
{{#indexentry:undef}}
 
{{#indexentry:undef}}
 
==Destroying Identifiers with undef==
 
 
<p>Identifiers created with <code>#declare</code> will generally persist until parsing is complete. Identifiers created with <code>#local</code> will persist until the end of the macro or include file in which they were created. You may however un-define an identifier using the <code>#undef</code> directive. For example:</p>
 
<p>Identifiers created with <code>#declare</code> will generally persist until parsing is complete. Identifiers created with <code>#local</code> will persist until the end of the macro or include file in which they were created. You may however un-define an identifier using the <code>#undef</code> directive. For example:</p>
 
<pre>
 
<pre>
Line 280: Line 287:
 
<p>See also [[Reference:Conditional Directives#The ifdef and ifndef Directives|:#ifdef|The #ifdef and #ifndef Directives]].</p>
 
<p>See also [[Reference:Conditional Directives#The ifdef and ifndef Directives|:#ifdef|The #ifdef and #ifndef Directives]].</p>
  
 +
==Deprecation Support==
 
{{#indexentry:deprecated}}
 
{{#indexentry:deprecated}}
==Deprecation Support==
 
 
<p>The ability to add a <code>deprecated</code> flag to a <code>#declare</code> has been added. This is to aid in migrating scenes away from old constructs (e.g. old textures). The usage is illustrated below:</p>
 
<p>The ability to add a <code>deprecated</code> flag to a <code>#declare</code> has been added. This is to aid in migrating scenes away from old constructs (e.g. old textures). The usage is illustrated below:</p>
 
<pre>
 
<pre>

Latest revision as of 20:47, 2 July 2021

Identifiers may be declared and later referenced to make scene files more readable and to parameterize scenes so that changing a single declaration changes many values. There are several built-in identifiers which POV-Ray declares for you. See the sections: Built-in Variables and Built-in Vector Identifiers for details.

Declaring identifiers

An identifier is declared as follows.

DECLARATION:
  #declare [deprecated] IDENTIFIER = RVALUE |
  #local [deprecated] IDENTIFIER = RVALUE
RVALUE:
  FLOAT; | VECTOR; | COLOR; | STRING | OBJECT | TEXTURE |
  PIGMENT | NORMAL | FINISH | INTERIOR | MEDIA | DENSITY |
  COLOR_MAP | PIGMENT_MAP | SLOPE_MAP | NORMAL_MAP |
  DENSITY_MAP | CAMERA | LIGHT_SOURCE | FOG | RAINBOW |
  SKY_SPHERE | TRANSFORM

Note: See the section on Deprecation Support for more information

Where IDENTIFIER is the name of the identifier that is at least one character long and RVALUE is any of the listed items.

The syntax for each is in the corresponding section of this language reference.

Note: In versions prior to 3.6.2, identifier names were limited to 40 characters. There has been a Change removing that restriction.

Here are some examples.

#declare Rows = 5;
#declare Count = Count+1;
#local  Here = <1,2,3>;
#declare White = rgb <1,1,1>;
#declare Cyan = color blue 1.0 green 1.0;
#declare Font_Name = "ariel.ttf"
#declare Rod = cylinder {-5*x,5*x,1}
#declare Ring = torus {5,1}
#local  Checks = pigment { checker White, Cyan }

object { Rod scale y*5 } // not "cylinder { Rod }"
object {
  Ring
  pigment { Checks scale 0.5 }
  transform Skew
  }

Note: There should be a semi-colon after the expression in all float,vector and color identifier declarations. This semi-colon is introduced in POV-Ray v3.1. If omitted, it generates a warning and some macros may not work properly. Semicolons after other declarations are optional.

Declarations, like most language directives, can appear almost anywhere in the file, even within other statements. For example:

#declare Here=<1,2,3>;
#declare Count=0;               // initialize Count
  union {
    object { Rod translate Here*Count }
    #declare Count=Count+1;     // re-declare inside union
    object { Rod translate Here*Count }
    #declare Count=Count+1;     // re-declare inside union
    object { Rod translate Here*Count }
    }

As this example shows, you can re-declare an identifier and may use previously declared values in that re-declaration.

Note: Object identifiers use the generic wrapper statement object{ ... }. You do not need to know what kind of object it is.

Declarations may be nested inside each other within limits. In the example in the previous section you could declare the entire union as a object. However for technical reasons there are instances where you may not use any language directive inside the declaration of floats, vectors or color expressions. Although these limits have been loosened somewhat since POV-Ray v3.1, they still exist.

Identifiers declared within #macro ... #end blocks are not created at the time the macro is defined. They are only created at the time the macro is actually invoked. Like all other items inside such a #macro definition, they are ignored when the macro is defined.

To help simplify passing multiple values out of a macro New tuple-style syntax extensions have been added to the #declare and #local directives:

#declare ( ID1, ID2, ...) = ( EXPR1, EXPR2, ... );

//This statement is fully equivalent to:
#declare ID1 = EXPR1;
#declare ID1 = EXPR2;

Note: This equivalence holds true even for constructs like #declare (A,B) = (B,A); which does not swap the contents of A and B as you might expect. The terminating semicolon is optional.

In addition, a similar syntax extension has been added for easier assignment of vector components to individual variables:

// Is this valid? ie: < and > if so just remove this line
#declare < ID1, ID2, ... > = VECTOR_EXPR;

//This statement is fully equivalent to:
#local TEMP = VECTOR_EXPR;
#declare ID1 = TEMP.x;
#declare IDY = TEMP.y;

Note: The new syntax does not actually define the local variable TEMP. The terminating semicolon is mandatory.

The #local statement syntax has also been extended accordingly. The deprecated keyword can be used with these new syntax variants by placing it right before the respective identifier:

#declare (A, deprecated B) = (47, 11);

Extended #declare and #local tuple syntax to also support assignment from arrays, and to support assignment to mismatching number of identifiers. Using ...

#declare { IDENTIFIER_LIST } = ARRAY_EXPRESSION

... will assign the first elements of the array expression (either an array identifier or an array declaration with initializer) to the given identifiers. The IDENTIFIER_LIST may now contain empty elements, in which case the corresponding element from the right-hand side will be skipped accordingly.

Extended tuple assignment syntax to allow for omission of right-hand side elements; extend array initializer syntax to allow for omission of elements.

Left-hand side elements in tuple assignments can now be prepended with the optional keyword. If an element is flagged this way, or left empty, the corresponding right-hand side element may be an uninitialized identifier or left empty. In this case, the respective left-hand side element remains unchanged (it is NOT undefined).

An array initializer may now be prepended with the optional keyword ...

#declare A = array[10] optional { ... }

... in this case, each individual element of the initializer may be an uninitialized identifier or left empty.

Note: Due to parser limitations, uninitialized identifiers do not encompass uninitialized array elements. This limitation also applies to optional macro parameters.

declare vs. local

Identifiers may be declared either global using #declare or local using the #local directive.

Those created by the #declare directive are permanent in duration and global in scope. Once created, they are available throughout the scene and they are not released until all parsing is complete or until they are specifically released using #undef. See Destroying Identifiers.

Those created by the #local directive are temporary in duration and local in scope. They temporarily override any identifiers with the same name. See Identifier Name Collisions.

If #local is used inside a #macro then the identifier is local to that macro. When the macro is invoked and the #local directive is parsed, the identifier is created. It persists until the #end directive of the macro is reached. At the #end directive, the identifier is destroyed. Subsequent invocations of the macro create totally new identifiers.

Use of #local within an include file but not in a macro, also creates a temporary identifier that is local to that include file. When the include file is included and the #local directive is parsed, the identifier is created. It persists until the end of the include file is reached. At the end of file the identifier is destroyed. Subsequent inclusions of the file create totally new identifiers.

Use of #local in the main scene file (not in an include file and not in a macro) is identical to #declare. For clarity sake you should not use #local in a main file except in a macro.

There is currently no way to create permanent, yet local identifiers in POV-Ray.

Local identifiers may be specifically released early using #undef but in general there is no need to do so. See Destroying Identifiers.

Identifier Name Collisions

Local identifiers may have the same names as previously declared identifiers. In this instance, the most recent, most local identifier takes precedence. Upon entering an include file or invoking a macro, a new symbol table is created. When referencing identifiers, the most recently created symbol table is searched first, then the next most recent and so on back to the global table of the main scene file. As each macro or include file is exited, its table and identifiers are destroyed. Parameters passed by value reside in the same symbol table as the one used for identifiers local to the macro.

The rules for duplicate identifiers may seem complicated when multiple-nested includes and macros are involved, but in actual practice the results are generally what you intended.

Consider this example: You have a main scene file called myscene.pov and it contains

#declare A = 123;
#declare B = rgb<1,2,3>;
#declare C = 0;
#include "myinc.inc"

Inside the include file you invoke a macro called MyMacro(J,K,L). It is not important where MyMacro is defined as long as it is defined before it is invoked. In this example, it is important that the macro is invoked from within myinc.inc.

The identifiers A, B, and C are generally available at all levels. If either myinc.inc or MyMacro contain a line such as #declare C=C+1; then the value C is changed everywhere as you might expect.

Now suppose inside myinc.inc you do...

#local A = 546;

The main version of A is hidden and a new A is created. This new A is also available inside MyMacro because MyMacro is called from inside myinc.inc. Once you exit myinc.inc, the local A is destroyed and the original A with its value of 123 is now in effect. Once you have created the local A inside myinc.inc, there is no way to reference the original global A unless you #undef A or exit the include file. Using #undef always undefines the most local version of an identifier.

Similarly if MyMacro contained...

#local B = box{0,1}

then a new identifier B is created local to the macro only. The original value of B remains hidden but is restored when the macro is finished. The local B need not have the same type as the original.

The complication comes when trying to assign a new value to an identifier at one level that was declared local at an earlier level. Suppose inside myinc.inc you do...

#local D = 789;

If you are inside myinc.inc and you want to increment D by one, you might try to do...

#local D = D + 1;

but if you try to do that inside MyMacro you will create a new D which is local to MyMacro and not the D which is external to MyMacro but local to myinc.inc. Therefore you've said "create a MyMacro D from the value of myinc.inc's D plus one". That's probably not what you wanted. Instead you should do...

#declare D = D + 1;

You might think this creates a new D that is global but it actually increments the myinc.inc version of D. Confusing isn't it? Here are the rules:

  1. When referencing an identifier, you always get the most recent, most local version. By "referencing" we mean using the value of the identifier in a POV-Ray statement or using it on the right of an equals sign in either a #declare or #local.
  2. When declaring an identifier using the #local keyword, the identifier which is created or has a new value assigned, is ALWAYS created at the current nesting level of macros or include files.
  3. When declaring a NEW, NON-EXISTANT identifier using #declare, it is created as fully global. It is put in the symbol table of the main scene file.
  4. When ASSIGNING A VALUE TO AN EXISTING identifier using #declare, it assigns it to the most recent, most local version at the time.

In summary, #local always means "the current level", and #declare means "global" for new identifiers and "most recent" for existing identifiers.

New in version 3.8: To circumvent the pitfalls of identifier name collisions, two pseudo-dictionaries are provided to specifically refer to identifiers at either the global or the most local scope. See also the Array section for more information.

Destroying Identifiers with undef

Identifiers created with #declare will generally persist until parsing is complete. Identifiers created with #local will persist until the end of the macro or include file in which they were created. You may however un-define an identifier using the #undef directive. For example:

#undef MyValue

If multiple local nested versions of the identifier exist, the most local most recent version is deleted and any identically named identifiers which were created at higher levels will still exist.

See also The #ifdef and #ifndef Directives.

Deprecation Support

The ability to add a deprecated flag to a #declare has been added. This is to aid in migrating scenes away from old constructs (e.g. old textures). The usage is illustrated below:

#declare deprecated Col_Glass_Old=color rgbf <0.8, 0.9, 0.85, 0.85>;
#declare deprecated once Col_Glass_Old=... etc
#declare deprecated "Some message" Col_Glass_Old=... etc

A deprecated identifier generates no message at the time it is declared, a warning is only issued if it is used.

If the optional once keyword is present it must immediately follow the deprecated keyword and indicates that the warning should only be displayed once per parse.

If the optional message string is present, it will be used as the warning to be displayed if the identifier is used. Otherwise, a message in the form "Identifier Col_Glass_Old was declared deprecated." is used.

An identifier is considered used if it is referenced anywhere (even if in another #declare).