Gondwana Game Engine Development (master) - 2.6.1
Gondwana is a cross-platform 2.5D game and rendering engine written in C#/.NET 8. It provides fine-grained control over rendering, timing, and scene composition, with built-in support for parallax, z-ordering, pixel overhang, collision detection, and particle effects. Gondwana targets desktop and web platforms using SkiaSharp for graphics and pluggable audio backends for desktop and browser targets.
Loading...
Searching...
No Matches
VideoWidget.cs
1using System.Drawing;
2using System.Numerics;
8
10
18public sealed class VideoWidget : DraggableWidgetBase
19{
20 private readonly IVideoPlayer _player;
21
29 public VideoWidget(RenderSurfaceHostBase renderSurfaceHost, View view, Rectangle bounds,
30 VideoSource source, Func<IVideoPlayer>? playerFactory = null, string? nickname = null)
31 : base(renderSurfaceHost, DirectDrawingMode.View, ValidateBounds(bounds).Location, nickname)
32 {
33 try
34 {
35 ArgumentNullException.ThrowIfNull(view);
36 ArgumentNullException.ThrowIfNull(source);
37 IVideoPlayer? player = null;
38 Video = new DirectVideo(() => player = (playerFactory ?? DefaultPlayerFactory)(),
39 source, renderSurfaceHost, view, bounds, $"{Nickname}.video");
40 _player = player!;
41 InitializeVideo();
42 }
43 catch
44 {
45 base.Dispose(); // DirectComposite registered this instance before construction completed.
46 throw;
47 }
48 }
49
57 public VideoWidget(RenderSurfaceHostBase renderSurfaceHost, SceneLayer sceneLayer, Rectangle bounds,
58 VideoSource source, Func<IVideoPlayer>? playerFactory = null, string? nickname = null)
59 : base(renderSurfaceHost, DirectDrawingMode.SceneLayer, ValidateBounds(bounds).Location, nickname)
60 {
61 try
62 {
63 ArgumentNullException.ThrowIfNull(sceneLayer);
64 ArgumentNullException.ThrowIfNull(source);
65 IVideoPlayer? player = null;
66 Video = new DirectVideo(() => player = (playerFactory ?? DefaultPlayerFactory)(),
67 source, renderSurfaceHost, sceneLayer, bounds, $"{Nickname}.video");
68 _player = player!;
69 InitializeVideo();
70 }
71 catch
72 {
73 base.Dispose();
74 throw;
75 }
76 }
77
85 public VideoWidget(RenderSurfaceHostBase renderSurfaceHost, View view, Rectangle bounds,
86 VideoSource source, IVideoPlayer player, string? nickname = null)
87 : this(renderSurfaceHost, view, bounds, source, OwnedPlayerFactory(player), nickname) { }
88
96 public VideoWidget(RenderSurfaceHostBase renderSurfaceHost, SceneLayer sceneLayer, Rectangle bounds,
97 VideoSource source, IVideoPlayer player, string? nickname = null)
98 : this(renderSurfaceHost, sceneLayer, bounds, source, OwnedPlayerFactory(player), nickname) { }
99
101 public DirectVideo Video { get; }
102
104 public Rectangle Bounds => Mode == DirectDrawingMode.View ? Video.ScreenBounds : Video.WorldBounds;
105
109 public VideoWidget SetBounds(Rectangle bounds)
110 {
111 ValidateBounds(bounds);
112 SetPosition(bounds.X, bounds.Y);
113 SetLocalOffset(Video, Vector2.Zero);
114 if (Mode == DirectDrawingMode.View) Video.ScreenBounds = bounds;
115 else Video.WorldBounds = bounds;
116 return this;
117 }
118
120 public void Play() => Video.Play();
122 public void Pause() => Video.Pause();
124 public void Stop() => Video.Stop();
127 public void Seek(TimeSpan position) => Video.Seek(position);
130 public void Open(VideoSource source) => Video.Open(source);
133 public void Open(Uri source) => Video.Open(source);
135 public double PlaybackRate { get => Video.PlaybackRate; set => Video.PlaybackRate = value; }
137 public bool Loop { get => Video.Loop; set => Video.Loop = value; }
139 public StretchMode Stretch { get => Video.Stretch; set => Video.Stretch = value; }
141 public bool IsPlaying => _player.IsPlaying;
143 public TimeSpan Duration => _player.Duration;
145 public TimeSpan Position => _player.Position;
147 public (int width, int height) NaturalSize => Video.NaturalSize;
149 public bool HasAudio => _player.HasAudio;
151 public bool IsMetadataReady => _player.IsMetadataReady;
153 public VideoMetadata Metadata => Video.Metadata;
154
156 public event EventHandler Started { add => _player.Started += value; remove => _player.Started -= value; }
158 public event EventHandler Paused { add => _player.Paused += value; remove => _player.Paused -= value; }
160 public event EventHandler Stopped { add => _player.Stopped += value; remove => _player.Stopped -= value; }
162 public event EventHandler Ended { add => _player.Ended += value; remove => _player.Ended -= value; }
164 public event EventHandler<VideoStateChangedEventArgs> StateChanged
165 {
166 add => _player.StateChanged += value;
167 remove => _player.StateChanged -= value;
168 }
169
170 private void InitializeVideo()
171 {
172 try { Add(Video, keepCurrentOffset: false, explicitLocalOffsetPx: Vector2.Zero); }
173 catch { Video.Dispose(); throw; }
174 IsDragEnabled = false;
175 CanReceiveFocus = true;
177 }
178
179 private static IVideoPlayer DefaultPlayerFactory() => new VlcVideoPlayer();
180
181 private static Func<IVideoPlayer> OwnedPlayerFactory(IVideoPlayer player)
182 {
183 ArgumentNullException.ThrowIfNull(player);
184 return () => player;
185 }
186
187 private static Rectangle ValidateBounds(Rectangle bounds)
188 {
189 if (bounds.Width <= 0 || bounds.Height <= 0)
190 throw new ArgumentOutOfRangeException(nameof(bounds), bounds, "Video widget size must be positive.");
191 return bounds;
192 }
193}
SceneLayer? SceneLayer
Gets the scene layer shared by all children in scene-layer mode.
DirectComposite SetLocalOffset(IDirectCompositeChild child, Vector2 newLocalOffsetPx)
Changes one child's local offset and reapplies its position.
View? View
Gets the view shared by all children in view mode.
virtual DirectComposite Add(IDirectCompositeChild child, bool keepCurrentOffset=true, Vector2? explicitLocalOffsetPx=null)
Adds a composite-compatible direct drawable as a child.
void SetPosition(Vector2 position)
Sets the composite anchor and repositions all children from their stored offsets.
DirectDrawingMode Mode
Gets the coordinate mode shared by the composite and its children.
Draws video frames provided by IVideoPlayer onto the backbuffer. Audio is handled by the IVideoPlayer...
Represents a base class for hosting a render surface, providing functionality for managing rendering ...
A URI, borrowed/owned stream, or GAF asset to open with a video backend.
Definition VideoSource.cs:7
TimeSpan Duration
Gets media duration; check metadata readiness before interpreting unknown values.
VideoWidget(RenderSurfaceHostBase renderSurfaceHost, SceneLayer sceneLayer, Rectangle bounds, VideoSource source, IVideoPlayer player, string? nickname=null)
Creates a scene-layer widget transferring player ownership to DirectVideo.
DirectVideo Video
Gets the owned drawing for advanced configuration. Do not dispose it separately.
void Stop()
Stops playback; DirectVideo retains its last consumed frame.
void Seek(TimeSpan position)
Seeks to a media position.
void Play()
Starts or resumes playback.
int width
Gets actual decoded dimensions, or (0, 0) before discovery.
bool HasAudio
Gets audio-track presence; false is inconclusive until metadata is ready.
VideoMetadata Metadata
Gets the authoritative metadata snapshot.
Rectangle Bounds
Gets presentation bounds in screen pixels (View) or world pixels (SceneLayer).
VideoWidget(RenderSurfaceHostBase renderSurfaceHost, SceneLayer sceneLayer, Rectangle bounds, VideoSource source, Func< IVideoPlayer >? playerFactory=null, string? nickname=null)
Creates a scene-layer/world-space widget. The default factory creates VlcVideoPlayer.
VideoWidget(RenderSurfaceHostBase renderSurfaceHost, View view, Rectangle bounds, VideoSource source, IVideoPlayer player, string? nickname=null)
Creates a view widget transferring player ownership to DirectVideo.
VideoWidget(RenderSurfaceHostBase renderSurfaceHost, View view, Rectangle bounds, VideoSource source, Func< IVideoPlayer >? playerFactory=null, string? nickname=null)
Creates a view/screen-space widget. The default factory creates VlcVideoPlayer.
VideoWidget SetBounds(Rectangle bounds)
Moves the composite and resizes its video using existing drawing bounds.
bool Loop
Gets or sets looping.
EventHandler Ended
Forwards end notifications on the player's event thread.
EventHandler Paused
Forwards pause notifications on the player's event thread.
TimeSpan Position
Gets the current media position.
EventHandler Stopped
Forwards stop notifications on the player's event thread.
bool IsMetadataReady
Gets whether metadata is available for this source.
StretchMode Stretch
Gets or sets scaling within the presentation bounds.
bool IsPlaying
Gets the player's current playing state.
void Open(VideoSource source)
Replaces the source and starts playback through DirectVideo.
EventHandler< VideoStateChangedEventArgs > StateChanged
Forwards state/metadata notifications, retaining the player's sender and threading.
EventHandler Started
Forwards playback start notifications on the player's event thread.
void Pause()
Pauses playback without hiding the widget.
void Open(Uri source)
Replaces a URI/file source and starts playback through DirectVideo.
double PlaybackRate
Gets or sets playback speed.
bool IsDragEnabled
Gets or sets whether new drag operations may begin.
DraggableWidgetBase(RenderSurfaceHostBase renderSurfaceHost, DirectDrawingMode mode, PointF anchor=default, string? nickname=null)
Initializes a new instance of the DraggableWidgetBase class.
bool CanReceiveFocus
Gets or sets a value indicating whether the widget can receive keyboard focus.
bool IsKeyboardInputEnabled
Gets or sets a value indicating whether the widget can receive keyboard input.
Defines the contract for a video player that can play, pause, stop, and seek video content.
@ Rectangle
Particles are spawned uniformly within a rectangular area. This is the default distribution.
DirectDrawingMode
Specifies where direct drawing operations are applied within the rendering pipeline.
@ View
Performs direct drawing at the view level using screen-space coordinates.
StretchMode
Defines how video content should be stretched or scaled to fit within its display bounds.
Definition StretchMode.cs:7
record VideoMetadata(VideoMetadataStatus Status, bool HasAudio, TimeSpan Duration)
An immutable metadata snapshot. Values are authoritative only when status is Ready.