Welcome to WSL!

New to the forum? Please read this and this.

Get the absolute path to project using variable

User avatar
malbred
Posts: 44
Joined: Wed Aug 16, 2017 9:17 pm
Answers: 1
Location: Saint-Petersburg, Russia
Contact:

Get the absolute path to project using variable

#1

Post by malbred »

Hello guys
I have a macro with simple interface control compiled in resolve. This macro used import FBX node (FBXMesh3D) and after using on fusion page I have no open FBX file because path file is absolute.

I want to get the path of the current project file *.drp. After that, i need to edit the path using LUA code and insert the correct path (path to fbx file) in the FBX import node inside the macro.

Structure of my project:
--------------------------
PROJECT.dra
-MediaFiles
--fbx_files
--pic
-project.drp
--------------------------

Now with active MediaIn and this LUA
  1. path = tostring(mediaprops.MEDIA_PATH)
  2. print(tostring(path))
i get the right path to project texture like a "D:\work\fusion_resolve\test_project\pic\input_texture.jpg"
next, I wanted to cut off the last characters from the resulting string ("D:\work\fusion_resolve\test_project\"),
add the fbx folder to it to get something similar to this "D:\work\fusion_resolve\test_project\fbx_files\",
and finaly connect my string(path to fbx folder) and a file name to get the correct fbx path to insert this path to FBXMesh3D node ("D:\work\fusion_resolve\test_project\fbx_files\cube.fbx")


Am I on the right way?
Are there any errors in my solution?
it seems to me that my option is too complicated and there is a simpler solution.
by Midgardsormr » Thu Jun 10, 2021 7:50 am
Thanks, Peter! Once again I have reinvented something that already exists. :D

The output of split is a table, so you can't concatenate it with the string SPLIT -

Replace line 76 with this:

Code: Select all

print('SPLIT - ')
dump(split(strInput, SEPARATOR))
You can assign the value of table.getn() to a variable or dump its value like any other function:

Code: Select all

pathTable = split(strInput, SEPARATOR)
 
tableLength = table.getn(pathTable)

print("Table Length = "..tableLength)

newpath = table.concat(pathTable, SEPARATOR)

print("New Path: "..newpath)
Go to full post
Last edited by malbred on Wed Jun 09, 2021 8:59 pm, edited 4 times in total.

User avatar
Midgardsormr
Fusionator
Posts: 2143
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 27
Location: Los Angeles, CA, USA
Been thanked: 36 times
Contact:

Re: Get the absolute path to project using variable

#2

Post by Midgardsormr »

Okay, I was in the middle of writing a response to your original question, and now it's entirely changed… But I don't want to waste what I just wrote, so that's here:

That'll simply dump all of the available path maps from the Fusion preferences. But the Resolve project file isn't a part of the Fusion path mapping system, so it won't help you.

I'm not terribly familiar with the Resolve API, but I think you can query the Project with GetCurrentProject(), then perhaps GetSetting() without arguments:

dump(GetCurrentProject():GetSetting())

Maybe. I don't have Resolve installed to test it.

https://deric.github.io/DaVinciResolve-API-Docs/

The above obviously makes no sense in the context of the new revised question. :mrgreen:

Onward!

I have some library functions to handle this kind of thing. Unfortunately, the network at the office seems to be down right now, so I can't connect to grab them. Well. I can at least give you parts of it. In the bmd.scriptlib are some handy functions:

Code: Select all

SEPARATOR = package.config:sub(1,1) -- Folder separator used by the Operating System.

------------------------------------------------------------------------------
-- parseFilename()
--
-- this is a great function for ripping a filepath into little bits
-- returns a table with the following
--
-- FullPath	: The raw, original path sent to the function
-- Path		: The path, without filename
-- FullName	: The name of the clip w\ extension
-- Name     : The name without extension
-- CleanName: The name of the clip, without extension or sequence
-- SNum		: The original sequence string, or "" if no sequence
-- Number 	: The sequence as a numeric value, or nil if no sequence
-- Extension: The raw extension of the clip
-- Padding	: Amount of padding in the sequence, or nil if no sequence
-- UNC		: A true or false value indicating whether the path is a UNC path or not
------------------------------------------------------------------------------
function parseFilename(filename)
	local seq = {}
	seq.FullPath = filename
	string.gsub(seq.FullPath, "^(.+[/\\])(.+)", function(path, name) seq.Path = path seq.FullName = name end)
	string.gsub(seq.FullName, "^(.+)(%..+)$", function(name, ext) seq.Name = name seq.Extension = ext end)

	if not seq.Name then -- no extension?
		seq.Name = seq.FullName
	end

	string.gsub(seq.Name,     "^(.-)(%d+)$", function(name, SNum) seq.CleanName = name seq.SNum = SNum end)

	if seq.SNum then
		seq.Number = tonumber( seq.SNum )
		seq.Padding = string.len( seq.SNum )
	else
	   seq.SNum = ""
	   seq.CleanName = seq.Name
	end

	if seq.Extension == nil then seq.Extension = "" end
	seq.UNC = ( string.sub(seq.Path, 1, 2) == [[\\]] )

	return seq
end

-----------------------------------------------------
-- split(strInput, delimit)
--
-- converts string strInput into a table, separating
-- records using the provided delimiter string
--
-----------------------------------------------------
function split(strInput, delimit)
	local strLength
	local strTemp
	local strCollect
	local tblSplit
	local intCount

	tblSplit = {}
	intCount = 0
	strCollect = ""
	if delimit == nil then
		delimit = ","
	end

	strLength = string.len(strInput)
	for i = 1, strLength do
		strTemp = string.sub(strInput, i, i)
		if strTemp == delimit then
			intCount = intCount + 1
			tblSplit[intCount] = trim(strCollect)
			strCollect = ""
		else
			strCollect = strCollect .. strTemp
		end
	end
	intCount = intCount + 1
	tblSplit[intCount] = trim(strCollect)

	return tblSplit
end

These are modified a bit to remove them from the bmd namespace, making them easier to port into your own scripts. I often use split() to turn a path into a table, which can be more easily manipulated. With table.getn(), you can find the end index of the table, then count backward down your folder structure to get to whichever root folder you need, then replace the branches as desired.

Up at the top, you'll see a line I borrowed from Andrew to get the operating system's folder delimiter. Use SEPARATOR in place of any slashes, and you don't have to worry about the difference between Windows and Unix-style paths.

To reassemble the table into a path, I use another function:

Code: Select all

function tableToPath(pathTable, delimiter)
    local out = ""
    i = 1
    while i < table.getn(pathTable) do
        out = out..item..delimiter
        i = i+1
    end
    
    out = out..pathtable[table.getn(pathtable)]

    return out
end
That reassembles the table into a path. Maybe test that one more stringently than the others—I rewrote it from memory.

Anyway, you can easily add or remove entries from the table using the functions in the table library, which should hopefully make it a little easier to manage your paths.

Hope that helps somewhat!

User avatar
malbred
Posts: 44
Joined: Wed Aug 16, 2017 9:17 pm
Answers: 1
Location: Saint-Petersburg, Russia
Contact:

Re: Get the absolute path to project using variable

#3

Post by malbred »

Thanks for your reply. I sit down to study your material.
Sorry for changing my question. I wanted to describe my problem in detail

User avatar
malbred
Posts: 44
Joined: Wed Aug 16, 2017 9:17 pm
Answers: 1
Location: Saint-Petersburg, Russia
Contact:

Re: Get the absolute path to project using variable

#4

Post by malbred »

I don't understand scripts very well and have some error.

What I do:
1) Rename one MediaIn with image to IMG_IN

