From 6a44517e6215c40ebdd4240ba9e8250f7fee2e5d Mon Sep 17 00:00:00 2001 From: Rollin'Barrel Date: Sun, 21 Sep 2025 11:22:25 +0300 Subject: [PATCH 1/2] add Timeline API --- Makefile | 3 ++- hlsteam.vcxproj | 1 + native/timeline.cpp | 34 ++++++++++++++++++++++++++++++++++ steam/Timeline.hx | 17 +++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 native/timeline.cpp create mode 100644 steam/Timeline.hx diff --git a/Makefile b/Makefile index 403edbf..4be7d7f 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,8 @@ endif LFLAGS = -lhl -lsteam_api -lstdc++ -L sdk/redistributable_bin/$(OS)$(ARCH) SRC = native/cloud.o native/common.o native/controller.o native/friends.o native/gameserver.o \ - native/matchmaking.o native/networking.o native/stats.o native/ugc.o + native/matchmaking.o native/networking.o native/stats.o native/ugc.o native/timeline.o + all: ${SRC} ${CC} ${CFLAGS} -shared -o steam.hdll ${SRC} ${LFLAGS} diff --git a/hlsteam.vcxproj b/hlsteam.vcxproj index 95b35b6..fe78990 100644 --- a/hlsteam.vcxproj +++ b/hlsteam.vcxproj @@ -283,6 +283,7 @@ + diff --git a/native/timeline.cpp b/native/timeline.cpp new file mode 100644 index 0000000..236a246 --- /dev/null +++ b/native/timeline.cpp @@ -0,0 +1,34 @@ +#include "steamwrap.h" + +HL_PRIM void HL_NAME(set_timeline_state_description)(vbyte* description, float timeDelta) { + ISteamTimeline* timeline = SteamTimeline(); + if (timeline) { + timeline->SetTimelineStateDescription((char*)description, timeDelta); + } +} + +HL_PRIM void HL_NAME(clear_timeline_state_description)(float timeDelta) { + ISteamTimeline* timeline = SteamTimeline(); + if (timeline) { + timeline->ClearTimelineStateDescription(timeDelta); + } +} + +HL_PRIM void HL_NAME(add_timeline_event)(vbyte* icon, vbyte* title, vbyte* description, int priority, float startOffsetSeconds, float durationSeconds, int possibleClip) { + ISteamTimeline* timeline = SteamTimeline(); + if (timeline) { + timeline->AddTimelineEvent((char*)icon, (char*)title, (char*)description, priority, startOffsetSeconds, durationSeconds, (ETimelineEventClipPriority)possibleClip); + } +} + +HL_PRIM void HL_NAME(set_timeline_game_mode)(int mode) { + ISteamTimeline* timeline = SteamTimeline(); + if (timeline) { + timeline->SetTimelineGameMode((ETimelineGameMode)mode); + } +} + +DEFINE_PRIM(_VOID, set_timeline_state_description, _BYTES _F32); +DEFINE_PRIM(_VOID, clear_timeline_state_description, _F32); +DEFINE_PRIM(_VOID, add_timeline_event, _BYTES _BYTES _BYTES _I32 _F32 _F32 _I32); +DEFINE_PRIM(_VOID, set_timeline_game_mode, _I32); \ No newline at end of file diff --git a/steam/Timeline.hx b/steam/Timeline.hx new file mode 100644 index 0000000..2728367 --- /dev/null +++ b/steam/Timeline.hx @@ -0,0 +1,17 @@ +package steam; + +@:hlNative("steam") +class Timeline { + public static function setTimelineStateDescription(description:String, timeDelta:hl.F32):Void { + @:privateAccess _SetTimelineStateDescription(description.toUtf8(), timeDelta); + } + public static function clearTimelineStateDescription(timeDelta:hl.F32):Void {} + public static function addTimelineEvent(icon:String, title:String, description:String, priority:Int, startOffsetSeconds:hl.F32, durationSeconds:hl.F32, possibleClip:Int):Void { + @:privateAccess _AddTimelineEvent(icon.toUtf8(), title.toUtf8(), description.toUtf8(), priority, startOffsetSeconds, durationSeconds, possibleClip); + } + public static function setTimelineGameMode(mode:Int):Void {} + + + @:hlNative("?steam", "set_timeline_state_description") private static function _SetTimelineStateDescription(description:hl.Bytes, timeDelta:hl.F32):Void {} + @:hlNative("?steam", "add_timeline_event") private static function _AddTimelineEvent(icon:hl.Bytes, title:hl.Bytes, description:hl.Bytes, priority:Int, startOffsetSeconds:hl.F32, durationSeconds:hl.F32, possibleClip:Int):Void {} +} \ No newline at end of file From 02ee8e15a56e917ebdd9529d46530a9540776b68 Mon Sep 17 00:00:00 2001 From: Yuxiao Mao Date: Wed, 10 Jun 2026 09:28:10 +0200 Subject: [PATCH 2/2] Update to new Timeline definitions and add missing function --- Makefile | 1 - native/timeline.cpp | 62 ++++++++++++++++++++------------- steam/Timeline.hx | 83 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 107 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index 02bcad8..814859d 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,6 @@ LFLAGS = -lhl -lsteam_api -lstdc++ -L $(SDK_BIN_DIR) SRC = native/cloud.o native/common.o native/controller.o native/friends.o native/gameserver.o \ native/matchmaking.o native/networking.o native/stats.o native/ugc.o native/timeline.o - all: ${SRC} ${CC} ${CFLAGS} -shared -o steam.hdll ${SRC} ${LFLAGS} diff --git a/native/timeline.cpp b/native/timeline.cpp index 236a246..e0b7aea 100644 --- a/native/timeline.cpp +++ b/native/timeline.cpp @@ -1,34 +1,48 @@ #include "steamwrap.h" -HL_PRIM void HL_NAME(set_timeline_state_description)(vbyte* description, float timeDelta) { - ISteamTimeline* timeline = SteamTimeline(); - if (timeline) { - timeline->SetTimelineStateDescription((char*)description, timeDelta); - } +HL_PRIM void HL_NAME(set_timeline_tooltip)( vbyte* description, float timeDelta ) { + SteamTimeline()->SetTimelineTooltip((char*)description, timeDelta); } -HL_PRIM void HL_NAME(clear_timeline_state_description)(float timeDelta) { - ISteamTimeline* timeline = SteamTimeline(); - if (timeline) { - timeline->ClearTimelineStateDescription(timeDelta); - } +HL_PRIM void HL_NAME(clear_timeline_tooltip)( float timeDelta ) { + SteamTimeline()->ClearTimelineTooltip(timeDelta); } -HL_PRIM void HL_NAME(add_timeline_event)(vbyte* icon, vbyte* title, vbyte* description, int priority, float startOffsetSeconds, float durationSeconds, int possibleClip) { - ISteamTimeline* timeline = SteamTimeline(); - if (timeline) { - timeline->AddTimelineEvent((char*)icon, (char*)title, (char*)description, priority, startOffsetSeconds, durationSeconds, (ETimelineEventClipPriority)possibleClip); - } +HL_PRIM void HL_NAME(set_timeline_game_mode)( ETimelineGameMode mode ) { + SteamTimeline()->SetTimelineGameMode(mode); } -HL_PRIM void HL_NAME(set_timeline_game_mode)(int mode) { - ISteamTimeline* timeline = SteamTimeline(); - if (timeline) { - timeline->SetTimelineGameMode((ETimelineGameMode)mode); - } +HL_PRIM TimelineEventHandle_t HL_NAME(add_instantaneous_timeline_event)( vbyte* title, vbyte* description, vbyte* icon, int priority, float startOffsetSeconds, ETimelineEventClipPriority possibleClip ) { + return SteamTimeline()->AddInstantaneousTimelineEvent((char*)title, (char*)description, (char*)icon, priority, startOffsetSeconds, possibleClip); } -DEFINE_PRIM(_VOID, set_timeline_state_description, _BYTES _F32); -DEFINE_PRIM(_VOID, clear_timeline_state_description, _F32); -DEFINE_PRIM(_VOID, add_timeline_event, _BYTES _BYTES _BYTES _I32 _F32 _F32 _I32); -DEFINE_PRIM(_VOID, set_timeline_game_mode, _I32); \ No newline at end of file +HL_PRIM TimelineEventHandle_t HL_NAME(add_range_timeline_event)( vbyte* title, vbyte* description, vbyte* icon, int priority, float startOffsetSeconds, float durationSeconds, ETimelineEventClipPriority possibleClip ) { + return SteamTimeline()->AddRangeTimelineEvent((char*)title, (char*)description, (char*)icon, priority, startOffsetSeconds, durationSeconds, possibleClip); +} + +HL_PRIM TimelineEventHandle_t HL_NAME(start_range_timeline_event)( vbyte* title, vbyte* description, vbyte* icon, int priority, float startOffsetSeconds, ETimelineEventClipPriority possibleClip ) { + return SteamTimeline()->StartRangeTimelineEvent((char*)title, (char*)description, (char*)icon, priority, startOffsetSeconds, possibleClip); +} + +HL_PRIM void HL_NAME(update_range_timeline_event)( TimelineEventHandle_t event, vbyte* title, vbyte* description, vbyte* icon, int priority, ETimelineEventClipPriority possibleClip ) { + SteamTimeline()->UpdateRangeTimelineEvent(event, (char*)title, (char*)description, (char*)icon, priority, possibleClip); +} + +HL_PRIM void HL_NAME(end_range_timeline_event)( TimelineEventHandle_t event, float endOffsetSeconds ) { + SteamTimeline()->EndRangeTimelineEvent(event, endOffsetSeconds); +} + +HL_PRIM void HL_NAME(remove_timeline_event)( TimelineEventHandle_t event ) { + SteamTimeline()->RemoveTimelineEvent(event); +} + +#define _TIMELINEEVENT _I64 +DEFINE_PRIM(_VOID, set_timeline_tooltip, _BYTES _F32); +DEFINE_PRIM(_VOID, clear_timeline_tooltip, _F32); +DEFINE_PRIM(_VOID, set_timeline_game_mode, _I32); +DEFINE_PRIM(_TIMELINEEVENT, add_instantaneous_timeline_event, _BYTES _BYTES _BYTES _I32 _F32 _I32); +DEFINE_PRIM(_TIMELINEEVENT, add_range_timeline_event, _BYTES _BYTES _BYTES _I32 _F32 _F32 _I32); +DEFINE_PRIM(_TIMELINEEVENT, start_range_timeline_event, _BYTES _BYTES _BYTES _I32 _F32 _I32); +DEFINE_PRIM(_VOID, update_range_timeline_event, _TIMELINEEVENT _BYTES _BYTES _BYTES _I32 _I32); +DEFINE_PRIM(_VOID, end_range_timeline_event, _TIMELINEEVENT _F32); +DEFINE_PRIM(_VOID, remove_timeline_event, _TIMELINEEVENT); diff --git a/steam/Timeline.hx b/steam/Timeline.hx index 2728367..a4038c3 100644 --- a/steam/Timeline.hx +++ b/steam/Timeline.hx @@ -1,17 +1,72 @@ package steam; -@:hlNative("steam") +enum abstract ETimelineGameMode(Int) from Int to Int { + var Invalid = 0; + var Playing = 1; + var Staging = 2; + var Menus = 3; + var LoadingScreen = 4; +} + +enum abstract ETimelineEventClipPriority(Int) from Int to Int { + var Invalid = 0; + var None = 1; + var Standard = 2; + var Featured = 3; +} + +typedef TimelineEventHandle = hl.I64; + +@:access(steam.TimelineNative) class Timeline { - public static function setTimelineStateDescription(description:String, timeDelta:hl.F32):Void { - @:privateAccess _SetTimelineStateDescription(description.toUtf8(), timeDelta); - } - public static function clearTimelineStateDescription(timeDelta:hl.F32):Void {} - public static function addTimelineEvent(icon:String, title:String, description:String, priority:Int, startOffsetSeconds:hl.F32, durationSeconds:hl.F32, possibleClip:Int):Void { - @:privateAccess _AddTimelineEvent(icon.toUtf8(), title.toUtf8(), description.toUtf8(), priority, startOffsetSeconds, durationSeconds, possibleClip); - } - public static function setTimelineGameMode(mode:Int):Void {} - - - @:hlNative("?steam", "set_timeline_state_description") private static function _SetTimelineStateDescription(description:hl.Bytes, timeDelta:hl.F32):Void {} - @:hlNative("?steam", "add_timeline_event") private static function _AddTimelineEvent(icon:hl.Bytes, title:hl.Bytes, description:hl.Bytes, priority:Int, startOffsetSeconds:hl.F32, durationSeconds:hl.F32, possibleClip:Int):Void {} -} \ No newline at end of file + public static function setTimelineTooltip(description:String, timeDelta:Float):Void { + @:privateAccess TimelineNative.setTimelineTooltip(description.toUtf8(), timeDelta); + } + + public static function clearTimelineTooltip(timeDelta:Float):Void { + TimelineNative.clearTimelineTooltip(timeDelta); + } + + public static function setTimelineGameMode(mode:ETimelineGameMode):Void { + TimelineNative.setTimelineGameMode(mode); + } + + public static function addInstantaneousTimelineEvent(title:String, description:String, icon:String, priority:Int, startOffsetSeconds:Float, possibleClip:ETimelineEventClipPriority = None):TimelineEventHandle { + return @:privateAccess TimelineNative.addInstantaneousTimelineEvent(title.toUtf8(), description.toUtf8(), icon.toUtf8(), priority, startOffsetSeconds, possibleClip); + } + + public static function addRangeTimelineEvent(title:String, description:String, icon:String, priority:Int, startOffsetSeconds:Float, durationSeconds:Float, possibleClip:ETimelineEventClipPriority = None):TimelineEventHandle { + return @:privateAccess TimelineNative.addRangeTimelineEvent(title.toUtf8(), description.toUtf8(), icon.toUtf8(), priority, startOffsetSeconds, durationSeconds, possibleClip); + } + + public static function startRangeTimelineEvent(title:String, description:String, icon:String, priority:Int, startOffsetSeconds:Float, possibleClip:ETimelineEventClipPriority = None):TimelineEventHandle { + return @:privateAccess TimelineNative.startRangeTimelineEvent(title.toUtf8(), description.toUtf8(), icon.toUtf8(), priority, startOffsetSeconds, possibleClip); + } + + public static function updateRangeTimelineEvent(event:TimelineEventHandle, title:String, description:String, icon:String, priority:Int, possibleClip:ETimelineEventClipPriority = None):Void { + @:privateAccess TimelineNative.updateRangeTimelineEvent(event, title.toUtf8(), description.toUtf8(), icon.toUtf8(), priority, possibleClip); + } + + public static function endRangeTimelineEvent(event:TimelineEventHandle, endOffsetSeconds:Float):Void { + TimelineNative.endRangeTimelineEvent(event, endOffsetSeconds); + } + + public static function removeTimelineEvent(event:TimelineEventHandle):Void { + TimelineNative.removeTimelineEvent(event); + } +} + +@:hlNative("steam") +class TimelineNative { + static function setTimelineTooltip(description:hl.Bytes, timeDelta:hl.F32):Void {} + static function clearTimelineTooltip(timeDelta:hl.F32):Void {} + static function setTimelineGameMode(mode:Int):Void {} + + static function addInstantaneousTimelineEvent(title:hl.Bytes, description:hl.Bytes, icon:hl.Bytes, priority:Int, startOffsetSeconds:hl.F32, possibleClip:Int):hl.I64 { return 0; } + static function addRangeTimelineEvent(title:hl.Bytes, description:hl.Bytes, icon:hl.Bytes, priority:Int, startOffsetSeconds:hl.F32, durationSeconds:hl.F32, possibleClip:Int):hl.I64 { return 0; } + + static function startRangeTimelineEvent(title:hl.Bytes, description:hl.Bytes, icon:hl.Bytes, priority:Int, startOffsetSeconds:hl.F32, possibleClip:Int):hl.I64 { return 0; } + static function updateRangeTimelineEvent(event:hl.I64, title:hl.Bytes, description:hl.Bytes, icon:hl.Bytes, priority:Int, possibleClip:Int):Void {} + static function endRangeTimelineEvent(event:hl.I64, endOffsetSeconds:hl.F32):Void {} + static function removeTimelineEvent(event:hl.I64):Void {} +}