示例#1
0
        private unsafe void InitLighting()
        {
            LoadLightingShaders();

            RegenerateLightingRenderTargets();

            // Occlusion VAO.
            // Only handles positions, no other vertex data necessary.
            _occlusionVao = new GLHandle(GL.GenVertexArray());
            GL.BindVertexArray(_occlusionVao.Handle);

            ObjectLabelMaybe(ObjectLabelIdentifier.VertexArray, _occlusionVao, nameof(_occlusionVao));

            _occlusionVbo = new GLBuffer(this, BufferTarget.ArrayBuffer, BufferUsageHint.DynamicDraw,
                                         nameof(_occlusionVbo));

            _occlusionEbo = new GLBuffer(this, BufferTarget.ElementArrayBuffer, BufferUsageHint.DynamicDraw,
                                         nameof(_occlusionEbo));

            GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(Vector3), IntPtr.Zero);
            GL.EnableVertexAttribArray(0);

            // FOV FBO.

            _fovFbo = new GLHandle(GL.GenFramebuffer());

            var boundDrawBuffer = GL.GetInteger(GetPName.DrawFramebufferBinding);
            var boundReadBuffer = GL.GetInteger(GetPName.ReadFramebufferBinding);

            GL.BindFramebuffer(FramebufferTarget.Framebuffer, _fovFbo.Handle);

            _fovDepthTexture = new GLHandle(GL.GenTexture());

            GL.BindTexture(TextureTarget.Texture2D, _fovDepthTexture.Handle);

            _fovDepthTextureObject = _genTexture(_fovDepthTexture, (ShadowMapSize, 1), "FOV depth texture");

            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent, ShadowMapSize, 1, 0,
                          PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero);

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS,
                            (int)OGLTextureWrapMode.Repeat);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT,
                            (int)OGLTextureWrapMode.Repeat);

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter,
                            (int)TextureMagFilter.Nearest);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
                            (int)TextureMinFilter.Nearest);

            GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment,
                                  _fovDepthTexture.Handle, 0);

            GL.DrawBuffer(DrawBufferMode.None);
            GL.ReadBuffer(ReadBufferMode.None);

            var status = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);

            DebugTools.Assert(status == FramebufferErrorCode.FramebufferComplete,
                              $"new framebuffer has bad status {status}");

            GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, boundDrawBuffer);
            GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, boundReadBuffer);
        }
示例#2
0
 /// <inheritdoc />
 public void ClientDisconnect(string reason)
 {
     DebugTools.Assert(IsClient, "Should never be called on the server.");
     Disconnect?.Invoke(this, new NetChannelArgs(ServerChannel));
     Shutdown(reason);
 }
        private static void HandleEntityState(IComponentManager compMan, IEntity entity, EntityState curState,
                                              EntityState nextState)
        {
            var compStateWork = new Dictionary <uint, (ComponentState curState, ComponentState nextState)>();
            var entityUid     = entity.Uid;

            if (curState?.ComponentChanges != null)
            {
                foreach (var compChange in curState.ComponentChanges)
                {
                    if (compChange.Deleted)
                    {
                        if (compMan.TryGetComponent(entityUid, compChange.NetID, out var comp))
                        {
                            compMan.RemoveComponent(entityUid, comp);
                        }
                    }
                    else
                    {
                        if (compMan.HasComponent(entityUid, compChange.NetID))
                        {
                            continue;
                        }

                        var newComp = (Component)IoCManager.Resolve <IComponentFactory>().GetComponent(compChange.ComponentName);
                        newComp.Owner = entity;
                        compMan.AddComponent(entity, newComp, true);
                    }
                }
            }

            if (curState?.ComponentStates != null)
            {
                foreach (var compState in curState.ComponentStates)
                {
                    compStateWork[compState.NetID] = (compState, null);
                }
            }

            if (nextState?.ComponentStates != null)
            {
                foreach (var compState in nextState.ComponentStates)
                {
                    if (compStateWork.TryGetValue(compState.NetID, out var state))
                    {
                        compStateWork[compState.NetID] = (state.curState, compState);
                    }
                    else
                    {
                        compStateWork[compState.NetID] = (null, compState);
                    }
                }
            }

            foreach (var kvStates in compStateWork)
            {
                if (!compMan.TryGetComponent(entityUid, kvStates.Key, out var component))
                {
                    DebugTools.Assert("Component does not exist for state.");
                }

                DebugTools.Assert(kvStates.Value.curState == null ||
                                  kvStates.Value.curState.GetType() == component.StateType,
                                  "Component state is of the wrong type.");

                component.HandleComponentState(kvStates.Value.curState, kvStates.Value.nextState);
            }
        }
示例#4
0
        /// <summary>
        ///     Constructs a new instance of <c>TypeEntityQuery</c>.
        /// </summary>
        /// <param name="componentType">Type of the component to match.</param>
        public TypeEntityQuery(Type componentType)
        {
            DebugTools.Assert(typeof(IComponent).IsAssignableFrom(componentType), "componentType must inherit IComponent");

            ComponentType = componentType;
        }