2) On fusion page open the console and run:

a) function split - I didn't change it

Code: Select all

function split(strInput, delimit)
	local strLength
	local strTemp
	local strCollect
	local tblSplit
	local intCount

	tblSplit = {}
	intCount = 0
	strCollect = ""
	if delimit == nil then
		delimit = ","
	end

	strLength = string.len(strInput)
	for i = 1, strLength do
		strTemp = string.sub(strInput, i, i)
		if strTemp == delimit then
			intCount = intCount + 1
			tblSplit[intCount] = trim(strCollect)
			strCollect = ""
		else
			strCollect = strCollect .. strTemp
		end
	end
	intCount = intCount + 1
	tblSplit[intCount] = trim(strCollect)

	return tblSplit
end
b) This to check split function

Code: Select all

filename = comp.IMG_IN:GetData('MediaProps.MEDIA_PATH')
dump('Checking path - ' .. filename)
split(filename, "^")
---------------------
My error is - [string "???"]:27: attempt to call global 'trim' (a nil value)
:cry:
PIC0001.jpeg
You do not have the required permissions to view the files attached to this post.

User avatar
PeterLoveday
Fusioneer
Posts: 221
Joined: Sun Sep 14, 2014 6:09 pm
Answers: 9
Been thanked: 5 times

Re: Get the absolute path to project using variable

#5

Post by PeterLoveday »

Midgardsormr wrote: Wed Jun 09, 2021 8:21 pm

Code: Select all

function tableToPath(pathTable, delimiter)
    local out = ""
    i = 1
    while i < table.getn(pathTable) do
        out = out..item..delimiter
        i = i+1
    end
    
    out = out..pathtable[table.getn(pathtable)]

    return out
