Convert a string GUID to the 4 int data fileds under the FMOD_GUID struct

Hi there,

I’m making a custom script on FMOD Studio. The basic idea is that you select some events and a scriptbale object asset file for Unity is created for each of them.

I have been able to create the file and all seems to work except for one thing. When trying to populate the EventReference field, I can add the path field (by using event.getPath()). I thought that would be enough and when giving focus to Unity the Guid fields will sort themselves but that doesn’t seem to be the case and they all stay at 0.

The result is what you see on the screenshot below, the GUID needs to be repaired on each asset you create. Not ideal.

image

So then I looked into grabbing the GUID from the event on the JavaScript script using event.id and that works but gives me a string hexadecimal version like {5e92e5bd-25ad-44a7-a977-8f34b736fed8}. The problem is that the aset file doesn’t use that, it uses the 4 data ints that the FMOD_GUID struct contain. So I tried to convert the hexadecimal into those 4 int fields and got almost there but could not figure out how to create the fourth field. Basically, I need to:

Turn {5e92e5bd-25ad-44a7-a977-8f34b736fed8} into 
Data1: 1586685373
Data2: 1151804845
Data3: 881817513
Data4: -654428489

Looking at the C# fmod unity plugin code, I found this:

        public GUID(Guid guid)
        {
            byte[] bytes = guid.ToByteArray();

            Data1 = BitConverter.ToInt32(bytes,  0);
            Data2 = BitConverter.ToInt32(bytes,  4);
            Data3 = BitConverter.ToInt32(bytes,  8);
            Data4 = BitConverter.ToInt32(bytes, 12);
        }

Which looks to me like the thing I need to do but I wasn’t able to do that in JavaScript (I’m sure is possible). That’s when I realized I was probably doing this the hard way. Maybe there is a way to directly grab these 4 int values from the event in the Javascript code somehow? Maybe there is an even simpler solution?

I think a js converter is the way to go, the unpacked 128bit integer isn’t available on the event itself but you should be able to calculate it easily enough by parsing the guid hex values. There is some byte swapping going on just to get the right endianness, here is an example:

function guidToBytes(str) {
    var array = [];
    for (var i = 0; i < str.length; i += 2) {
        if (str[i] == "}") {
            break;
        }
        if (str[i] == "-" || str[i] == "{") {
            i += 1;
        }
        array.push(parseInt(str[i] + str[i + 1], 16));
    }
    return array;
}

function byteArrayToLong(byteArray) {
    var value = 0;
    for (var i = byteArray.length - 1; i >= 0; i--) {
        value = (value * 256) + byteArray[i];
    }
    return value;
}

function bytesToGuidObject(bytes) {
    var guid = {}

    guid.Data1 = swap32(byteArrayToLong(bytes.slice(0, 4)));

    var d2 = bytes.slice(4, 8);
    guid.Data2 = swap32(byteArrayToLong([d2[2], d2[3], d2[0], d2[1]]));

    guid.Data3 = byteArrayToLong(bytes.slice(8, 12));

    var d4 = bytes.slice(12, 16);
    guid.Data4 = swap32(byteArrayToLong([d4[3], d4[2], d4[1], d4[0]]));

    return guid;
}

// Credit to LukeH for int32 swap endianness method https://stackoverflow.com/questions/5320439/how-do-i-swap-endian-ness-byte-order-of-a-variable-in-javascript
function swap32(val) {
    return ((val & 0xFF) << 24)
        | ((val & 0xFF00) << 8)
        | ((val >> 8) & 0xFF00)
        | ((val >> 24) & 0xFF);
}

var str = '{5e92e5bd-25ad-44a7-a977-8f34b736fed8}';
var bytes = guidToBytes(str);
var guid = bytesToGuidObject(bytes);

alert([guid.Data1, guid.Data2, guid.Data3, guid.Data4]);

Thanks, this works! Although there was a wrong parameter name. You had:

function bytesToGuidObject(byteArray) {

And I changed it to:

function bytesToGuidObject(bytes) {

Other than that, all is working, thanks again!

1 Like