示例#5
0
        private void HandleEntityState(IComponentManager compMan, IEntity entity, EntityState curState,
                                       EntityState nextState)
        {
            var compStateWork = new Dictionary <uint, (ComponentState curState, ComponentState nextState)>();
            var entityUid     = entity.Uid;

            if (curState?.ComponentChanges != null)
            {
                foreach (var compChange in curState.ComponentChanges)
                {
                    if (compChange.Deleted)
                    {
                        if (compMan.TryGetComponent(entityUid, compChange.NetID, out var comp))
                        {
                            compMan.RemoveComponent(entityUid, comp);
                        }
                    }
                    else
                    {
                        if (compMan.HasComponent(entityUid, compChange.NetID))
                        {
                            continue;
                        }

                        var newComp = (Component)IoCManager.Resolve <IComponentFactory>()
                                      .GetComponent(compChange.ComponentName);
                        newComp.Owner = entity;
                        compMan.AddComponent(entity, newComp, true);
                    }
                }
            }

            if (curState?.ComponentStates != null)
            {
                foreach (var compState in curState.ComponentStates)
                {
                    compStateWork[compState.NetID] = (compState, null);
                }
            }

            if (nextState?.ComponentStates != null)
            {
                foreach (var compState in nextState.ComponentStates)
                {
                    if (compStateWork.TryGetValue(compState.NetID, out var state))
                    {
                        compStateWork[compState.NetID] = (state.curState, compState);
                    }
                    else
                    {
                        compStateWork[compState.NetID] = (null, compState);
                    }
                }
            }

            foreach (var kvStates in compStateWork)
            {
                if (!compMan.TryGetComponent(entityUid, kvStates.Key, out var component))
                {
                    DebugTools.Assert("Component does not exist for state.");
                    continue;
                }

                try
                {
                    component.HandleComponentState(kvStates.Value.curState, kvStates.Value.nextState);
                }
                catch (Exception e)
                {
                    var wrapper = new ComponentStateApplyException(
                        $"Failed to apply comp state: entity={component.Owner}, comp={component.Name}", e);
#if EXCEPTION_TOLERANCE
                    _runtimeLog.LogException(wrapper, "Component state apply");
#else
                    throw wrapper;
#endif
                }
            }
        }
示例#6
0
        public void Update()
        {
            DebugTools.Assert(_impl != null, "WebViewManager has not yet been initialized!");

            _impl !.Update();
        }
示例#7
0
        public IWebViewWindow CreateBrowserWindow(BrowserWindowCreateParameters createParams)
        {
            DebugTools.Assert(_impl != null, "WebViewManager has not yet been initialized!");

            return(_impl !.CreateBrowserWindow(createParams));
        }
示例#8
0
        public override void AlignPlacementMode(ScreenCoordinates mouseScreen)
        {
            const float SearchBoxSize = 1.5f; // size of search box in meters

            MouseCoords = ScreenToCursorGrid(mouseScreen);

            var mapGrid = pManager.MapManager.GetGrid(MouseCoords.GridID);

            if (mapGrid.IsDefaultGrid)
            {
                // check if we are on an edge of a grid
                // create a box around the cursor
                DebugTools.Assert(mapGrid.WorldPosition == Vector2.Zero); // assert that LocalPos == WorldPos
                var gridSearchBox = Box2.UnitCentered.Scale(SearchBoxSize).Translated(MouseCoords.Position);

                // find grids in search box
                var gridsInArea = pManager.MapManager.FindGridsIntersecting(mapGrid.ParentMapId, gridSearchBox);

                // find closest grid intersecting our search box.
                IMapGrid closest   = null;
                var      distance  = float.PositiveInfinity;
                var      intersect = new Box2();
                foreach (var grid in gridsInArea)
                {
                    // figure out closest intersect
                    var gridIntersect = gridSearchBox.Intersect(grid.WorldBounds);
                    var gridDist      = (gridIntersect.Center - MouseCoords.Position).LengthSquared;

                    if (gridDist >= distance)
                    {
                        continue;
                    }

                    distance  = gridDist;
                    closest   = grid;
                    intersect = gridIntersect;
                }

                if (closest != null) // stick to existing grid
                {
                    // round to nearest cardinal dir
                    var normal = new Angle(MouseCoords.Position - intersect.Center).GetCardinalDir().ToVec();

                    // round coords to center of tile
                    var tileIndices     = closest.WorldToTile(intersect.Center);
                    var tileCenterWorld = closest.GridTileToWorldPos(tileIndices);

                    // move mouse one tile out along normal
                    var newTilePos = tileCenterWorld + normal * closest.TileSize;
                    MouseCoords = new GridCoordinates(closest.WorldToLocal(newTilePos), closest.Index);
                }
                //else free place
            }


            CurrentTile = mapGrid.GetTileRef(MouseCoords);
            float tileSize = mapGrid.TileSize; //convert from ushort to float

            GridDistancing = tileSize;

            if (pManager.CurrentPermission.IsTile)
            {
                if (!mapGrid.IsDefaultGrid)
                {
                    MouseCoords = new GridCoordinates(CurrentTile.X + tileSize / 2,
                                                      CurrentTile.Y + tileSize / 2,
                                                      MouseCoords.GridID);
                }
                // else we don't modify coords
            }
            else
            {
                MouseCoords = new GridCoordinates(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
                                                  CurrentTile.Y + tileSize / 2 + pManager.PlacementOffset.Y,
                                                  MouseCoords.GridID);
            }
        }
示例#9
0
            public void Use()
            {
                DebugTools.Assert(Handle != -1);

                GL.BindBuffer(Type, Handle);
            }
示例#10
0
 public void ClientDisconnect(string reason)
 {
     DebugTools.Assert(IsClient);
     Disconnect?.Invoke(this, new NetChannelArgs(ServerChannel));
     Shutdown(reason);
 }