end
See also:

Code: Select all

Lua> =table.concat({"A","B","C"}, "/")
A/B/C

User avatar
malbred
Posts: 44
Joined: Wed Aug 16, 2017 9:17 pm
Answers: 1
Location: Saint-Petersburg, Russia
Contact:

Re: Get the absolute path to project using variable

#6

Post by malbred »

I don't understand:
1) How can I check or see the number of table.getn() ? (syntax problem)
2) How to check the result of the split() function? (syntax problem)

My code with comments:

  1. SEPARATOR = package.config:sub(1,1)
  2.  
  3. --IMG_IN is MediaIN node with texture
  4. filename = comp.IMG_IN:GetData('MediaProps.MEDIA_PATH')
  5.  
  6.  
  7. -------------
  8. function parseFilename(filename)
  9.     local seq = {}
  10.     seq.FullPath = filename
  11.     string.gsub(seq.FullPath, "^(.+[/\\])(.+)", function(path, name) seq.Path = path seq.FullName = name end)
  12.     string.gsub(seq.FullName, "^(.+)(%..+)$", function(name, ext) seq.Name = name seq.Extension = ext end)
  13.  
  14.     if not seq.Name then -- no extension?
  15.         seq.Name = seq.FullName
  16.     end
  17.  
  18.     string.gsub(seq.Name,     "^(.-)(%d+)$", function(name, SNum) seq.CleanName = name seq.SNum = SNum end)
  19.  
  20.     if seq.SNum then
  21.         seq.Number = tonumber( seq.SNum )
  22.         seq.Padding = string.len( seq.SNum )
  23.     else
  24.        seq.SNum = ""
  25.        seq.CleanName = seq.Name
  26.     end
  27.  
  28.     if seq.Extension == nil then seq.Extension = "" end
  29.     seq.UNC = ( string.sub(seq.Path, 1, 2) == [[\\]] )
  30.  
  31.     return seq
  32. end
  33.  
  34.  
  35. -- Check file path
  36. dump('PATH IS -  ' .. parseFilename(filename).Path)
  37.  
  38.  
  39. function split(strInput, delimit)
  40.     local strLength
  41.     local strTemp
  42.     local strCollect
  43.     local tblSplit
  44.     local intCount
  45.  
  46.     tblSplit = {}
  47.     intCount = 0
  48.     strCollect = ""
  49.     if delimit == nil then
  50.         delimit = ","
  51.     end
  52.  
  53.     strLength = string.len(strInput)
  54.     for i = 1, strLength do
  55.         strTemp = string.sub(strInput, i, i)
  56.         if strTemp == delimit then
  57.             intCount = intCount + 1
  58.             tblSplit[intCount] = trim(strCollect)
  59.             strCollect = ""
  60.         else
  61.             strCollect = strCollect .. strTemp
  62.         end
  63.     end
  64.     intCount = intCount + 1
  65.     tblSplit[intCount] = trim(strCollect)
  66.  
  67.     return tblSplit
  68. end
  69.  
  70.  
  71.  
  72. strInput = parseFilename(filename).Path
  73.  
  74. -- STRING - 74!!!
  75. --Check split result
  76. dump('SPLIT - ' .. split(strInput, SEPARATOR))
  77.  
  78. --table.getn(???)
  79. --table.concat({"A","B","C"}, SEPARATOR)

After compilate see - [string "???"]:74: attempt to concatenate a table value
Last edited by malbred on Thu Jun 10, 2021 8:19 am, edited 1 time in total.

User avatar
Midgardsormr
Fusionator
Posts: 2143
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 27
Location: Los Angeles, CA, USA
Been thanked: 36 times
Contact:

Re: Get the absolute path to project using variable

#7

Post by Midgardsormr »

Thanks, Peter! Once again I have reinvented something that already exists. :D

The output of split is a table, so you can't concatenate it with the string SPLIT -

Replace line 76 with this:

Code: Select all

print('SPLIT - ')
dump(split(strInput, SEPARATOR))
You can assign the value of table.getn() to a variable or dump its value like any other function:

Code: Select all

pathTable = split(strInput, SEPARATOR)
 
tableLength = table.getn(pathTable)

print("Table Length = "..tableLength)

newpath = table.concat(pathTable, SEPARATOR)

print("New Path: "..newpath)

User avatar
malbred
Posts: 44
Joined: Wed Aug 16, 2017 9:17 pm
Answers: 1
Location: Saint-Petersburg, Russia
Contact:

Re: Get the absolute path to project using variable

#8

Post by malbred »

Thank you so much for suggesting.
Script is working now.I do understand the logic of writing code, but I don't know the syntax. You've been very helpful, I appreciate your support a lot.

