hi there,
For the people who don't like the API browser. I wrote a Lua script a while ago to create a html file describing the Octane Lua API. The script will ask for an output file.
cheers,
Thomas
Script to create Lua API documentation in html.
- stratified
- Posts: 945
- Joined: Wed Aug 15, 2012 6:32 am
- Location: Auckland, New Zealand
Output error with script
Also text in the Output area of the editor doesn't copy to clipboardWin 11 64GB | NVIDIA RTX3060 12GB
- stratified
- Posts: 945
- Joined: Wed Aug 15, 2012 6:32 am
- Location: Auckland, New Zealand
Hi there,
I modified the script to dump out an error when doc is nil. This can happend when that file is not writable. Could you try to use a different path in the variable HTML_FILE?
thanks,
Thomas
I modified the script to dump out an error when doc is nil. This can happend when that file is not writable. Could you try to use a different path in the variable HTML_FILE?
thanks,
Thomas
Code: Select all
--
-- Creates a single html that describes the Lua API. Run this thing from
-- within Octane. It creates a file api.html next to the Octane binary.
--
local HTML_FILE = "/tmp/api.html"
doc, errMsg = io.open(HTML_FILE, "w")
if not doc then error(errMsg) end
local cssStyle =
[[
body
{
font-family: 'Titillium Web', Verdana, Helvetica, sans-serif;
}
h1
{
color: #d50708;
}
h2
{
color: #d50708;
border-bottom: 1px solid #d50708;
}
h3
{
color: #3083aa;
border-bottom: 1px solid #3083aa;
}
a
{
color: #FF6600;
}
a:hover
{
color: white;
background-color: #FF6600;
}
table.funcdoc
{
padding-top: 10px;
}
table.funcdoc th
{
color:#4b6a7e;
padding-right: 40px;
}
]]
local function inArray(array, value)
for _, val in ipairs(array) do
if value == val then return true end
end
return false
end
-- Inline CSS style
doc:write("<html>")
doc:write("<head>")
doc:write(string.format("<style>%s</style>", cssStyle))
doc:write("</head>")
doc:write("<body>")
-- Logo
doc:write('<div class="logo" style="left: 200px; opacity: 1;">')
doc:write('<img src="http://render.otoy.com/images/octanerender_logo.png" width="58" height="65" alt="Octane Render Logo" class="spinme">')
doc:write('<img src="http://render.otoy.com/images/octanerender_text.png" width="206" height="65" alt="Octane Render">')
doc:write('</div>')
doc:write("<h1>Lua API<h1>")
local modules = octane.help.modules()
-- Module overview.
doc:write("<h2>Modules Overview</h2>")
doc:write("<table class='overview'>")
for name, description in pairs(modules) do
doc:write(string.format("<tr><td><a href='#%s'>%s</a></td><td>%s</td></tr>", name, name, description))
end
doc:write("</table>")
-- Per Module breakdown.
for moduleName, description in pairs(modules) do
doc:write(string.format("<h2 id='%s'>Module %s</h2>", moduleName, moduleName))
doc:write(string.format("<p>%s</p>", description))
-- Table with functions.
local modfunctions = octane.help.functions(moduleName)
doc:write("<h3>Functions</h3>")
doc:write("<table class='overview'>")
for _, func in ipairs(modfunctions) do
local funcdoc = octane.help.functionDoc(octane[moduleName][func])
local fullName = string.format("octane.%s.%s", moduleName, func)
doc:write(string.format("<tr><td><a href='#%s'>%s</a></td><td>%s</td></tr>", fullName, fullName, funcdoc.description))
end
doc:write("</table>")
-- Table with the properties.
local moduleProps = octane.help.properties(moduleName)
if #moduleProps > 0 then
doc:write("<h3>Properties</h3>")
doc:write("<table class='overview'>")
for idx, propsName in ipairs(moduleProps) do
local propsDoc = octane.help.propertiesDoc(moduleName, propsName)
local fullName = string.format("octane.%s.%s", moduleName, propsName)
doc:write(string.format("<tr><td><a href='#%s'>%s</a></td><td>%s</td></tr>", fullName, fullName, propsDoc.description))
end
doc:write("</table>")
end
-- Table with the constants.
local moduleConstants = octane.help.constants(moduleName)
if #moduleConstants > 0 then
doc:write("<h3>Constants</h3>")
doc:write("<table class='overview'>")
for idx, constantName in ipairs(moduleConstants) do
local constantInfo = octane.help.constantDoc(moduleName, constantName)
local fullName = string.format("octane.%s.%s", moduleName, constantName)
doc:write(string.format("<tr><td><a href='#%s'>%s</a></td><td>%s</td></tr>", fullName, fullName, constantInfo.description))
end
doc:write("</table>")
end
end
-- Give a breakdown per function.
doc:write("<h2>Function Overview</h2>")
for moduleName, moduleDescription in pairs(modules) do
local moduleFunctions = octane.help.functions(moduleName)
for _, functionName in ipairs(moduleFunctions) do
local fullName = string.format("octane.%s.%s", moduleName, functionName)
doc:write(string.format("<h3 id='%s'>%s</h3>", fullName, fullName))
local funcDoc = octane.help.functionDoc(octane[moduleName][functionName])
local modProps = octane.help.properties(moduleName)
doc:write("<span class='funcdoc'>")
-- Table with the description.
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'><th>Description</th></tr>")
doc:write(string.format("<tr><td>%s</td></tr>", funcDoc.description))
doc:write("</table>")
-- Table with the parameters.
if #funcDoc.params > 0 then
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'> <th colspan='3'>Parameters</th> </tr>")
doc:write("<tr align='left'> <th>Name</th> <th>Type</th> <th>Description</th> </tr>")
for _, param in ipairs(funcDoc.params) do
if (not inArray(modProps, param.name)) then
-- regular param
doc:write(string.format("<tr> <td>%s</td> <td>%s</td> <td>%s</td> </tr>",
param["name"], param["type"], param["description"]))
else
-- property
doc:write(string.format("<tr> <td><a href='#%s'>%s</a></td> <td>%s</td> <td>%s</td> </tr>",
string.format("octane.%s.%s", moduleName, param.name),
param["name"],
param["type"],
param["description"]))
end
end
doc:write("</table>")
end
-- Table with return values.
if #funcDoc.returns > 0 then
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'> <th colspan='3'>Return Values</th> </tr>")
doc:write("<tr align='left'> <th>Name</th> <th>Type</th> <th>Description</th> </tr>")
for _, ret in ipairs(funcDoc.returns) do
if not inArray(modProps, ret.name) then
-- regular return value.
doc:write(string.format("<tr> <td>%s</td> <td>%s</td> <td>%s</td> </tr>", ret["name"], ret["type"], ret["description"]))
else
-- property return value.
doc:write(string.format("<tr> <td><a href='#%s'>%s</a></td> <td>%s</td> <td>%s</td> </tr>",
string.format("octane.%s.%s", moduleName, ret.name),
ret["name"],
ret["type"],
ret["description"]))
end
end
doc:write("</table>")
end
-- Create the synopsis.
local synopsis = ""
if #funcDoc.returns > 0 then
for i=1,#funcDoc.returns-1 do
synopsis = synopsis..funcDoc.returns[i].name..", "
end
synopsis = synopsis..funcDoc.returns[#funcDoc.returns].name.." = "
end
synopsis = synopsis..fullName.."( "
if #funcDoc.params > 0 then
for i=1,#funcDoc.params-1 do
synopsis = synopsis..funcDoc.params[i].name..", "
end
synopsis = synopsis..funcDoc.params[#funcDoc.params].name
end
synopsis = synopsis.." )"
-- Table with the synopsis.
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'><th>Synopsis</th></tr>")
doc:write(string.format("<tr align='left'><td>%s</td></tr>", synopsis))
doc:write("</table>")
doc:write("</span>")
end
end
-- Give a breakdown per constant.
doc:write("<h2>Constant Overview</h2>")
for moduleName, moduleDescription in pairs(modules) do
local constantNames = octane.help.constants(moduleName)
for _, constantName in ipairs(constantNames) do
local fullName = string.format("octane.%s.%s", moduleName, constantName)
doc:write(string.format("<h3 id='%s'>%s</h3>", fullName, fullName))
local constDoc = octane.help.constantDoc(moduleName, constantName)
-- Table with the description.
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'><th>Description</th></tr>")
doc:write(string.format("<tr><td>%s</td></tr>", constDoc.description))
doc:write("</table>")
-- Table with the constant values.
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'><th>Values</th></tr>")
-- Get the names.
local names = {}
for name, _ in pairs(constDoc.values) do
table.insert(names, name)
end
-- Sort the names.
table.sort(names)
for _, name in ipairs(names) do
doc:write(string.format("<tr> <td>%s</td> </tr>", name))
end
doc:write("</table>")
end
end
-- Give a breakdown per properties.
doc:write("<h2>Properties Overview</h2>")
for moduleName, moduleDescription in pairs(modules) do
local moduleProps = octane.help.properties(moduleName)
for _, propertiesName in ipairs(moduleProps) do
local fullName = string.format("octane.%s.%s", moduleName, propertiesName)
doc:write(string.format("<h3 id='%s'>%s</h3>", fullName, fullName))
local propertiesDoc = octane.help.propertiesDoc(moduleName, propertiesName)
doc:write("<span class='funcdoc'>")
-- Table with the description.
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'><th>Description</th></tr>")
doc:write(string.format("<tr><td>%s</td></tr>", propertiesDoc.description))
doc:write("</table>")
local properties = propertiesDoc.properties
local propNames = {}
for name, _ in pairs(properties) do
table.insert(propNames, name)
end
table.sort(propNames)
-- Table with each proprty
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'> <th colspan='3'>Properties</th> </tr>")
doc:write("<tr align='left'> <th>Name</th> <th>Description</th> <th>Type</th> <th>Writable</th></tr>")
for _,name in ipairs(propNames) do
local info = properties[name]
doc:write(string.format("<tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> </tr>",
name, info.description, info["type"], info.writable))
end
doc:write("</table>")
doc:write("</span>")
end
end
doc:write("</body>")
doc:write("</html>")
- stratified
- Posts: 945
- Joined: Wed Aug 15, 2012 6:32 am
- Location: Auckland, New Zealand
just noticed that as well, we'll fix it in one of the next releases.Tugpsx wrote:Also text in the Output area of the editor doesn't copy to clipboard
cheers,
Thomas
Can we add an option to clear the output in the editor also. This will help a lot with debugging script outputs
Win 11 64GB | NVIDIA RTX3060 12GB
Output works great now. But better yet add an option for it to prompt the user for the location to save the file. End user will appreciate it.
Win 11 64GB | NVIDIA RTX3060 12GB
- stratified
- Posts: 945
- Joined: Wed Aug 15, 2012 6:32 am
- Location: Auckland, New Zealand
This will show a dialog asking the user where to save the file. It pops up an error if something went wrong.
But then again I guess the people who're interested in Lua could have figured this out themselves
cheers,
Thomas
But then again I guess the people who're interested in Lua could have figured this out themselves

cheers,
Thomas
Code: Select all
--
-- Creates a single html that describes the Lua API. Run this thing from
-- within Octane. It creates a file api.html next to the Octane binary.
--
-- show the user a file chooser
result = octane.gui.showDialog
{
type = octane.gui.dialogType.FILE_DIALOG,
title = "Choose Lua API html doc output",
wildcards = "*.html;*.htm",
save = true
}
-- try to open the file and show an error dialog if it failed
doc, errMsg = io.open(result.result, "w")
if not doc then
result = octane.gui.showDialog
{
type = octane.gui.dialogType.ERROR_DIALOG,
title = "File error",
text = errMsg
}
-- stop the script
error(errMsg)
end
local cssStyle =
[[
body
{
font-family: 'Titillium Web', Verdana, Helvetica, sans-serif;
}
h1
{
color: #d50708;
}
h2
{
color: #d50708;
border-bottom: 1px solid #d50708;
}
h3
{
color: #3083aa;
border-bottom: 1px solid #3083aa;
}
a
{
color: #FF6600;
}
a:hover
{
color: white;
background-color: #FF6600;
}
table.funcdoc
{
padding-top: 10px;
}
table.funcdoc th
{
color:#4b6a7e;
padding-right: 40px;
}
]]
local function inArray(array, value)
for _, val in ipairs(array) do
if value == val then return true end
end
return false
end
-- Inline CSS style
doc:write("<html>")
doc:write("<head>")
doc:write(string.format("<style>%s</style>", cssStyle))
doc:write("</head>")
doc:write("<body>")
-- Logo
doc:write('<div class="logo" style="left: 200px; opacity: 1;">')
doc:write('<img src="http://render.otoy.com/images/octanerender_logo.png" width="58" height="65" alt="Octane Render Logo" class="spinme">')
doc:write('<img src="http://render.otoy.com/images/octanerender_text.png" width="206" height="65" alt="Octane Render">')
doc:write('</div>')
doc:write("<h1>Lua API<h1>")
local modules = octane.help.modules()
-- Module overview.
doc:write("<h2>Modules Overview</h2>")
doc:write("<table class='overview'>")
for name, description in pairs(modules) do
doc:write(string.format("<tr><td><a href='#%s'>%s</a></td><td>%s</td></tr>", name, name, description))
end
doc:write("</table>")
-- Per Module breakdown.
for moduleName, description in pairs(modules) do
doc:write(string.format("<h2 id='%s'>Module %s</h2>", moduleName, moduleName))
doc:write(string.format("<p>%s</p>", description))
-- Table with functions.
local modfunctions = octane.help.functions(moduleName)
doc:write("<h3>Functions</h3>")
doc:write("<table class='overview'>")
for _, func in ipairs(modfunctions) do
local funcdoc = octane.help.functionDoc(octane[moduleName][func])
local fullName = string.format("octane.%s.%s", moduleName, func)
doc:write(string.format("<tr><td><a href='#%s'>%s</a></td><td>%s</td></tr>", fullName, fullName, funcdoc.description))
end
doc:write("</table>")
-- Table with the properties.
local moduleProps = octane.help.properties(moduleName)
if #moduleProps > 0 then
doc:write("<h3>Properties</h3>")
doc:write("<table class='overview'>")
for idx, propsName in ipairs(moduleProps) do
local propsDoc = octane.help.propertiesDoc(moduleName, propsName)
local fullName = string.format("octane.%s.%s", moduleName, propsName)
doc:write(string.format("<tr><td><a href='#%s'>%s</a></td><td>%s</td></tr>", fullName, fullName, propsDoc.description))
end
doc:write("</table>")
end
-- Table with the constants.
local moduleConstants = octane.help.constants(moduleName)
if #moduleConstants > 0 then
doc:write("<h3>Constants</h3>")
doc:write("<table class='overview'>")
for idx, constantName in ipairs(moduleConstants) do
local constantInfo = octane.help.constantDoc(moduleName, constantName)
local fullName = string.format("octane.%s.%s", moduleName, constantName)
doc:write(string.format("<tr><td><a href='#%s'>%s</a></td><td>%s</td></tr>", fullName, fullName, constantInfo.description))
end
doc:write("</table>")
end
end
-- Give a breakdown per function.
doc:write("<h2>Function Overview</h2>")
for moduleName, moduleDescription in pairs(modules) do
local moduleFunctions = octane.help.functions(moduleName)
for _, functionName in ipairs(moduleFunctions) do
local fullName = string.format("octane.%s.%s", moduleName, functionName)
doc:write(string.format("<h3 id='%s'>%s</h3>", fullName, fullName))
local funcDoc = octane.help.functionDoc(octane[moduleName][functionName])
local modProps = octane.help.properties(moduleName)
doc:write("<span class='funcdoc'>")
-- Table with the description.
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'><th>Description</th></tr>")
doc:write(string.format("<tr><td>%s</td></tr>", funcDoc.description))
doc:write("</table>")
-- Table with the parameters.
if #funcDoc.params > 0 then
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'> <th colspan='3'>Parameters</th> </tr>")
doc:write("<tr align='left'> <th>Name</th> <th>Type</th> <th>Description</th> </tr>")
for _, param in ipairs(funcDoc.params) do
if (not inArray(modProps, param.name)) then
-- regular param
doc:write(string.format("<tr> <td>%s</td> <td>%s</td> <td>%s</td> </tr>",
param["name"], param["type"], param["description"]))
else
-- property
doc:write(string.format("<tr> <td><a href='#%s'>%s</a></td> <td>%s</td> <td>%s</td> </tr>",
string.format("octane.%s.%s", moduleName, param.name),
param["name"],
param["type"],
param["description"]))
end
end
doc:write("</table>")
end
-- Table with return values.
if #funcDoc.returns > 0 then
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'> <th colspan='3'>Return Values</th> </tr>")
doc:write("<tr align='left'> <th>Name</th> <th>Type</th> <th>Description</th> </tr>")
for _, ret in ipairs(funcDoc.returns) do
if not inArray(modProps, ret.name) then
-- regular return value.
doc:write(string.format("<tr> <td>%s</td> <td>%s</td> <td>%s</td> </tr>", ret["name"], ret["type"], ret["description"]))
else
-- property return value.
doc:write(string.format("<tr> <td><a href='#%s'>%s</a></td> <td>%s</td> <td>%s</td> </tr>",
string.format("octane.%s.%s", moduleName, ret.name),
ret["name"],
ret["type"],
ret["description"]))
end
end
doc:write("</table>")
end
-- Create the synopsis.
local synopsis = ""
if #funcDoc.returns > 0 then
for i=1,#funcDoc.returns-1 do
synopsis = synopsis..funcDoc.returns[i].name..", "
end
synopsis = synopsis..funcDoc.returns[#funcDoc.returns].name.." = "
end
synopsis = synopsis..fullName.."( "
if #funcDoc.params > 0 then
for i=1,#funcDoc.params-1 do
synopsis = synopsis..funcDoc.params[i].name..", "
end
synopsis = synopsis..funcDoc.params[#funcDoc.params].name
end
synopsis = synopsis.." )"
-- Table with the synopsis.
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'><th>Synopsis</th></tr>")
doc:write(string.format("<tr align='left'><td>%s</td></tr>", synopsis))
doc:write("</table>")
doc:write("</span>")
end
end
-- Give a breakdown per constant.
doc:write("<h2>Constant Overview</h2>")
for moduleName, moduleDescription in pairs(modules) do
local constantNames = octane.help.constants(moduleName)
for _, constantName in ipairs(constantNames) do
local fullName = string.format("octane.%s.%s", moduleName, constantName)
doc:write(string.format("<h3 id='%s'>%s</h3>", fullName, fullName))
local constDoc = octane.help.constantDoc(moduleName, constantName)
-- Table with the description.
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'><th>Description</th></tr>")
doc:write(string.format("<tr><td>%s</td></tr>", constDoc.description))
doc:write("</table>")
-- Table with the constant values.
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'><th>Values</th></tr>")
-- Get the names.
local names = {}
for name, _ in pairs(constDoc.values) do
table.insert(names, name)
end
-- Sort the names.
table.sort(names)
for _, name in ipairs(names) do
doc:write(string.format("<tr> <td>%s</td> </tr>", name))
end
doc:write("</table>")
end
end
-- Give a breakdown per properties.
doc:write("<h2>Properties Overview</h2>")
for moduleName, moduleDescription in pairs(modules) do
local moduleProps = octane.help.properties(moduleName)
for _, propertiesName in ipairs(moduleProps) do
local fullName = string.format("octane.%s.%s", moduleName, propertiesName)
doc:write(string.format("<h3 id='%s'>%s</h3>", fullName, fullName))
local propertiesDoc = octane.help.propertiesDoc(moduleName, propertiesName)
doc:write("<span class='funcdoc'>")
-- Table with the description.
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'><th>Description</th></tr>")
doc:write(string.format("<tr><td>%s</td></tr>", propertiesDoc.description))
doc:write("</table>")
local properties = propertiesDoc.properties
local propNames = {}
for name, _ in pairs(properties) do
table.insert(propNames, name)
end
table.sort(propNames)
-- Table with each proprty
doc:write("<table class='funcdoc'>")
doc:write("<tr align='left'> <th colspan='3'>Properties</th> </tr>")
doc:write("<tr align='left'> <th>Name</th> <th>Description</th> <th>Type</th> <th>Writable</th></tr>")
for _,name in ipairs(propNames) do
local info = properties[name]
doc:write(string.format("<tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> </tr>",
name, info.description, info["type"], info.writable))
end
doc:write("</table>")
doc:write("</span>")
end
end
doc:write("</body>")
doc:write("</html>")
Quick question about documentation: where can I get all the parameter info that the octane.node.create() function gets? ie. this:
• table PROPS_NODE_ITEM
Table with properties for the node.
I would like to generate a node graph, basically a shader. But dunno how to assign which is the parent container (node graph) to nodes.
Maybe the next tutorial could be about how to set up a generic node graph shader programatically, with texture loading from disk and all the usual stuff (setting pins, connections, mixing materials or textures...)?
Anyway, great work with implementing scripting. Thanks!
EDIT: ah, sorry, I got it. Was at the end of the list. To specify where the node is created, I must use the "graphOwner" param.
• table PROPS_NODE_ITEM
Table with properties for the node.
I would like to generate a node graph, basically a shader. But dunno how to assign which is the parent container (node graph) to nodes.
Maybe the next tutorial could be about how to set up a generic node graph shader programatically, with texture loading from disk and all the usual stuff (setting pins, connections, mixing materials or textures...)?

Anyway, great work with implementing scripting. Thanks!
EDIT: ah, sorry, I got it. Was at the end of the list. To specify where the node is created, I must use the "graphOwner" param.

SW: Octane 3.05 | Linux Mint 18.1 64bit | Blender 2.78 HW: EVGA GTX 1070 | i5 2500K | 16GB RAM Drivers: 375.26
cgmo.net
cgmo.net
- stratified
- Posts: 945
- Joined: Wed Aug 15, 2012 6:32 am
- Location: Auckland, New Zealand
I'll create a post explaining all this...matej wrote: Maybe the next tutorial could be about how to set up a generic node graph shader programatically, with texture loading from disk and all the usual stuff (setting pins, connections, mixing materials or textures...)?![]()
cheers,
Thomas
This script is crashing with the current demo version of octane because octane[moduleName] == nil when moduleName == 'benchmark' or 'octane'. The crash happens on lines 122 and 164. I was able to put checks in for myself, but I didn't want to post my code since I'm very new to octane and I thought it might be an issue only with the demo version.
Thanks.
Thanks.