示例#11
0
            public void ProcessPackets()
            {
                while (_messageChannel.Reader.TryRead(out var item))
                {
                    switch (item)
                    {
                    case ConnectMessage connect:
                    {
                        DebugTools.Assert(IsServer);

                        var writer = connect.ChannelWriter;

                        var uid       = _genConnectionUid();
                        var sessionId = new NetSessionId($"integration_{uid}");

                        var connectArgs =
                            new NetConnectingArgs(sessionId, new IPEndPoint(IPAddress.IPv6Loopback, 0));
                        Connecting?.Invoke(this, connectArgs);
                        if (connectArgs.Deny)
                        {
                            writer.TryWrite(new DeniedConnectMessage());
                            continue;
                        }

                        writer.TryWrite(new ConfirmConnectMessage(uid, sessionId));
                        var channel = new IntegrationNetChannel(this, connect.ChannelWriter, uid, sessionId);
                        _channels.Add(uid, channel);
                        Connected?.Invoke(this, new NetChannelArgs(channel));
                        break;
                    }

                    case DataMessage data:
                    {
                        IntegrationNetChannel channel;
                        if (IsServer)
                        {
                            if (!_channels.TryGetValue(data.Connection, out channel))
                            {
                                continue;
                            }
                        }
                        else
                        {
                            channel = ServerChannel;
                        }

                        var message = data.Message;
                        message.MsgChannel = channel;
                        if (_callbacks.TryGetValue(message.GetType(), out var callback))
                        {
                            callback(message);
                        }

                        break;
                    }

                    case DisconnectMessage disconnect:
                    {
                        if (IsServer)
                        {
                            if (_channels.TryGetValue(disconnect.Connection, out var channel))
                            {
                                Disconnect?.Invoke(this, new NetChannelArgs(channel));

                                _channels.Remove(disconnect.Connection);
                            }
                        }
                        else
                        {
                            _channels.Clear();
                        }

                        break;
                    }

                    case DeniedConnectMessage _:
                    {
                        DebugTools.Assert(IsClient);

                        ConnectFailed?.Invoke(this, new NetConnectFailArgs("I didn't implement a deny reason!"));
                        break;
                    }

                    case ConfirmConnectMessage confirm:
                    {
                        DebugTools.Assert(IsClient);

                        var channel = new IntegrationNetChannel(this, NextConnectChannel, _genConnectionUid(),
                                                                confirm.SessionId, confirm.AssignedUid);

                        _channels.Add(channel.ConnectionUid, channel);

                        Connected?.Invoke(this, new NetChannelArgs(channel));
                        break;
                    }

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
            }
示例#12
0
        public Texture LoadTextureFromImage <T>(Image <T> image, string?name     = null,
                                                TextureLoadParameters?loadParams = null) where T : unmanaged, IPixel <T>
        {
            DebugTools.Assert(_mainThread == Thread.CurrentThread);

            var actualParams = loadParams ?? TextureLoadParameters.Default;
            var pixelType    = typeof(T);

            if (!_hasGLTextureSwizzle)
            {
                // If texture swizzle isn't available we have to pre-process the images to apply it ourselves
                // and then upload as RGBA8.
                // Yes this is inefficient but the alternative is modifying the shaders,
                // which I CBA to do.
                // Even 8 year old iGPUs support texture swizzle.
                if (pixelType == typeof(A8))
                {
                    // Disable sRGB so stuff doesn't get interpreter wrong.
                    actualParams.Srgb = false;
                    var img = ApplyA8Swizzle((Image <A8>)(object) image);
                    return(LoadTextureFromImage(img, name, loadParams));
                }

                if (pixelType == typeof(L8) && !actualParams.Srgb)
                {
                    var img = ApplyL8Swizzle((Image <L8>)(object) image);
                    return(LoadTextureFromImage(img, name, loadParams));
                }
            }

            // Flip image because OpenGL reads images upside down.
            var copy = FlipClone(image);

            var texture = new GLHandle((uint)GL.GenTexture());

            CheckGlError();
            GL.BindTexture(TextureTarget.Texture2D, texture.Handle);
            CheckGlError();
            ApplySampleParameters(actualParams.SampleParameters);

            PixelInternalFormat internalFormat;
            PixelFormat         pixelDataFormat;
            PixelType           pixelDataType;
            bool isActuallySrgb = false;

            if (pixelType == typeof(Rgba32))
            {
                // Note that if _hasGLSrgb is off, we import an sRGB texture as non-sRGB.
                // Shaders are expected to compensate for this
                internalFormat  = (actualParams.Srgb && _hasGLSrgb) ? PixelInternalFormat.Srgb8Alpha8 : PixelInternalFormat.Rgba8;
                isActuallySrgb  = actualParams.Srgb;
                pixelDataFormat = PixelFormat.Rgba;
                pixelDataType   = PixelType.UnsignedByte;
            }
            else if (pixelType == typeof(A8))
            {
                if (image.Width % 4 != 0 || image.Height % 4 != 0)
                {
                    throw new ArgumentException("Alpha8 images must have multiple of 4 sizes.");
                }

                internalFormat  = PixelInternalFormat.R8;
                pixelDataFormat = PixelFormat.Red;
                pixelDataType   = PixelType.UnsignedByte;

                unsafe
                {
                    // TODO: Does it make sense to default to 1 for RGB parameters?
                    // It might make more sense to pass some options to change swizzling.
                    var swizzle = stackalloc[] { (int)All.One, (int)All.One, (int)All.One, (int)All.Red };
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, swizzle);
                }
            }
            else if (pixelType == typeof(L8) && !actualParams.Srgb)
            {
                // Can only use R8 for L8 if sRGB is OFF.
                // Because OpenGL doesn't provide sRGB single/dual channel image formats.
                // Vulkan when?
                if (copy.Width % 4 != 0 || copy.Height % 4 != 0)
                {
                    throw new ArgumentException("L8 non-sRGB images must have multiple of 4 sizes.");
                }

                internalFormat  = PixelInternalFormat.R8;
                pixelDataFormat = PixelFormat.Red;
                pixelDataType   = PixelType.UnsignedByte;

                unsafe
                {
                    var swizzle = stackalloc[] { (int)All.Red, (int)All.Red, (int)All.Red, (int)All.One };
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, swizzle);
                }
            }
            else
            {
                throw new NotImplementedException($"Unable to handle pixel type '{pixelType.Name}'");
            }

            unsafe
            {
                var span = copy.GetPixelSpan();
                fixed(T *ptr = span)
                {
                    GL.TexImage2D(TextureTarget.Texture2D, 0, internalFormat, copy.Width, copy.Height, 0,
                                  pixelDataFormat, pixelDataType, (IntPtr)ptr);
                    CheckGlError();
                }
            }

            var pressureEst = EstPixelSize(internalFormat) * copy.Width * copy.Height;

            return(GenTexture(texture, (copy.Width, copy.Height), isActuallySrgb, name, pressureEst));
        }
