#Animation Marker Exporter
1 messages ยท Page 1 of 1 (latest)
animation data serializer ๐
IT'S PERFECT.
i know it's metadata but that's so longggggggggg
animation data is keyframe transforms
ughhhhhhhhhh..................
use Marker Exporter
fine.
if you guys find any bugs make sure NOT to tell me โค๏ธ
ill make SURE that i TELL you
Ill make sure to email it
spam email.
markers can be anything
I mean I guess
sure
making plugins is so much fun!
i should make my own OS
i think
in holyC
just like terry davis intended
i actually sort of am larping
i've never released anything
today that changes.
new year new me. (it's april)
lol
i might change the name to be Parameter instead of Argument in the data
since that's what it's called in the animation editor too
oh right i have to actually worry about breaking changes
the world revolves around me dude get USED to it.
๐ซ
๐ซ
you can do it gng ๐ญ
๐คจ
riiiiiiight..... okay buddy........
i'm sure @haughty jasper could help you
๐
@chrome surge
its broken
{"Markers":[],"Keyframes":[]}
this is the attribute it always
saves
when there are events there
that's what it saves for empty stuff
if there are no events and no custom keyframes
i'll just make it not add anything then
are the animations published?
i mean
yeah
how else
would i get the ids
ugh
does it not work for just a few animations or does it not work for any?
and do any errors appear?
ffs gimme a sec
@chrome surge @frank patrol lmk when ts works
Ill make utility in animation manager
Rui Ferreira
rah
@frank patrol see if it works now
added some simple logging
just update the plugin or whatever
uses KeyframeSequenceProvider to export the times, names and an optional paramter value for keyframes and animation markers
{"Markers":{"Step":[{"Time":0,"Parameter":"Step"},{"Time":0.5,"Parameter":"Step"}]},"Keyframes":{"Step":[{"Time":0},{"Time":0.5}]}}
an example of an exported animation
Ah okay i see
i don't really see the use case myself but sinek and idan need it so ๐คท
first published plugin!!!
okay NOW it should work
i was requiring a types module which roblox doesn't let you do lol
flags your plugin as malware
huh????
show me your entire output
is it just the export complete and no markers or keyframes message?
so it's not failing to fetch them it just deems all of them as nil
could you send me your animations?
i probably need permissions don't i
well
idrc
but
the ids is fine?
@chrome surge
rbxassetid://71439886846067
this is an example
yup not authorized to use asset
ffs
can you give me permissions somehow
if you're the owner
idk how to do that
maybe moon animator has a different animation marker format or something?????
like they save it differently???
idfk
okay i'm getting the same thing as you
it skips over it
i need to head out for now once i get back i'll look into it
grrr
I'm home
so tired
but I'll look into it just for u bb
knees weak arms are heavy
there's vomit on my sweater already
moms spaghetti
sorry mom...
let's take a look ๐
let's take an eyes ๐
@frank patrol fixed
stupid oversight on my part
there's a lot of data i'm not removing even if it's empty, if it becomes an issue let me know
then again you're saving almost no space and you have to add nil checks in your code now
i think i'd rather just keep the consistent structure
yeah generate data no matter what
tbf
keep the tables empty
Keyframes and Markers
the only times i skip over it is if both are empty
is that okay?
tbf generate no matter what
so we know they don't have any rather than not generated
alr fair enough
done
generates entries no matter what and also works properly now
you have a cute little icon for the button now too
and a low res thumbnail i can't be bothered to change
entire code, give me suggestions or whatever
Nice work
you might want to play around with the strings you can set in Parameter, i don't know how well that works
like what if you input numbers
or .. .. to try and exit out of the thingamajig i don't know what it's called
basically SQL injection
looks good
my code wouldve been non typescripted
and that why i dont do plugins
cuz they are unreadable later
i started to love making plugins
I'm too stupid to make games โ๏ธ
ok
now make a vfx editing
plugin
you can loot at the emitter module of vfx forge for reference
there are a bunch of vfx plugins already
that would blow anything i make out of the water
๐ด pay me......
nah, im broke
actually no don't I wouldn't make it anyway
I'd take the money and run ๐ค
i don't like how you can't have modules in your plugins
you have to maintain one big ass file
gross
ima fork it a little
and make it
update
newly added animations
if you turn automod on
i'd like to see what you do with it
kk fair enough
aight
time to get to work
@chrome surge
can you assist me in my making
because
i never made plugins
plugin is just a script that runs when the plugin is loaded in
think of it like running a game
if you have scripts there with apropriate run context
they will run
you just set a scripts run context to "Plugin"
and it will run when the plugin (the .rbxm) is loaded
@frank patrol
that's all
how?
cuz like
when i write the code inside
there isnt even autofill
which makes me have no idea
what methods i can even use
wdym bro
there's auto fill
๐
it's just like writing normal scripts
how
can I stream you how to make plugin
really
wanna show
np
if you can ofc
@ocean current
local Connection
Connection = AutoSerializeInside.Click:Connect(function()
if enabled == false then
enabled = true
local Selections = SelectionService:Get()
if #Selections == 0 then warn('[Animation Marker Exporter] Nothing selected!') return end
for _,Selected in Selections do
if Selected:IsA('Folder') then
Selected.ChildAdded:Connect(function(Child)
if Child:IsA("Animation") and Child.AnimationId ~= nil then
ExportAnimation(Child)
end
end)
end
end
end
end)
how would i go about this
i want it
to
do it automaticly
if you turned on the button
so basicly you select a folder, you
press the button
and then when you add something inside of it, it automaticly saves it all
you need to connect to child added yeah basically
or descendant added
you can do game.Descendant added
and check if it's animation
that also works
um
wouldnt that be heavy
?
uhm....
that's the point
it's a plugin
made for preruntime
local Connection
AutoSerializeInside.Click:Connect(function()
if enabled == false then
enabled = true
Connection = game.ChildAdded:Connect(function(Child)
if Child:IsA("Animation") then
Child:GetPropertyChangedSignal("AnimationId"):Connect(function()
if Child.AnimationId ~= "" then
ExportAnimation(Child)
end
end)
end
end)
else
enabled = false
Connection:Disconnect()
end
end)
so smth like this
its unfinished
but
i think im getting the hang of it
alr i made it work @ocean current
my playlist on apple and spotify: https://shesgone.lnk.to/Apple-Spotify
music to calm your soul, to fall asleep to or to overthink.
all music is created by myself :)
#ambientmusic #sleepmusic #sadmusic #ambient
sad music for sleeping
balls (playlist)
time to make it work with ur plugin
bro the first piece of the trifecta
there's also hand
oh
๐ฅ
and then the DENIS
anyways
where can i find ur animation manager
cuz
ehm
im not scrolling
thru
1.5k messeges
actually you know what
Ill nuke that thread
holy shit
cant do
๐ญ
what would we call this
golden digga
goofy ah runnin around
WAIT
IS THAT THE SEX BULLETS STAND
WAIT
I DIDNT RECOGNIZE IT
IF IT IS OFC
not sure tho
its not them prolly
oof
Im gon make github for animation manager
aight
whos that diddy blud ๐ญ
he is bizzare
i do remember him getting beat up hard somewhere
why do ppl do it tho
like
huh
wierd af
like not having license automatically makes it untouchable by default for legal system
it counts as your work
MIT allows almost anything just requires attribution
can you say allows for forking and
changing stuff
and that sit?
yes
so
it allows that
apparently legal systems say no
digga waaaaaaaaaaaaaa
like
how can someone
sue you
for code u use
if they arent allowed
to see private
files
like
whaaaaaaaaaaaaaaaaattttt
Sinek License
๐คทโโ๏ธ
okay Ill do the unlicense
dawg
like all of these
enforce you to keep the license
I can't get around it unfortunately
๐ญ
dawg if Im uploading to a platform like that
Im claiming the code
just want to do it right
say free to use and redestribute
yeah
if they doi
i credit
and leave the liscense
but usualy its without any license
If there's no license
encourage them to pick one
it makes things easier for everyone
and more secure
yeah
he got beat up
fuckass won 5 mil
because his friends helped him
and he gave them 1k each calling them beggar
beggars* and telling them to leave him alone
so bizzare
you'll have to reselect the folder each time
save the folder path with plugin:SetSetting()
and save the gameid too
so it doesn't look for that folder in the wrong game
i can try implementing that sometime someday
but tomorrow idk if I'll be able to
Shouldn't be a problem
Ive made it work
Currently I do have to press it each time I load in
But
I make it auto load if it's on already
i could make you a version where you save the folder path once and it works always
I'd probably make it so you can only track a single root folder though
dw
ill figure it out
on my own
i already got the core
now i just have to make it automaticly turn on if the last session it was turned on
I DID IT!
YESSIRRR
FINALLY
now,
ill have to make a custom animation system
that uses it
cuz
@ocean current doesnt want to add it on his own
๐
and i dont know how to even start forking his code
bro you just need to add 2 new functions
GetAnimationMarkerTimepositions
GetKeyframeTimepositions
like the code is very simple
like
i dont understand how to use ur system
like overall
i understand what it does
but i cant seem to understand on using it
you have :Play
that's it
that's where you start
plays an animation track
how do you play animations usually
@chrome surge
how would i decode it tho?
if i want to get the info
i have to decode it somehow
aight
i already did it
local function DecodeData(instance)
local raw = instance:GetAttribute("Data")
if not raw then return nil end
return HttpService:JSONDecode(raw)
end
local function GetAllMarkerTimings(animation: Animation, markername: string): {}
local decoded = DecodeData(animation)
if decoded then
local markers = decoded.Markers
if markers then
local markerlist = {}
for name, list in markers do
table.insert(markerlist,name)
end
return markerlist
end
end
return {}
end
local function GetTimeToMarker(animation: Animation, markername: string): number?
local decoded = DecodeData(animation)
if not decoded then return nil end
local markers = decoded.Markers
if not markers then return nil end
local markerList = markers[markername]
if not markerList or #markerList == 0 then return nil end
return markerList[1].Time
end
``` ts is what i added to @ocean current s module
unfinished yet
but
prolly will work
you can even cache the data when it's decoded for the first time
make a global table for them
the second one
what if you have multiple markers
use markerIndex
as an argument
also markername should be markerName
it only gets the first marker
make markerIndex: number?
it defaults to 1
local function GetTimeToMarker(animation: Animation, markerName: string): number?
local decoded = DecodeData(animation)
if not decoded then return nil end
local markers = decoded.Markers
if not markers then return nil end
local markerList = markers[markerName]
if not markerList or #markerList == 0 then return nil end
print(markerList[1].Time)
return markerList[1].Time
end
its get time to marker*
its for 1 marker
local function GetTimeToMarker(animation: Animation, markerName: string, markerIndex: number?): number?
local decoded = DecodeData(animation)
if not decoded then return nil end
local markers = decoded.Markers
if not markers then return nil end
local markerList = markers[markerName]
if not markerList or #markerList == 0 then return nil end
local markerIndex = markerIndex or 1
local markerData = markerList[markerIndex]
if not markerData then return nil end
return markerData.Time
end
i got get all markerrs
use this
also cache the decoded marker data
because you may have it run for 100 npcs
no
like
i was talking about
like checking if the animation was cached already
and if it was skip the stuff
right?
Im talking about marker data
being cached
I already cache anything else
dont json decode every time
only do it once
also this only construct the marker data once
and do that even if you just want to get a single marker
lazy loading
hm
well
how do i do it tho
local function DecodeData(instance)
local raw = instance:GetAttribute("Data")
if not raw then return nil end
return HttpService:JSONDecode(raw)
end
local function GetAllMarkerTimings(animation: Animation): {}
local decoded = DecodeData(animation)
if decoded then
local markers = decoded.Markers
if markers then
local markerlist = {}
for name, list in pairs(markers) do
for _, markerData in pairs(list) do
local Time = markerData.Time
warn("Time: ", Time ," Name:", name)
table.insert(markerlist, {
Name = name,
Time = Time
})
end
end
return markerlist
end
end
return {}
end
local function GetTimeToMarker(animation: Animation, markerName: string, markerIndex: number?): number?
local decoded = DecodeData(animation)
if not decoded then return nil end
local markers = decoded.Markers
if not markers then return nil end
local markerList = markers[markerName]
if not markerList or #markerList == 0 then return nil end
local markerIndex = markerIndex or 1
local markerData = markerList[markerIndex]
if not markerData then return nil end
return markerData.Time
end
this is what i got rn
@ocean current
exactly
in the types thingy?
save it in the global table
and use it to retrieve
just like what I did for animation length
local AnimationMarkerData = {} :: {[Animation]: {}}
so this basicly
at the start
where i save all global tables
exactly
and specify some type for it
types are not as complicated as they look
trust me
but what type
should i save it as
cuz
so like number,
like
string,number?
for name,time?
type MarkerData = {[string]: {
TimePosition: number,
Parameter: string?,
}
}
@frank patrol
save it like so
types are really simple really
oh can I see
yes
put it there
no need to export it
put it higher than the class type
type KeyframeData = {[string]: {
TimePosition: number,
}
}
and KeyframeData
I did this to show you how the types look expanded
like that i suppose
I usually do
type MarkerData = {[string]: {{TimePosition: number, Parameter: string?}}}
looks better imo
yeah nope
what does export do tho
it allows you to access the type by requiring the module
local a: AnimationManager.MarkerData = nil
hm ic
yes they need a better way to export types
i use it here:
local AnimationMarkerData = {} :: {MarkerData}
I agree
Yes twin
:: {[Animation]: MarkerData}
it's per animation
also leave the table empty if there's no data for it
so we know it was processed before
wait
so can i for example
save it from here:
local function DecodeData(instance)
local raw = instance:GetAttribute("Data")
if not raw then return nil end
return HttpService:JSONDecode(raw)
end
should i maybe save it when i decode the data?
.
yes
exactly
process only once mentality
so then when i call decode
@frank patrol
I made a mistake here
it checks if it has been saved already
yeah exactly if it has been cached
update your type
aight ill try ma best
yeah
i already did
before
you told me
alr alr
i saw a syntax error
that's how you grow
not everything will be served to your plate
๐
yeah i know
thats why im trying to do it on my own
no chatlgbt this time ๐ฅ
ill learn more by working on plugins prolly
since i wont get sidetracked
by vfx animations
ye exactly
and other stuff
also btw
i noticed that if i want to test
with the command line
i have to restart studio
each time if i want the command bar to load the new code
any way to fix?
@ocean current
for plugins?
why are you testing in command line
for some reason
just test by running the game
yeah nah
so basicly i save it like that:
AnimationMarkerData[instance] = Proccessed.Markers
warn(AnimationMarkerData[instance])
and now i have to make checks to see if it has been cached already
im thinking about
either doing Proccessed.Markers
or
just Proccessed
exactly
also
it should be this:
type MarkerData = {[string]: {{Parameter: string?,TimePosition: number}}}
and not
timeposition fist
cuz
honestly
22:18:29.756 โผ {
["hitreg"] = โผ {
[1] = โผ {
["Parameter"] = "",
["Time"] = 0.4000000059604645
}
}
save keyframe and marker data at the same time
better imo
since you will decode anyways
you can do
do what?
cuz
i mean i could add more stuff
into the type
but whats the point
if its too long
it will just be confusing af
local AnimationMetadata = {} :: {[Animation]: {
MarkerData: MarkerData?,
KeyframeData: KeyframeData?,
}}
yeah this
then you can check if they have the table
if they do it is already processed
it won't trust
this is not confusing at all
very intuitive
um
like
whats the point of having that?
basically saying merge the data
hm
whats the point of having it tho
wdym what's the point
to make your life easier
Idk how you can't see this simplifies things
decode data once and then save it as metadata
for auto complete?
get rid of the other global tables
use AnimationMetadata global table
index with the instance itself to save the decoded data
local AnimationLengths = {} :: {[Animation]: number}
local AnimationByPath = {} :: any
local AnimationMarkerData = {} :: {[Animation]: MarkerData}
local AnimationMetadata = {} :: {[Animation]: {MarkerData: MarkerData?,KeyframeData: KeyframeData?,}}
get rid of the other one
yes
yea exactly
๐ญ
๐ซก
brother
you have keyframes
aswell
did you forget
๐
don't make shit only for yourself
challange yourself to generalize a bit
it's literally marker data
without parameter
you can also save it as a number list
that's also valid
{number}
local function DecodeData(instance)
if AnimationMetadata[instance] then return AnimationMetadata[instance] end
local raw = instance:GetAttribute("Data")
local Proccessed = HttpService:JSONDecode(raw)
AnimationMetadata[instance] = Proccessed
warn(AnimationMetadata[instance])
return Proccessed
end
so
basicly this right?
not sure
if its exactly the way you wanted me to optimize
but it does seem like it would optimize a lil
yeah i understand
but i didnt make the plugin
and i have absolutly no idea
what it would contain
considering that it always prints this for my animation outputs:
you haven't tried it???
22:30:15.796 โผ {
["Keyframes"] = {},
["Markers"] = โผ {
["hitreg"] = โผ {
[1] = โผ {
["Parameter"] = "",
["Time"] = 0.4000000059604645
}
}
}
} - Server - AnimationManager:97
nope
HOW!?!?
if it prints
it's already working
check the attribute
on the animation instance
{"Markers":{"hitreg":[{"Time":0.4000000059604645,"Parameter":""}]},"Keyframes":[]}
empty
yeah bro then it2s empty
that means there's no keyframe data for it
it ignores keyframes named "Keyframe"
@chrome surge make it so when parameter is not existent it saves it as nil
i got a ton of questions
bro
you can change name of keyframes
and get keyframes by name
that's it
that's what it is
so basicly you can move an animation to a named keyframe right?
in animation editor
double click the thing
and rename
it might be right click too
Idk how you never noticed you can rename keyframes
what about moon animator ๐ญ
need to export manually for it probably
cuz moon animator is stupid
yeah they are deprecated
events or namings?
hm
aight
good to know i guess
--!strict
type MarkerData = {[string]: {{Parameter: string?,TimePosition: number}}}
type KeyframeData = {[Keyframe]: {Name: string?}}
so after allat
it should look like this right?
also
here
local AnimationMetadata = {} :: {[Animation]: {KeyframeData: KeyframeData?,MarkerData: MarkerData?}}
it should be like that
instead of the opposite
you just need string
like before
type KeyframeData = {[string]: {number}}
string is keyframe name
sinek
yk what
when you are bored
make a tutorial
on how to use and understand this ts code
cuz
im personaly still kinda confused
I thought the code was as clean as it gets
i mean i guess not everyone can see clean as clean
also
you didnt answer my question
local function DecodeData(instance)
if AnimationMetadata[instance] then return AnimationMetadata[instance] end
local raw = instance:GetAttribute("Data")
local Proccessed = HttpService:JSONDecode(raw)
AnimationMetadata[instance] = Proccessed
warn(AnimationMetadata[instance])
return Proccessed
end
is the idea implemented right here?
yes it's good
a little refactor tho
variable naming can be better
fuck no
Im abandoning you
get out
what is that table insert bs btw
I don't get it
@frank patrol
make a type for animation metadata
actually
type AnimationMetadata = {
MarkerData: MarkerData?,
KeyframeData: KeyframeData?,
}
and Id do it like this
broooo
YOU KEEP
WRITING IT
THE OPOSSITE
WAY
ITS THE KEYFRAME DATA
AND THEN MARKER DATA
RAHHHHHHH
local function GetAnimationMetadata(animation: Animation): AnimationMetadata
local metadata = AnimationMetadata[animation]
if metadata then return metadata end
local jsonData = instance:GetAttribute("Data")
local metadata = HttpService:JSONDecode(jsonData)
AnimationMetadata[animation] = metadata
return metadata
end
@frank patrol
isnt it the same thing?
ah
ok
i get it
so you make it return
a known type

exactly
btw
the decoded.markers
i think i missed something when setting up the types
tryna find
where the chain started
Markers are optional
Dont forget
Also you dont have {MarkerData}
That means an array ot MarkerData
Because MarkerData is optional
even without
It can be nil
Also dont call it decoded call it metadata
right