There are 3 more questions.
1)
To determine the first original path, I use this code
  1. filename = comp.Tex_In:GetData('MediaProps.MEDIA_PATH')
Here is my project in DaVinci.
PIC001.jpeg
It's placed on the Fusion page. These are several textures and a macro in which I need to redefine the paths to the FBX files.
Did I write this code correctly? My doubts are about "comp" before Tex_In. Maybe I need to write "fu" or something else for correct work?

2)
As I understand it, I need to run the script once after load the project to redefine the paths.
Where should I place my script for that?

3)
Are there any special features in the script when working with Mac or PC? like SEPARATOR variable.
You do not have the required permissions to view the files attached to this post.

User avatar
Midgardsormr
Fusionator
Posts: 2143
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 27
Location: Los Angeles, CA, USA
Been thanked: 36 times
Contact:

Re: Get the absolute path to project using variable

#9

Post by Midgardsormr »

1) Your Tex_In node is a member of comp, which is the currently active composite. As long as the script is running from within that composite, comp will be defined, and you'll be able to address nodes in that fashion. So that is correct.

If you're executing the script from outside Fusion—from an IDE or a remote process—then you'd need to first define the active comp, and for that you'd need Fusion(). Here's my library code for that:

Code: Select all

--======================== ENVIRONMENT SETUP ============================--

------------------------------------------------------------------------
-- getFusion()
--
-- check if global fusion is set, meaning this script is being
-- executed from within fusion
--
-- Arguments: None
-- Returns: handle to the Fusion instance
------------------------------------------------------------------------
function getFusion()
	if fusion == nil then 
		-- remotely get the fusion ui instance
		fusion = bmd.scriptapp("Fusion", "localhost")
	end
	return fusion
end -- end of getFusion()

-- get fusion instance
_fusion = getFusion()

-- ensure a fusion instance was retrieved
if not _fusion then
	error("Please open the Fusion GUI before running this tool.")
end

-- get composition
_comp = _fusion.CurrentComp
SetActiveComp(_comp)

2) I'm not sure about the answer to this one within the context of Resolve. In Fusion standalone, you can rename the script with the extension .scriptlib and put it in the Scripts/Comp folder, and it will execute every time a comp is opened. I don't know if that would work in Resolve or not. I've only experimented with scriptlib files a little, and that was before Fusion 16 released. There are some scant details in the Fusion 8 Scripting Guide on page 24.

3) Probably, but the path separator is the only one I've needed to worry about so far. @AndrewHazelden might know more about that. Most of what I'm sharing came from him originally, anyway. :)

User avatar
AndrewHazelden
Fusionator
Posts: 1754
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 11
Location: West Dover, Nova Scotia, Canada
Been thanked: 32 times
Contact:

Re: Get the absolute path to project using variable

#10

Post by AndrewHazelden »

Hi. I'm just looking at this thread now. It appears you want to modify both an FBX file's path, and an input texture map so it points at your current project folder location on disk. Another route to solve this effort would be to:

1. Switch the MediaIn node you are using to access your FBX model's texture maps to a Loader node.

2. Then use a custom PathMap (shortcut) for the project folder location that is used to hold both the FBX mesh, and the Loader node accessed texture map.

An example of what a custom PathMap could look like in the Fusion > Fusion Settings > PathMap preferences would be:

From:
ActiveProject:

To:
D:\work\fusion_resolve\Background_generator\

Image

Using PathMaps to Access Images and Models

Then in the Loader node you would write the relative PathMap based filepath as:
ActiveProject:\pic\input_HDRI.jpg

For the FBX model you would write the relative PathMap based filepath as:
ActiveProject:\fbx_files\cube.fbx


Image

Scripting PathMap Usage

You could use the following Lua code to create / modify the PathMap entry:
Code: [Select all] [Expand/Collapse] [Download] (CreatePathmap.lua)
  1. -- ---------------------------------------------------------------------------------------------
  2. -- Create a new PathMap
  3.  
  4. -- Current working project folder path
  5. active_project_path = [[D:\work\fusion_resolve\Background_generator\]]
  6.  
  7. -- Add an "ActiveProject:" PathMap entry
  8. app:SetPrefs("Global.Paths.Map.ActiveProject:", active_project_path)

When you want to access the fully expanded the PathMap into an "absolute" filepath you can use the following Lua code:
Code: [Select all] [Expand/Collapse] [Download] (ExpandPathmap.lua)
  1. -- ---------------------------------------------------------------------------------------------
  2. -- Expand a PathMap
  3.  
  4. file_path = app:MapPath([[ActiveProject:\fbx_files\cube.fbx]])
  5. print("[Absolute Filepath] ", file_path)
Image