示例#13
0
 private void OnConnectFailed(object?sender, NetConnectFailArgs args)
 {
     DebugTools.Assert(RunLevel == ClientRunLevel.Connecting);
     Reset();
 }
示例#14
0
 /// <inheritdoc />
 public void StopSinglePlayer()
 {
     DebugTools.Assert(RunLevel == ClientRunLevel.SinglePlayerGame);
     DebugTools.Assert(!_net.IsConnected);
     GameStoppedReset();
 }
示例#15
0
        private RenderTarget CreateRenderTarget(Vector2i size, RenderTargetFormatParameters format,
                                                TextureSampleParameters?sampleParameters = null, string?name = null)
        {
            // Cache currently bound framebuffers
            // so if somebody creates a framebuffer while drawing it won't ruin everything.
            var boundDrawBuffer = GL.GetInteger(GetPName.DrawFramebufferBinding);
            var boundReadBuffer = GL.GetInteger(GetPName.ReadFramebufferBinding);

            // Generate FBO.
            var fbo = new GLHandle(GL.GenFramebuffer());

            // Bind color attachment to FBO.
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbo.Handle);

            ObjectLabelMaybe(ObjectLabelIdentifier.Framebuffer, fbo, name);

            var(width, height) = size;

            ClydeTexture textureObject;
            GLHandle     depthStencilBuffer = default;

            // Color attachment.
            {
                var texture = new GLHandle(GL.GenTexture());

                GL.BindTexture(TextureTarget.Texture2D, texture.Handle);

                ApplySampleParameters(sampleParameters);

                var internalFormat = format.ColorFormat switch
                {
                    RenderTargetColorFormat.Rgba8 => PixelInternalFormat.Rgba8,
                    RenderTargetColorFormat.Rgba16F => PixelInternalFormat.Rgba16f,
                    RenderTargetColorFormat.Rgba8Srgb => PixelInternalFormat.Srgb8Alpha8,
                    RenderTargetColorFormat.R11FG11FB10F => PixelInternalFormat.R11fG11fB10f,
                    RenderTargetColorFormat.R32F => PixelInternalFormat.R32f,
                    RenderTargetColorFormat.RG32F => PixelInternalFormat.Rg32f,
                    RenderTargetColorFormat.R8 => PixelInternalFormat.R8,
                    _ => throw new ArgumentOutOfRangeException(nameof(format.ColorFormat), format.ColorFormat, null)
                };

                GL.TexImage2D(TextureTarget.Texture2D, 0, internalFormat, width, height, 0, PixelFormat.Red,
                              PixelType.Byte, IntPtr.Zero);

                GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0,
                                      texture.Handle,
                                      0);

                textureObject = GenTexture(texture, size, name == null ? null : $"{name}-color");
            }

            // Depth/stencil buffers.
            if (format.HasDepthStencil)
            {
                depthStencilBuffer = new GLHandle(GL.GenRenderbuffer());
                GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, depthStencilBuffer.Handle);

                ObjectLabelMaybe(ObjectLabelIdentifier.Renderbuffer, depthStencilBuffer,
                                 name == null ? null : $"{name}-depth-stencil");

                GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.Depth24Stencil8, width,
                                       height);

                GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment,
                                           RenderbufferTarget.Renderbuffer, depthStencilBuffer.Handle);
            }

            // This should always pass but OpenGL makes it easy to check for once so let's.
            var status = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);

            DebugTools.Assert(status == FramebufferErrorCode.FramebufferComplete,
                              $"new framebuffer has bad status {status}");

            // Re-bind previous framebuffers.
            GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, boundDrawBuffer);
            GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, boundReadBuffer);

            var handle       = AllocRid();
            var renderTarget = new RenderTarget(size, textureObject, fbo, this, handle, depthStencilBuffer);

            _renderTargets.Add(handle, renderTarget);
            return(renderTarget);
        }
