-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path_ff_scripting_manual.lua
988 lines (683 loc) · 43.1 KB
/
_ff_scripting_manual.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
---
title: Lua
layout: 2017/sheet
---
::= in this context means: `is defined as` and applies to the given element syntax. For example:
identifier ::= (letter|"_") (letter | digit | "_")*
Means all `identifiers` must conform to the given `syntax rule`. The symbol on the left must be replaced with the expression on the right. Sequences [of symbols] are separated by the vertical bar "|", indicating a choice, the whole being a possible substitution for the symbol on the left.
--[[
Backus–Naur form or Backus normal form (BNF) is a metasyntax notation for context-free grammars, often used to describe the syntax of languages used in computing, such as computer programming languages, document formats, instruction sets and communication protocols. It is applied wherever exact descriptions of languages are needed: for instance, in official language specifications, in manuals, and in textbooks on programming language theory.
As an example, consider this possible BNF for a U.S. postal address:
<postal-address> ::= <name-part> <street-address> <zip-part>
<name-part> ::= <personal-part> <last-name> <opt-suffix-part> <EOL> | <personal-part> <name-part>
<personal-part> ::= <initial> "." | <first-name>
<street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL>
<zip-part> ::= <town-name> "," <state-code> <ZIP-code> <EOL>
<opt-suffix-part> ::= "Sr." | "Jr." | <roman-numeral> | ""
<opt-apt-num> ::= <apt-num> | ""
This translates into English as:
A postal address consists of a name-part, followed by a street-address part, followed by a zip-code part.
A name-part consists of either: a personal-part followed by a last name followed by an optional suffix (Jr., Sr., or dynastic number) and end-of-line, or a personal part followed by a name part (this rule illustrates the use of recursion in BNFs, covering the case of people who use multiple first and middle names and initials).
A personal-part consists of either a first name or an initial followed by a dot.
A street address consists of a house number, followed by a street name, followed by an optional apartment specifier, followed by an end-of-line.
A zip-part consists of a town-name, followed by a comma, followed by a state code, followed by a ZIP-code followed by an end-of-line.
An opt-suffix-part consists of a suffix, such as "Sr.", "Jr." or a roman-numeral, or an empty string (i.e. nothing).
An opt-apt-num consists of an apartment number or an empty string (i.e. nothing).
Note that many things (such as the format of a first-name, apartment number, ZIP-code, and Roman numeral) are left unspecified here. If necessary, they may be described using additional BNF rules.
https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form
]]--
## Basic examples
### References
- <https://www.lua.org/pil/13.html>
- <http://lua-users.org/wiki/ObjectOrientedProgramming>
### Comments
-- comment
--[[ Multiline
comment ]]
### Invoking functions
print()
print("Hi")
-- You can omit parentheses if the argument is one string or table literal
print "Hello World" <--> print("Hello World")
dofile 'a.lua' <--> dofile ('a.lua')
print [[a multi-line <--> print([[a multi-line
message]] message]])
f{x=10, y=20} <--> f({x=10, y=20})
type{} <--> type({})
### Tables / arrays
t = {}
t = { a = 1, b = 2 }
t.a = function() ... end
t = { ["hello"] = 200 }
t.hello
-- Remember, arrays are also tables
array = { "a", "b", "c", "d" }
print(array[2]) -- "b" (one-indexed)
print(#array) -- 4 (length)
### Loops
while condition do
end
for i = 1,5 do
end
for i = start,finish,delta do
end
for k,v in pairs(tab) do
end
repeat
until condition
-- Breaking out:
while x do
if condition then break end
end
### Conditionals
if condition then
print("yes")
elseif condition then
print("maybe")
else
print("no")
end
### Variables
local x = 2
two, four = 2, 4
### Functions
function myFunction()
return 1
end
function myFunctionWithArgs(a, b)
-- ...
end
myFunction()
anonymousFunctions(function()
-- ...
end)
-- Not exported in the module
local function myPrivateFunction()
end
-- Splats
function doAction(action, ...)
print("Doing '"..action.."' to", ...)
--> print("Doing 'write' to", "Shirley", "Abed")
end
doAction('write', "Shirley", "Abed")
### Lookups
mytable = { x = 2, y = function() .. end }
-- The same:
mytable.x
mytable['x']
-- Syntactic sugar, these are equivalent:
mytable.y(mytable)
mytable:y()
mytable.y(mytable, a, b)
mytable:y(a, b)
function X:y(z) .. end
function X.y(self, z) .. end
## More concepts
### Metatables
mt = {}
-- A metatable is simply a table with functions in it.
mt.__tostring = function() return "lol" end
mt.__add = function(b) ... end -- a + b
mt.__mul = function(b) ... end -- a * b
mt.__index = function(k) ... end -- Lookups (a[k] or a.k)
mt.__newindex = function(k, v) ... end -- Setters (a[k] = v)
-- Metatables allow you to override behavior of another table.
mytable = {}
setmetatable(mytable, mt)
print(myobject)
### Classes
Account = {}
function Account:new(balance)
local t = setmetatable({}, { __index = Account })
-- Your constructor stuff
t.balance = (balance or 0)
return t
end
function Account:withdraw(amount)
print("Withdrawing "..amount.."...")
self.balance = self.balance - amount
self:report()
end
function Account:report()
print("Your current balance is: "..self.balance)
end
a = Account:new(9000)
a:withdraw(200) -- method call
### Constants
nil
false
true
## Operators (and their metatable names)
### Relational
-- Relational (binary)
-- __eq __lt __gt __le __ge
== < > <= >=
~= -- Not equal, just like !=
-- Arithmetic (binary)
-- __add __sub __muv __div __mod __pow
+ - * / % ^
-- Arithmetic (unary)
-- __unm (unary minus)
-
### Logic
-- Logic (and/or)
nil and false --> nil
false and nil --> false
0 and 20 --> 20
10 and 20 --> 20
### Tables
-- Length
-- __len(array)
#array
-- Indexing
-- __index(table, key)
t[key]
t.key
-- __newindex(table, key, value)
t[key]=value
-- String concat
-- __concat(left, right)
"hello, "..name
-- Call
-- __call(func, ...)
## API
Scripting API
This article describes what functions and variables are available to scripts in the Map Script and Curve Script components. All Filter Forge API functions (but not variables) are syntax-highlighted with orange in the script editor.
Availability of Standard Lua Libraries
Safe scripts (that is, scripts that have the Unsafe Script setting turned off in their Script Settings) are allowed to call Lua functions from the following standard Lua libraries:
String library.
Table library.
Math library. Note that math.random() and math.randomseed() functions cannot be called from script's get_sample() function, they can be called from prepare() only. This restriction applies to both safe and unsafe scripts.
Basic library, excluding the Coroutine library and dofile(), getfenv(), getmetatable(), load(), loadfile(), loadstring(), pcall(), rawequal(), rawget(), rawset(), setfenv(), setmetatable() and xpcall() functions.
Unsafe scripts are allowed to call all Lua functions from all standard Lua libraries.
API Variables
The scripts in Filter Forge can employ several global variables that let you query the value of the global Size and Variation sliders, the width and height of the working image and more. When referencing these variables from scripts, remember that Lua is case-sensitive, so the variable names must be written in uppercase, as shown in the list:
SIZE – the value of the global Size slider. Available only to scripts that have the Makes use of the global Size setting flag turned on in their Script Settings. Measured in pixels, but can assume non-integer values.
VARIATION – the value of the global Variation slider. Available only to scripts that have the Makes use of the global Variation setting flag turned on in their Script Settings.
OUTPUT_WIDTH and OUTPUT_HEIGHT – width and height of the image currently loaded into Filter Forge. Measured in pixels.
SEAMLESS_REGION_WIDTH and SEAMLESS_REGION_HEIGHT – width and height of the seamless region, i.e. the region in which the script must provide seamlessly-tiled output. Available only to scripts that have the Produces seamlessly-tiled results flag turned on in their Script Settings. Both variables are measured as a ratio to SIZE. For example, if SIZE is 300 pixels and the seamless region width is 450 pixels, the SEAMLESS_REGION_WIDTH variable will assume the value of 1.5.
SEAMLESS – the state of the global Seamless Tiling checkbox, either true or false. Available only to scripts that have the "Produces seamlessly-tiled results" flag turned on in their Script Settings.
API Functions for Referencing Custom Inputs
Filter Forge provides functions allowing you to query values of custom inputs added to a Map Script or Curve Script component via the Input Editor. Each input type (e.g. Slider, Checkbox etc.) has a corresponding query function. For information on input types and their corresponding functions, see Referencing Inputs from Scripts.
API Functions for Smart Anti-Aliasing
Filter Forge provides a combine_aa_zones() function that simplifies the process of combining anti-aliasing zones. For more information on this function and on handling anti-aliasing in scripts in general, see Implementing Smart Anti-Aliasing.
API Functions for Noises
Filter Forge provides a ... function that simplifies the process of .... For more information on this function and on using noise generation in scripts in general, see Noise API.
API Functions for Blending Modes
Filter Forge provides a ... function that simplifies the process of .... For more information on this function and on using blending modes in scripts, see Blending Modes API.
Writing to the Message Log
You can use the standard Lua error() function to write error messages to the Message Log. Note that calling this function terminates the script. Currently, there are no other ways to send messages to the Message Log without interrupting the script.
Copyright © 2006-2020 Filter Forge, Inc. All rights reserved.
### API: Global Functions
dofile("hello.lua")
loadfile("hello.lua")
assert(x) -- x or (raise an error)
assert(x, "failed")
type(var) -- "nil" | "number" | "string" | "boolean" | "table" | "function" | "thread" | "userdata"
-- Does /not/ invoke meta methods (__index and __newindex)
rawset(t, index, value) -- Like t[index] = value
rawget(t, index) -- Like t[index]
_G -- Global context
setfenv(1, {}) -- 1: current function, 2: caller, and so on -- {}: the new _G
pairs(t) -- iterable list of {key, value}
ipairs(t) -- iterable list of {index, value}
tonumber("34")
tonumber("8f", 16)
### API: Strings
'string'..'concatenation'
s = "Hello"
s:upper()
s:lower()
s:len() -- Just like #s
s:find()
s:gfind()
s:match()
s:gmatch()
s:sub()
s:gsub()
s:rep()
s:char()
s:dump()
s:reverse()
s:byte()
s:format()
### API: Tables
table.foreach(t, function(row) ... end)
table.setn
table.insert(t, 21) -- append (--> t[#t+1] = 21)
table.insert(t, 4, 99)
table.getn
table.concat
table.sort
table.remove(t, 4)
### API: Math
math.abs math.acos math.asin math.atan math.atan2
math.ceil math.cos math.cosh math.deg math.exp
math.floor math.fmod math.frexp math.ldexp math.log
math.log10 math.max math.min math.modf math.pow
math.rad math.random math.randomseed math.sin math.sinh
math.sqrt math.tan math.tanh
math.sqrt(144)
math
### API: Misc
io.output(io.open("file.txt", "w"))
io.write(x)
io.close()
for line in io.lines("file.txt")
file = assert(io.open("file.txt", "r"))
file:read()
file:lines()
file:close()
Filter Editor Menu and Hotkeys
File
Save Filter (Ctrl+S) Saves the current filter into the default folder in Custom Filters (usually My Filters). For details, see Saving and Renaming Filters in Using Filter Editor.
Save Filter As... (Ctrl+Shift+S) Saves a copy of the current filter into the default folder in Custom Filters (usually My Filters).
Save Image As... (Alt+S) Saves the rendered image to a file.
Render Animation... Opens the Render Animation dialog. This command is only available for animated filters. See Render Animation dialog.
Exit Filter Editor Exits the Filter Editor. You will be prompted to save any unsaved changes.
Edit
Undo (Ctrl+Z) Reverses the last performed operation.
Redo (Ctrl+Y) Reverses the results of the last Undo command.
Cut (Ctrl+X) Cuts the selected objects to the clipboard.
Copy (Ctrl+C) Copies the selected objects to the clipboard.
Paste (Ctrl+V) Pastes the objects from the clipboard. If nothing has been cut or copied, Paste is unavailable.
Delete (Del) Deletes the selected objects or clears the selected value in a text field.
Duplicate (Ctrl+D) Duplicates the selected components preserving their incoming connections.
Copy Image Copies the current rendering result to the system clipboard
Paste Image Loads an image from the system clipboard as a new source image
Group (Ctrl+G) Creates a new group from the selected components.
Ungroup (Shift+Ctrl+G) Ungroups the components inside the selected group.
Save As Snippet... Saves the selected group as a new snippet for later reuse.
Detach from Instancing Allows you to edit the group independently from other group copies.
Select Filter Controls (F) Selects the Filter Controls plaque under the Result component.
Select Subtree (Ctrl+T) Selects all components connected to inputs of the currently selected component.
Select All (Ctrl+A) Selects all objects on the Workspace.
Image
Blank... Opens a Blank Image dialog which creates a blank source image of the desired size, fill color and transparency.
Open... Loads a source image from a file. This command is available in the standalone mode only. See Image component.
Recent Images Shows the list of most recently opened images. Up to 9 recent files are listed.
Built-In Previews... Shows the list of factory images to be used as a source image.
Selection Loads a selection image from a file. See Selection component
Filter
Anti-aliasing Sets the level of anti-aliasing for the current filter. See Anti-Aliasing Menu.
Render Channels Allows you to render bump, diffuse, normal and other maps. See Render Channels Menu.
Edit Filter Info (Ctrl+I)... Opens the Filter Info dialog which allows you to fill in the information about the filter.
Order of Controls... Opens the Order of Controls dialog which allows you to customize the order of controls created by Control Components.
Overrides... Opens the Overrides dialog which allows you to manually override automatically-determined behavior of global filter controls.
Animation
Next Frame (]) Moves the Timeline playhead to the next frame. This command is only available for animated filters.
Previous Frame ([) Moves the Timeline playhead to the previous frame. This command is only available for animated filters.
10 Frames Forward (Shift+]) Moves the Timeline playhead 10 frames ahead. This command is only available for animated filters.
10 Frames Back (Shift+[) Moves the Timeline playhead 10 frames back. This command is only available for animated filters.
First Frame (Ctrl+Shift+[) Moves the Timeline playhead to the first frame. This command is only available for animated filters.
Last Frame (Ctrl+Shift+]) Moves the Timeline playhead to the last frame. This command is only available for animated filters.
View
Zoom In (Shift+Ctrl+Plus) Zooms the Preview in.
Zoom Out (Shift+Ctrl+Minus) Zooms the Preview out.
Actual Pixels (Shift+Ctrl+Alt+0) Sets the zoom level to 1:1 so that the image pixels correspond to screen pixels directly.
Zoom to Fit (Shift+Ctrl+0) Sets the zoom level so that the Preview shows the entire image.
Show Border (Ctrl+B) Shows or hides the borders of a seamless texture. If Seamless Tiling is turned off, this command is unavailable.
Lock Preview (Enter) Makes the Preview always show the output of the component it's locked to, regardless of the current selection.
Workspace Zoom In (Ctrl+Plus) Zooms the Workspace in.
Workspace Zoom Out (Ctrl+Minus) Zooms the Workspace out.
Workspace Actual Size (Ctrl+Alt+0) Sets the zoom level to 100% (actual size).
Workspace Zoom to Fit (Ctrl+0) Sets the zoom level so that you can see the entire filter tree at once.
Thumbnails Allows you to set the size of the component thumbnails: small, medium or large.
Move Subtree (M) When this option is turned on, moving a component also moves its entire subtree.
Snap to Grid When turned on, components are aligned to grid lines when moved.
Show Components (C) Shows or hides the Components Bar.
Show Message Log (Ctrl+L) Shows or hides the Message Log pane.
Find Components... (Ctrl+F) Opens the Components Bar and sets the focus to the component search field.
Help
Filter Forge Help (F1) Shows this help.
Filter Forge Website Opens the Filter Forge website.
Filter Forge Forums Opens the Filter Forge forums.
Contact Us Opens the Filter Forge contact form.
About... Shows the information about Filter Forge and its developers, as well as copyrights and legal notices.
Debugging & Error Handling
The Message Log
The built in message log (View > Show Message Log, Ctrl + L) lets you inspect the render time and possible errors. This is useful information when debugging and optimizing performance. An error in a script, or a loop, or with an Intlsider range automatically opens the Message Log. It can also be opened or closed via the View > Show Message Log menu command, or by pressing Ctrl+L. Additionally, it can be closed by pressing the Esc key.
Non-error messages are shown in gray, error messages are dark red. The most recent message is shown in bold.
If an error originates in a Script component double-clicking the error message in the Message Log takes you to the location where the error occurred: Filter Forge selects the script component that generated the error, opens its Script tab, and, if the message has a line number, positions the cursor at the appropriate line. Errors in Loop and IntSlider components are marked with a Connection Warning and cannot be located via double-clicking.
The contents of the Message Log are not saved between the Filter Editor sessions – the log resets every time you open the Filter Editor.
Error Handling
The "error" function can be used to stop the script execution (and rendering process as such). This is only way it is currently possible to write to the message log (see Advanced Debugging for another way to get debugging info out in a log file):
if (y == x) then
error("y equals x")
end
Like stated calling "error" will stop the rendering and throw a script error, which is not useful for debugging read-outs. The "error" function should be used for error handling with e.g. invalid input values in advanced scripts.
Advanced Debugging
Luckily the "error" function is not the only way to get some debugging info out. For more advanced debugging you can use the "print" function:
function prepare()
print("prepare was called")
end;
function get_sample(x, y)
print("get_sample was called")
return 1,1,1,1
end;
"Print" will NOT write to the built in message log. The print calls are written to a global log file with one of the following names (depending on OS/CPU target):
"Filter Forge x86-SSE2.log"
"Filter Forge x86.log"
"Filter Forge x64.log"
"Filter Forge universal.log" (Mac OS X)
On a Windows machine the file is located in "c:\Users\<your username>\AppData\Local\Temp\". 0r "%APPDATA%\Local\Temp\"
On Mac OSX the file is located in "/private/tmp/".
Here is some of the output from the above example:
Filter Forge x64 9.006.53910.27538 Release, December 30, 2019 09:50 [13-04-2020 10:44:24 +0200]
prepare was called
get_sample was called
get_sample was called
get_sample was called
get_sample was called
get_sample was called
get_sample was called
get_sample was called
get_sample was called
get_sample was called
get_sample was called
get_sample was called
...
You may notice that print calls from prepare is showing up multiple times. This is because "prepare" is called for every rendering block (and not once per "rendering session" like stated in the documentation). This issue is discussed here.
Note that Filter Forge will append every print call to this file, and it will grow quickly if you print something inside the get_sample function.
To prevent this file from growing in all eternity, Filter Forge clears the log file when starting up.
For additional information and questions, please see this forum thread: https://filterforge.com/forum/read.php?FID=18&TID=7525&MID=85607
Referencing Inputs from Scripts
https://www.filterforge.com/more/help/Scripting/ReferencingInputs.html
Input Type » Function » Call From
Color Map Inputs » r, g, b, a = get_sample_map(x, y, input_id) » get_sample()
Grayscale Map Inputs » v = get_sample_grayscale(x, y, input_id) » get_sample()
Slider Inputs » value = get_slider_input(input_id) » prepare()
Angle Inputs » angle = get_angle_input(input_id) » prepare()
Integer Slider Inputs » value = get_intslider_input(input_id) » prepare()
Checkbox Inputs » state = get_checkbox_input(input_id) » prepare()
Curve Inputs » c = get_sample_curve(x, y, t, input_id) » get_sample()
5.5 – Table Manipulation
This library provides generic functions for table manipulation. It provides all its functions inside the table table.
Most functions in the table library assume that the table represents an array or a list. For these functions, when we talk about the "length" of a table we mean the result of the length operator.
table.concat (table [, sep [, i [, j]]]):
Given an array where all elements are strings or numbers, returns table[i]..sep..table[i+1] ··· sep..table[j]. The default value for sep is the empty string, the default for i is 1, and the default for j is the length of the table. If i is greater than j, returns the empty string.
table.insert (table, [pos,] value):
Inserts element value at position pos in table, shifting up other elements to open space, if necessary. The default value for pos is n+1, where n is the length of the table (see §2.5.5), so that a call table.insert(t,x) inserts x at the end of table t.
table.maxn (table):
Returns the largest positive numerical index of the given table, or zero if the table has no positive numerical indices. (To do its job this function does a linear traversal of the whole table.):
table.remove (table [, pos]):
Removes from table the element at position pos, shifting down other elements to close the space, if necessary. Returns the value of the removed element. The default value for pos is n, where n is the length of the table, so that a call table.remove(t) removes the last element of table t.
table.sort (table [, comp]):
Sorts table elements in a given order, in-place, from table[1] to table[n], where n is the length of the table. If comp is given, then it must be a function that receives two table elements, and returns true when the first is less than the second (so that not comp(a[i+1],a[i]) will be true after the sort). If comp is not given, then the standard Lua operator < is used instead.
The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort.
5.6 – Mathematical Functions
This library is an interface to the standard C math library. It provides all its functions inside the table math.
math.abs (x):
Returns the absolute value of x.
math.acos (x):
Returns the arc cosine of x (in radians).
math.asin (x):
Returns the arc sine of x (in radians).
math.atan (x):
Returns the arc tangent of x (in radians).
math.atan2 (y, x):
Returns the arc tangent of y/x (in radians), but uses the signs of both parameters to find the quadrant of the result. (It also handles correctly the case of x being zero.):
math.ceil (x):
Returns the smallest integer larger than or equal to x.
math.cos (x):
Returns the cosine of x (assumed to be in radians).
math.cosh (x):
Returns the hyperbolic cosine of x.
math.deg (x):
Returns the angle x (given in radians) in degrees.
math.exp (x):
Returns the value ex.
math.floor (x):
Returns the largest integer smaller than or equal to x.
math.fmod (x, y):
Returns the remainder of the division of x by y that rounds the quotient towards zero.
math.frexp (x):
Returns m and e such that x = m2e, e is an integer and the absolute value of m is in the range [0.5, 1) (or zero when x is zero).
math.huge
The value HUGE_VAL, a value larger than or equal to any other numerical value.
math.ldexp (m, e):
Returns m2e (e should be an integer).
math.log (x):
Returns the natural logarithm of x.
math.log10 (x):
Returns the base-10 logarithm of x.
math.max (x, ···):
Returns the maximum value among its arguments.
math.min (x, ···):
Returns the minimum value among its arguments.
math.modf (x):
Returns two numbers, the integral part of x and the fractional part of x.
math.pi
The value of pi.
math.pow (x, y):
Returns xy. (You can also use the expression x^y to compute this value.):
math.rad (x):
Returns the angle x (given in degrees) in radians.
math.random ([m [, n]]):
This function is an interface to the simple pseudo-random generator function rand provided by ANSI C. (No guarantees can be given for its statistical properties.):
When called without arguments, returns a uniform pseudo-random real number in the range [0,1). When called with an integer number m, math.random returns a uniform pseudo-random integer in the range [1, m]. When called with two integer numbers m and n, math.random returns a uniform pseudo-random integer in the range [m, n].
math.randomseed (x):
Sets x as the "seed" for the pseudo-random generator: equal seeds produce equal sequences of numbers.
math.sin (x):
Returns the sine of x (assumed to be in radians).
math.sinh (x):
Returns the hyperbolic sine of x.
math.sqrt (x):
Returns the square root of x. (You can also use the expression x^0.5 to compute this value.):
math.tan (x):
Returns the tangent of x (assumed to be in radians).
math.tanh (x):
Returns the hyperbolic tangent of x.
•• Are there other function calls available to map scripts in Filter Forge that I should know about?
Yes, there are several other useful function calls available in Filter Forge map scripts. Here are some common ones:
• get_sample(x, y, channel) - Returns the value of a sample from the input image at the given x and y coordinates, in the specified channel (0 = red, 1 = green, 2 = blue, 3 = alpha). The coordinates are in the range 0 to 1.
• get_sample_map(channel) - Returns a map containing the values of the specified channel (0 = red, 1 = green, 2 = blue, 3 = alpha) for all pixels in the input image. The map can be modified and used as input for other functions.
interpolate(x, y, map) - Interpolates the value of a map at the given x and y coordinates. The coordinates are in the range 0 to 1. The map should be a result of get_sample_map.
•• Can you explain what this actually means?: 'Interpolates the value of a map at the given x and y coordinates. '
Sure! In the context of Filter Forge, a "map" refers to an image that is used to control various properties of a filter. For example, a map can be used to control the amount of blur applied to an image, or the intensity of a color adjustment.
When you interpolate the value of a map at a given x and y coordinate, you are essentially determining the color value of the map at that location. This is done by looking at the surrounding pixels of the map and using them to estimate the color value at the given coordinate.
The process of interpolation involves using mathematical techniques to estimate the value of a function (in this case, the color values of the map) between discrete data points. In Filter Forge, bilinear interpolation is commonly used to interpolate the value of a map at a given coordinate. This involves using the four surrounding pixels of the map to estimate the color value at the given coordinate.
In summary, when you interpolate the value of a map at a given x and y coordinate in Filter Forge, you are determining the color value of the map at that location by using surrounding pixels to estimate the value using mathematical techniques.
• math.sin(x), math.cos(x), math.tan(x) - Trigonometric functions.
• math.pow(x, y) - Returns x raised to the power of y.
• math.exp(x) - Returns e raised to the power of x.
• math.log(x) - Returns the natural logarithm of x.
• math.sqrt(x) - Returns the square root of x.
• math.abs(x) - Returns the absolute value of x.
• math.floor(x), math.ceil(x), math.round(x) - Rounding functions.
• table.concat(table, delimiter) - Concatenates the elements of a table into a string, using the specified delimiter.
There are many other functions available as well, including string manipulation functions, bitwise operators, and more. You can find a complete list of functions in the Filter Forge map script documentation.
•• I'm familiar with functions from the standard library. I'd like to know ones that are unique to Filter Forge.
Sure! Here are some functions unique to Filter Forge map scripts:
• get_sample_map(channel):
Returns the source image for the specified channel. channel should be one of the constants SOURCE_CHANNEL_RED, SOURCE_CHANNEL_GREEN, SOURCE_CHANNEL_BLUE, or SOURCE_CHANNEL_ALPHA.
• set_sample_map(channel, map):
Sets the source image for the specified channel to map. channel should be one of the constants listed above, and map should be a 2D array of pixel data.
• get_gradient_map(channel):
Returns the gradient image for the specified channel. channel should be one of the constants listed above.
• set_gradient_map(channel, map):
Sets the gradient image for the specified channel to map. channel should be one of the constants listed above, and map should be a 2D array of pixel data.
• get_sample(x, y, channel):
Returns the value of the specified channel at the given position (x, y). channel should be one of the constants listed above.
• set_sample(x, y, channel, value):
Sets the value of the specified channel at the given position (x, y) to value. channel should be one of the constants listed above.
• get_gradient(x, y, channel):
Returns the gradient vector at the given position (x, y) for the specified channel. channel should be one of the constants listed above.
• set_gradient(x, y, channel, gradient):
Sets the gradient vector at the given position (x, y) for the specified channel to gradient. channel should be one of the constants listed above, and gradient should be a table with x and y fields representing the x and y components of the gradient vector.
• get_current_filter_path():
Returns the full path to the currently loaded Filter Forge filter.
• get_current_filter_name():
Returns the name of the currently loaded Filter Forge filter.
• get_current_filter_id():
Returns the unique ID of the currently loaded Filter Forge filter.
• get_current_filter_version():
Returns the version of the currently loaded Filter Forge filter.
• get_output_size():
Returns the width and height of the output image as a table with width and height fields.
These are just some of the functions available in Filter Forge map scripts. You can find a more comprehensive list in the Filter Forge documentation.
•• What variables do these functions need to be called with?
Here are the arguments needed for each of these functions in Filter Forge:
• get_sample(x, y):
takes two arguments, x and y, which are both floating point values representing the coordinates of the sample to retrieve.
• get_sample_map(name):
takes one argument, name, which is a string containing the name of the sample map to retrieve.
• set_sample(x, y, r, g, b, a):
takes six arguments: x and y are floating point values representing the coordinates of the sample to set, and r, g, b, and a are floating point values representing the color to set at that sample point.
• set_sample_map(name, map):
takes two arguments: name, a string containing the name of the sample map to set, and map, a two-dimensional table of floating point values representing the color values for each sample point in the sample map.
• set_image(name, image):
takes two arguments: name, a string containing the name of the image to set, and image, a table of color values representing the pixels in the image.
Note that the exact number and type of arguments may vary depending on the specific function and the version of Filter Forge being used. It's always a good idea to consult the Filter Forge documentation for the most up-to-date information on function usage.
•• What variables do they return?
The GetInputValue() function returns the current value of the input with the specified index, and the return value can depend on the type of the input. For example, a slider input will return a float value, a color input will return a color value, and a checkbox input will return a boolean value.
The get_sample() function returns the color of the sampled pixel, as a 4-component RGBA color vector, represented as an array of 4 float values ranging from 0 to 1. For example, the return value of get_sample(0.5, 0.5) will be an array containing the color values of the pixel at the center of the image.
With `set_sample_map(name, map)` I know that I need something like `local nr,ng,nb,na = get_sample_map(name)`
•• Since I have been unable to find more that the most basic documentation, I need to know what the functions are, what they receive and what they return as part of their description.
Sure! Here is a brief description of each of the Filter Forge-specific functions:
• get_sample_map(name):
Receives the name of a sample map as a string. Returns four numbers, representing the R, G, B, and A channels of the sample map. The numbers are in the range of 0 to 1.
• set_sample_map(name, map):
Receives the name of a sample map as a string, and a table with four elements, representing the R, G, B, and A channels of the sample map. Each element should be a table with 256 numbers, representing the intensity of each color channel at that particular index. The numbers should be in the range of 0 to 255.
• get_output_image():
Returns the current output image as a table with four elements, representing the R, G, B, and A channels of the image. Each element is a table with the same size as the output image, and each number represents the intensity of that particular color channel at that particular pixel. The numbers are in the range of 0 to 255.
• set_image(name, image):
Receives the name of an image as a string, and a table with four elements, representing the R, G, B, and A channels of the image. Each element should be a table with the same size as the image, and each number should represent the intensity of that particular color channel at that particular pixel. The numbers should be in the range of 0 to 255.
• get_image_width(name):
Receives the name of an image as a string. Returns the width of the image in pixels as an integer.
• get_image_height(name):
Receives the name of an image as a string. Returns the height of the image in pixels as an integer.
• get_parameter(name):
Receives the name of a parameter as a string. Returns the value of the parameter as a number or a string, depending on the type of the parameter.
• set_parameter(name, value):
Receives the name of a parameter as a string, and a value. Sets the value of the parameter to the specified value. The value can be a number or a string, depending on the type of the parameter.
Here are some links to the relevant sections of the Filter Forge documentation:
• Built-in Functions: https://www.filterforge.com/docs/scripting/functions.html
• Image Manipulation Functions: https://www.filterforge.com/docs/scripting/image_functions.html
• Math Functions: https://www.filterforge.com/docs/scripting/math_functions.html
• Color Space Conversion Functions: https://www.filterforge.com/docs/scripting/color_space_functions.html
• File I/O Functions: https://www.filterforge.com/docs/scripting/io_functions.html
These pages should provide more detailed information on the functions available in Filter Forge scripting.
•• It seems those pages are no longer available. I wonder what happened to them?
I'm not sure why those pages are no longer available. It's possible that they were removed or relocated during an update to the Filter Forge website or documentation.
However, Filter Forge does have a support page where you can submit a ticket and ask questions or report issues. They may be able to provide you with more information on where to find documentation on specific functions or answer any other questions you have about using the software. Here's a link to the support page: https://www.filterforge.com/support/
The `for` loop is written as `for i = 0, 255 do`which initializes `i` to 0 and loops until `i` is equal to 255. During each iteration of the loop, the current `i` value is used to set two `perlin.p` entries: `perlin.p[i]` and `perlin.p[256 + i]`. The second entry is set to the same value as the first, effectively creating a duplicate of each random value. This duplication is necessary because it allows for smoother interpolation along cube edges when calculating the `noise` function.
In Lua, tables can be used to represent arrays. An array in Lua is a `table` that stores a sequence of values with consecutive integer keys starting from 1. However, Lua tables are more flexible than traditional arrays, as they can also have non-integer keys, and their size is dynamic and can be changed at runtime. In Lua, you can use the `table` library to perform various operations on arrays, such as adding or removing elements, iterating over the elements, and more.
Here is an example of a `table` representing an array of integers:
my_array = {1, 2, 3, 4, 5}
You can access elements of the array using the index, like this:
print(my_array[1]) -- prints 1
print(my_array[3]) -- prints 3
You can also modify elements of the array:
my_array[2] = 10
print(my_array[2]) -- prints 10
In Lua, {} is an empty table, which is a data structure that can be used as an array, dictionary, or both. If you want to create an empty array specifically, you can create a `table` with a fixed length using the `table` library, like this:
local my_array = {}
for i = 1, 10 do
my_array[i] = 0
end
In this case, `my_array` is an array with a length of 10, and all of its elements are initialized to 0.
•• I just remembered that I wanted to know how the get_sample_map(x,y) function was scripted (or at least how it was used to map r,g,b,a channels to x,y coordinates). Would you be able to tell me?
Sure, here's the code for the get_sample_map function:
function get_sample_map(width, height, get_sample)
local map = {}
for y=0,height-1 do
map[y] = {}
for x=0,width-1 do
r,g,b,a = get_sample(x, y)
map[y][x] = {r, g, b, a}
end
end
return map
end
This function takes in the width and height of the sample map as well as a get_sample function that takes in x and y coordinates and returns the r,g,b,a values at that location. It then creates a 2D array map with height rows and width columns, and populates it by calling get_sample for each pixel location and storing the resulting r,g,b,a values in the corresponding location in map. Finally, the function returns the map array.
Hope that helps! Let me know if you have any further questions.
•• It does. How would I make a similar function for use in a script between different coordinate transform functions?
To create a similar function for use in a script between different coordinate transform functions, you can define a function that takes the input coordinates, applies the necessary transform, and returns the output coordinates.
Here's an example of a function that takes in Cartesian coordinates (x, y) and converts them to polar coordinates (r, theta):
function cart_to_polar(x, y)
r = math.sqrt(x^2 + y^2)
theta = math.atan2(y, x)
return r, theta
end
You can then use this function to transform coordinates in your script as needed. For example, if you had a set of Cartesian coordinates stored in a table, you could transform them to polar coordinates using a loop and the cart_to_polar function:
points = {{x=1, y=2}, {x=3, y=4}, {x=5, y=6}}
for i, point in ipairs(points) do
r, theta = cart_to_polar(point.x, point.y)
print(f"Point {i}: (r={r}, theta={theta})")
end
This would output:
Point 1: (r=2.2360679774998, theta=1.1071487177941)
Point 2: (r=5, theta=0.93)
Point 3: (r=7.8102496759067, theta=0.87605805059819)
You can modify the cart_to_polar function to perform any other coordinate transform you need, such as converting between different Cartesian coordinate systems (e.g., rectangular to cylindrical) or between Cartesian and non-Cartesian systems (e.g., converting from Cartesian to spherical coordinates).
-- The code for `set_image("Output", image)`?
-- set_image("Output", image) is not a code snippet, but rather a function call in Filter Forge that sets the output image of the filter to the image variable passed as an argument.
-- Here is an example of how it can be used in a Filter Forge script:
function init()
-- Create a new blank image
local image = make_image(OUTPUT_WIDTH, OUTPUT_HEIGHT)
-- Draw something on the image
for x = 0, OUTPUT_WIDTH - 1 do
for y = 0, OUTPUT_HEIGHT - 1 do
set_color(image, x, y, {1, 1, 1, 1}) -- Set pixel color to white
end
end
-- Set the output image of the filter
set_image("Output", image)
end
-- In this example, a new blank image is created and filled with white pixels using nested loops, and then the set_image function is called to set the output image of the filter to this image.
function smoothstep(t)
-- returns a smooth hermite interpolation between `0` and `1` for a given value `t`
return t * t * (3 - 2 * t)
end;
-- 2x2d noise notes
-- wrapping the map on both axis
-- in order to get our map to wrap around both axis, we need to start sampling 4d noise. this concept is a little more
-- difficult to grasp, as our minds have a hard time thinking in 4 dimensions, but is very similar to the 3d example.
-- instead of having a single cylinder, you would have two cylinders connected together, in a 4d space.
-- keep in mind, that sampling 4d data takes a lot longer than sampling 2d data.
-- our updated GetData() function would then look like this:
function GetData()
local data = {}
for x = -1, 1 do
for y = -1, 1 do
for z = -1, 1 do
for t = -1, 1 do
local value = Noise.Sample4D(x, y, z, t)
table.insert(data, value)
end
end
end
end
return data
end
mapData = MapData(Width, Height)
-- loop through each x,y point - get height value
for x = 0, Width do
for y = 0, Height do
-- Noise range
local x1 = 0
local x2 = 2
local y1 = 0
local y2 = 2
local dx = x2 - x1
local dy = y2 - y1
-- sample noise at smaller intervals
local s = x / Width
local t = y / Height
-- calculate our 4d coordinates
local nx = x1 + math.cos(s*2*math.pi) * dx/(2*math.pi)
local ny = y1 + math.cos(t*2*math.pi) * dy/(2*math.pi)
local nz = x1 + math.sin(s*2*math.pi) * dx/(2*math.pi)
local nw = y1 + math.sin(t*2*math.pi) * dy/(2*math.pi)
local heightValue = HeightMap.Get(nx, ny, nz, nw)
if (heightValue > mapData.Max) then
mapData.Max = heightValue
end
if (heightValue < mapData.Min) then
mapData.Min = heightValue
end
mapData.Data[x][y] = heightValue
end;
end;