示例#16
0
        public Texture LoadTextureFromImage <T>(Image <T> image, string name     = null,
                                                TextureLoadParameters?loadParams = null) where T : unmanaged, IPixel <T>
        {
            DebugTools.Assert(_mainThread == Thread.CurrentThread);

            var actualParams = loadParams ?? TextureLoadParameters.Default;
            var pixelType    = typeof(T);

            var texture = new OGLHandle((uint)GL.GenTexture());

            GL.BindTexture(TextureTarget.Texture2D, texture.Handle);
            _applySampleParameters(actualParams.SampleParameters);

            PixelInternalFormat internalFormat;
            PixelFormat         pixelDataFormat;
            PixelType           pixelDataType;

            if (pixelType == typeof(Rgba32))
            {
                internalFormat  = actualParams.Srgb ? PixelInternalFormat.Srgb8Alpha8 : PixelInternalFormat.Rgba8;
                pixelDataFormat = PixelFormat.Rgba;
                pixelDataType   = PixelType.UnsignedByte;
            }
            else if (pixelType == typeof(Alpha8))
            {
                if (image.Width % 4 != 0 || image.Height % 4 != 0)
                {
                    throw new ArgumentException("Alpha8 images must have multiple of 4 sizes.");
                }
                internalFormat  = PixelInternalFormat.R8;
                pixelDataFormat = PixelFormat.Red;
                pixelDataType   = PixelType.UnsignedByte;

                // TODO: Does it make sense to default to 1 for RGB parameters?
                // It might make more sense to pass some options to change swizzling.
                var swizzle = new[] { (int)All.One, (int)All.One, (int)All.One, (int)All.Red };
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, swizzle);
            }
            else if (pixelType == typeof(Gray8) && !actualParams.Srgb)
            {
                // Can only use R8 for Gray8 if sRGB is OFF.
                // Because OpenGL doesn't provide non-sRGB single/dual channel image formats.
                // Vulkan when?
                if (image.Width % 4 != 0 || image.Height % 4 != 0)
                {
                    throw new ArgumentException("Gray8 non-sRGB images must have multiple of 4 sizes.");
                }

                internalFormat  = PixelInternalFormat.R8;
                pixelDataFormat = PixelFormat.Red;
                pixelDataType   = PixelType.UnsignedByte;

                var swizzle = new[] { (int)All.Red, (int)All.Red, (int)All.Red, (int)All.One };
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, swizzle);
            }
            else
            {
                throw new NotImplementedException($"Unable to handle pixel type '{pixelType.Name}'");
            }

            unsafe
            {
                var span = image.GetPixelSpan();
                fixed(T *ptr = span)
                {
                    GL.TexImage2D(TextureTarget.Texture2D, 0, internalFormat, image.Width, image.Height, 0,
                                  pixelDataFormat, pixelDataType, (IntPtr)ptr);
                }
            }

            return(_genTexture(texture, (image.Width, image.Height), name));
        }
示例#17
0
        private DockingComponent?GetDockable(PhysicsComponent body, TransformComponent dockingXform)
        {
            // Did you know Saltern is the most dockable station?

            // Assume the docking port itself (and its body) is valid

            if (!_mapManager.TryGetGrid(dockingXform.GridID, out var grid) ||
                !EntityManager.HasComponent <ShuttleComponent>(grid.GridEntityId))
            {
                return(null);
            }

            var transform      = body.GetTransform();
            var dockingFixture = _fixtureSystem.GetFixtureOrNull(body, DockingFixture);

            if (dockingFixture == null)
            {
                DebugTools.Assert(false);
                Logger.ErrorS("docking", $"Found null fixture on {(body).Owner}");
                return(null);
            }

            Box2?aabb = null;

            for (var i = 0; i < dockingFixture.Shape.ChildCount; i++)
            {
                aabb = aabb?.Union(dockingFixture.Shape.ComputeAABB(transform, i)) ?? dockingFixture.Shape.ComputeAABB(transform, i);
            }

            if (aabb == null)
            {
                return(null);
            }

            var enlargedAABB = aabb.Value.Enlarged(DockingRadius * 1.5f);

            // Get any docking ports in range on other grids.
            _mapManager.FindGridsIntersectingEnumerator(dockingXform.MapID, enlargedAABB, out var enumerator);

            while (enumerator.MoveNext(out var otherGrid))
            {
                if (otherGrid.Index == dockingXform.GridID)
                {
                    continue;
                }

                foreach (var ent in otherGrid.GetAnchoredEntities(enlargedAABB))
                {
                    if (!EntityManager.TryGetComponent(ent, out DockingComponent? otherDocking) ||
                        !otherDocking.Enabled ||
                        !EntityManager.TryGetComponent(ent, out PhysicsComponent? otherBody))
                    {
                        continue;
                    }

                    var otherTransform      = otherBody.GetTransform();
                    var otherDockingFixture = _fixtureSystem.GetFixtureOrNull(otherBody, DockingFixture);

                    if (otherDockingFixture == null)
                    {
                        DebugTools.Assert(false);
                        Logger.ErrorS("docking", $"Found null docking fixture on {ent}");
                        continue;
                    }

                    for (var i = 0; i < otherDockingFixture.Shape.ChildCount; i++)
                    {
                        var otherAABB = otherDockingFixture.Shape.ComputeAABB(otherTransform, i);

                        if (!aabb.Value.Intersects(otherAABB))
                        {
                            continue;
                        }

                        // TODO: Need CollisionManager's GJK for accurate bounds
                        // Realistically I want 2 fixtures anyway but I'll deal with that later.
                        return(otherDocking);
                    }
                }
            }

            return(null);
        }
示例#18
0
 /// <summary>
 ///     Constructs a new instance of the given type, and return it cast to the specified type.
 /// </summary>
 /// <param name="dynamicTypeFactory">The dynamic type factory to use.</param>
 /// <param name="type">The type to instantiate.</param>
 /// <param name="args">The arguments to pass to the constructor.</param>
 /// <typeparam name="T">The type that the instance will be cast to.</typeparam>
 /// <returns>Newly created object, cast to <typeparamref name="T"/>.</returns>
 public static T CreateInstance <T>(this IDynamicTypeFactory dynamicTypeFactory, Type type, object[] args)
 {
     DebugTools.Assert(typeof(T).IsAssignableFrom(type), "type must be subtype of T");
     return((T)dynamicTypeFactory.CreateInstance(type, args));
 }
示例#19
0
        public void Shutdown()
        {
            DebugTools.Assert(_impl != null, "WebViewManager has not yet been initialized!");

            _impl !.Shutdown();
        }
        public VVPropEditor SetProperty(ViewVariablesBlobMembers.MemberData member)
        {
            NameLabel.Text = member.Name;
            var type = Type.GetType(member.Type);

            _bottomLabel.Text = $"Type: {member.TypePretty}";
            VVPropEditor editor;

            if (type == null || !_robustSerializer.CanSerialize(type))
            {
                // Type is server-side only.
                // Info whether it's reference or value type can be figured out from the sent value.
                if (type?.IsValueType == true || member.Value is ViewVariablesBlobMembers.ServerValueTypeToken)
                {
                    // Value type, just display it stringified read-only.
                    editor = new VVPropEditorDummy();
                }
                else
                {
                    // Has to be a reference type at this point.
                    DebugTools.Assert(member.Value is ViewVariablesBlobMembers.ReferenceToken || member.Value == null || type?.IsClass == true || type?.IsInterface == true);
                    editor = _viewVariablesManager.PropertyFor(type ?? typeof(object));
                }
            }
            else
            {
                editor = _viewVariablesManager.PropertyFor(type);
            }

            var view = editor.Initialize(member.Value, !member.Editable);

            if (!view.HorizontalExpand)
            {
                NameLabel.HorizontalExpand = true;
            }

            NameLabel.MinSize = new Vector2(150, 0);
            TopContainer.AddChild(view);

            /*
             * _beingEdited = obj;
             * _editedProperty = propertyInfo;
             * DebugTools.Assert(propertyInfo.DeclaringType != null);
             * DebugTools.Assert(propertyInfo.DeclaringType.IsInstanceOfType(obj));
             *
             * DebugTools.Assert(ViewVariablesUtility.TryGetViewVariablesAccess(fieldInfo, out var access));
             * NameLabel.Text = propertyInfo.Name;
             *
             * _bottomLabel.Text = $"Type: {propertyInfo.PropertyType.FullName}";
             *
             * var editor = vvm.PropertyFor(propertyInfo.PropertyType);
             * var value = propertyInfo.GetValue(obj);
             *
             * var view = editor.Initialize(value, access != VVAccess.ReadWrite);
             * if (view.SizeFlagsHorizontal != SizeFlags.FillExpand)
             * {
             *  NameLabel.HorizontalExpand = true;
             * }
             * NameLabel.MinSize = new Vector2(150, 0);
             * TopContainer.AddChild(view);
             * editor.OnValueChanged += v => { propertyInfo.SetValue(obj, v); };
             */
            return(editor);
        }
示例#21
0
        public IWebViewControlImpl MakeControlImpl(WebViewControl owner)
        {
            DebugTools.Assert(_impl != null, "WebViewManager has not yet been initialized!");

            return(_impl !.MakeControlImpl(owner));
        }
 private void ExcitedGroupResetCooldowns(ExcitedGroup excitedGroup)
 {
     DebugTools.Assert(!excitedGroup.Disposed, "Excited group is disposed!");
     excitedGroup.BreakdownCooldown = 0;
     excitedGroup.DismantleCooldown = 0;
 }
        private void ProcessGraphUpdates()
        {
            var totalUpdates = 0;

            foreach (var update in _collidableUpdateQueue)
            {
                var entity = EntityManager.GetEntity(update.Owner);
                if (update.CanCollide)
                {
                    HandleEntityAdd(entity);
                }
                else
                {
                    HandleEntityRemove(entity);
                }

                totalUpdates++;
            }

            _collidableUpdateQueue.Clear();

            foreach (var update in _accessReaderUpdateQueue)
            {
                if (update.Enabled)
                {
                    HandleEntityAdd(update.Sender);
                }
                else
                {
                    HandleEntityRemove(update.Sender);
                }

                totalUpdates++;
            }

            _accessReaderUpdateQueue.Clear();

            foreach (var tile in _tileUpdateQueue)
            {
                HandleTileUpdate(tile);
                totalUpdates++;
            }

            _tileUpdateQueue.Clear();
            var moveUpdateCount = Math.Max(50 - totalUpdates, 0);

            // Other updates are high priority so for this we'll just defer it if there's a spike (explosion, etc.)
            // If the move updates grow too large then we'll just do it
            if (_moveUpdateQueue.Count > 100)
            {
                moveUpdateCount = _moveUpdateQueue.Count - 100;
            }

            moveUpdateCount = Math.Min(moveUpdateCount, _moveUpdateQueue.Count);

            for (var i = 0; i < moveUpdateCount; i++)
            {
                HandleEntityMove(_moveUpdateQueue.Dequeue());
            }

            DebugTools.Assert(_moveUpdateQueue.Count < 1000);
        }
        /// <inheritdoc />
        public void AddComponent <T>(IEntity entity, T component, bool overwrite = false) where T : Component
        {
            if (entity == null || !entity.IsValid())
            {
                throw new ArgumentException("Entity is not valid.", nameof(entity));
            }

            if (component == null)
            {
                throw new ArgumentNullException(nameof(component));
            }

            if (component.Owner != entity)
            {
                throw new InvalidOperationException("Component is not owned by entity.");
            }

            var uid = entity.Uid;

            // get interface aliases for mapping
            var reg = _componentFactory.GetRegistration(component);

            // Check that there are no overlapping references.
            foreach (var type in reg.References)
            {
                if (!TryGetComponent(uid, type, out var duplicate))
                {
                    continue;
                }

                if (!overwrite)
                {
                    throw new InvalidOperationException(
                              $"Component reference type {type} already occupied by {duplicate}");
                }

                // these two components are required on all entities and cannot be overwritten.
                if (duplicate is ITransformComponent || duplicate is IMetaDataComponent)
                {
                    throw new InvalidOperationException("Tried to overwrite a protected component.");
                }

                RemoveComponentImmediate((Component)duplicate);
            }

            // add the component to the grid
            foreach (var type in reg.References)
            {
                _entTraitDict[type].Add(uid, component);
                _entCompIndex.Add(uid, component);
            }

            // add the component to the netId grid
            if (component.NetID != null)
            {
                // the main comp grid keeps this in sync

                var netId = component.NetID.Value;
                _entNetIdDict[netId].Add(uid, component);

                // mark the component as dirty for networking
                component.Dirty();

                ComponentAdded?.Invoke(this, new AddedComponentEventArgs(component));
            }

            component.ExposeData(DefaultValueSerializer.Reader());

            component.OnAdd();

            if (!entity.Initialized && !entity.Initializing)
            {
                return;
            }

            component.Initialize();

            DebugTools.Assert(component.Initialized, "Component is not initialized after calling Initialize(). "
                              + "Did you forget to call base.Initialize() in an override?");

            if (entity.Initialized)
            {
                component.Running = true;
            }
        }
        private static void HandleEntityState(IComponentManager compMan, IEntity entity, EntityState curState,
                                              EntityState nextState)
        {
            var compStateWork = new Dictionary <uint, (ComponentState curState, ComponentState nextState)>();
            var entityUid     = entity.Uid;

            if (curState?.ComponentChanges != null)
            {
                foreach (var compChange in curState.ComponentChanges)
                {
                    if (compChange.Deleted)
                    {
                        if (compMan.TryGetComponent(entityUid, compChange.NetID, out var comp))
                        {
                            compMan.RemoveComponent(entityUid, comp);
                        }
                    }
                    else
                    {
                        if (compMan.HasComponent(entityUid, compChange.NetID))
                        {
                            continue;
                        }

                        var newComp = (Component)IoCManager.Resolve <IComponentFactory>().GetComponent(compChange.ComponentName);
                        newComp.Owner = entity;
                        compMan.AddComponent(entity, newComp, true);
                    }
                }
            }

            if (curState?.ComponentStates != null)
            {
                foreach (var compState in curState.ComponentStates)
                {
                    compStateWork[compState.NetID] = (compState, null);
                }
            }

            if (nextState?.ComponentStates != null)
            {
                foreach (var compState in nextState.ComponentStates)
                {
                    if (compStateWork.TryGetValue(compState.NetID, out var state))
                    {
                        compStateWork[compState.NetID] = (state.curState, compState);
                    }
                    else
                    {
                        compStateWork[compState.NetID] = (null, compState);
                    }
                }
            }

            foreach (var kvStates in compStateWork)
            {
                if (!compMan.TryGetComponent(entityUid, kvStates.Key, out var component))
                {
                    DebugTools.Assert("Component does not exist for state.");
                    continue;
                }

                try
                {
                    component.HandleComponentState(kvStates.Value.curState, kvStates.Value.nextState);
                }
                catch (Exception e)
                {
                    Logger.ErrorS("entity", $"Failed to apply comp state: entity={component.Owner}, comp={component.Name}\n  {e}");
                    DebugTools.Assert(e.Message);
                }
            }
        }
        private async Task _moveToPage(int page)
        {
            // TODO: Network overhead optimization potential:
            // Right now, (in NETWORK mode) if I request page 5, it has to cache all 5 pages,
            // now the server obviously (enumerator and all that) has to TOO, but whatever.
            // The waste is that all pages are also SENT, even though we only really care about the fifth at the moment.
            // Because the cache can't have holes (and also the network system is too simplistic at the moment,
            // if you do do a by-page pull and you're way too far along,
            // you'll just get 0 elements which doesn't tell you where it ended but that's kinda necessary.
            if (page < 0)
            {
                page = 0;
            }

            if (page > HighestKnownPage || (!_ended && page == HighestKnownPage))
            {
                if (_ended)
                {
                    // The requested page is higher than the highest page we have (and we know this because the enumerator ended).
                    page = HighestKnownPage;
                }
                else
                {
                    // The page is higher than the highest page we have, but the enumerator hasn't ended yet so that might be valid.
                    // Gotta get more data.
                    await _cacheTo((page + 1) *ElementsPerPage);

                    if (page > HighestKnownPage)
                    {
                        // We tried, but the enumerator ended before we reached our goal.
                        // Oh well.
                        DebugTools.Assert(_ended);
                        page = HighestKnownPage;
                    }
                }
            }

            _elementsVBox.DisposeAllChildren();

            for (var i = page * ElementsPerPage; i < ElementsPerPage * (page + 1) && i < _cache.Count; i++)
            {
                var element = _cache[i];
                ViewVariablesPropertyEditor editor;
                if (element == null)
                {
                    editor = new ViewVariablesPropertyEditorDummy();
                }
                else
                {
                    var type = element.GetType();
                    editor = Instance.ViewVariablesManager.PropertyFor(type);
                }

                var control = editor.Initialize(element, true);
                if (editor is ViewVariablesPropertyEditorReference refEditor)
                {
                    if (_networked)
                    {
                        var iSafe = i;
                        refEditor.OnPressed += () =>
                                               Instance.ViewVariablesManager.OpenVV(
                            new ViewVariablesSessionRelativeSelector(Instance.Session !.SessionId,
                                                                     new object[] { new ViewVariablesEnumerableIndexSelector(iSafe), }));
                    }
                    else
                    {
                        refEditor.OnPressed += () => Instance.ViewVariablesManager.OpenVV(element !);
                    }
                }
                _elementsVBox.AddChild(control);
            }

            _page = page;

            _updateControls();
        }
示例#27
0
 /// <inheritdoc />
 public virtual bool CanRemove(IEntity toremove)
 {
     DebugTools.Assert(!Deleted);
     return(Contains(toremove));
 }
        /// <summary>
        /// Docks 2 ports together and assumes it is valid.
        /// </summary>
        public void Dock(DockingComponent dockA, DockingComponent dockB)
        {
            if (dockB.Owner.GetHashCode() < dockA.Owner.GetHashCode())
            {
                (dockA, dockB) = (dockB, dockA);
            }

            _sawmill.Debug($"Docking between {dockA.Owner} and {dockB.Owner}");

            // https://gamedev.stackexchange.com/questions/98772/b2distancejoint-with-frequency-equal-to-0-vs-b2weldjoint

            // We could also potentially use a prismatic joint? Depending if we want clamps that can extend or whatever
            var dockAXform = EntityManager.GetComponent <TransformComponent>(dockA.Owner);
            var dockBXform = EntityManager.GetComponent <TransformComponent>(dockB.Owner);

            DebugTools.Assert(dockAXform.GridUid != null);
            DebugTools.Assert(dockBXform.GridUid != null);
            var gridA = dockAXform.GridUid !.Value;
            var gridB = dockBXform.GridUid !.Value;

            SharedJointSystem.LinearStiffness(
                2f,
                0.7f,
                EntityManager.GetComponent <PhysicsComponent>(gridA).Mass,
                EntityManager.GetComponent <PhysicsComponent>(gridB).Mass,
                out var stiffness,
                out var damping);

            // These need playing around with
            // Could also potentially have collideconnected false and stiffness 0 but it was a bit more suss???
            WeldJoint joint;

            // Pre-existing joint so use that.
            if (dockA.DockJointId != null)
            {
                DebugTools.Assert(dockB.DockJointId == dockA.DockJointId);
                joint = _jointSystem.GetOrCreateWeldJoint(gridA, gridB, dockA.DockJointId);
            }
            else
            {
                joint = _jointSystem.GetOrCreateWeldJoint(gridA, gridB, DockingJoint + dockA.Owner);
            }

            var gridAXform = EntityManager.GetComponent <TransformComponent>(gridA);
            var gridBXform = EntityManager.GetComponent <TransformComponent>(gridB);

            var anchorA = dockAXform.LocalPosition + dockAXform.LocalRotation.ToWorldVec() / 2f;
            var anchorB = dockBXform.LocalPosition + dockBXform.LocalRotation.ToWorldVec() / 2f;

            joint.LocalAnchorA     = anchorA;
            joint.LocalAnchorB     = anchorB;
            joint.ReferenceAngle   = (float)(gridBXform.WorldRotation - gridAXform.WorldRotation);
            joint.CollideConnected = true;
            joint.Stiffness        = stiffness;
            joint.Damping          = damping;

            dockA.DockedWith = dockB.Owner;
            dockB.DockedWith = dockA.Owner;

            dockA.DockJoint   = joint;
            dockA.DockJointId = joint.ID;

            dockB.DockJoint   = joint;
            dockB.DockJointId = joint.ID;

            if (TryComp <AirlockComponent>(dockA.Owner, out var airlockA))
            {
                airlockA.SetBoltsWithAudio(true);
            }

            if (TryComp <AirlockComponent>(dockB.Owner, out var airlockB))
            {
                airlockB.SetBoltsWithAudio(true);
            }

            if (TryComp(dockA.Owner, out DoorComponent? doorA))
            {
                doorA.ChangeAirtight = false;
                _doorSystem.StartOpening(doorA.Owner, doorA);
            }

            if (TryComp(dockB.Owner, out DoorComponent? doorB))
            {
                doorB.ChangeAirtight = false;
                _doorSystem.StartOpening(doorB.Owner, doorB);
            }

            var msg = new DockEvent
            {
                DockA    = dockA,
                DockB    = dockB,
                GridAUid = gridA,
                GridBUid = gridB,
            };

            EntityManager.EventBus.RaiseLocalEvent(dockA.Owner, msg, false);
            EntityManager.EventBus.RaiseLocalEvent(dockB.Owner, msg, false);
            EntityManager.EventBus.RaiseEvent(EventSource.Local, msg);
        }
示例#29
0
        /// <inheritdoc />
        public void ForceRemove(IEntity toRemove)
        {
            DebugTools.Assert(!Deleted);

            InternalRemove(toRemove);
        }
示例#30
0
        private static IRsiStateLike TextureForConfig(ObjectSerializer serializer, IResourceCache resourceCache)
        {
            DebugTools.Assert(serializer.Reading);

            if (serializer.TryGetCacheData <IRsiStateLike>(SerializationCache, out var dirTex))
            {
                return(dirTex);
            }

            var tex = serializer.ReadDataField <string?>("texture", null);

            if (!string.IsNullOrWhiteSpace(tex))
            {
                dirTex = resourceCache.GetResource <TextureResource>(SpriteComponent.TextureRoot / tex).Texture;
                serializer.SetCacheData(SerializationCache, dirTex);
                return(dirTex);
            }

            RSI rsi;

            var rsiPath = serializer.ReadDataField <string?>("sprite", null);

            if (string.IsNullOrWhiteSpace(rsiPath))
            {
                dirTex = resourceCache.GetFallback <TextureResource>().Texture;
                serializer.SetCacheData(SerializationCache, dirTex);
                return(dirTex);
            }

            var path = SpriteComponent.TextureRoot / rsiPath;

            try
            {
                rsi = resourceCache.GetResource <RSIResource>(path).RSI;
            }
            catch
            {
                dirTex = resourceCache.GetFallback <TextureResource>().Texture;
                serializer.SetCacheData(SerializationCache, dirTex);
                return(dirTex);
            }

            var stateId = serializer.ReadDataField <string?>("state", null);

            if (string.IsNullOrWhiteSpace(stateId))
            {
                Logger.ErrorS(LogCategory, "No state specified.");
                dirTex = resourceCache.GetFallback <TextureResource>().Texture;
                serializer.SetCacheData(SerializationCache, dirTex);
                return(dirTex);
            }

            if (rsi.TryGetState(stateId, out var state))
            {
                serializer.SetCacheData(SerializationCache, state);
                return(state);
            }
            else
            {
                Logger.ErrorS(LogCategory, "State '{0}' does not exist on RSI.", stateId);
                return(resourceCache.GetFallback <TextureResource>().Texture);
            }
        }