//****************************************

        internal WinChildController(GuiChildPresenter presenter, GuiViewController parent, UserControl control) : base(presenter)
        {
            if (parent is IWinController)
            {
                ((IWinController)parent).Attach(this);
            }
            else
            {
                throw new ArgumentException("Not a WinForms controller");
            }

            //****************************************

            _UserControl = control;
            _Provider    = ((WinToolkit)GuiService.Toolkit).GetProvider(presenter.Host);
            _ViewDef     = _Provider.GetViewDef(this.Name);

            //****************************************

            _UserControl.Enter += OnGotFocus;
            if (_UserControl.IsHandleCreated)
            {
                OnLoad(_UserControl, EventArgs.Empty);
            }
            else
            {
                _UserControl.HandleCreated += OnLoad;
            }

            _UserControl.Leave += OnLostFocus;
        }
        internal WinChildController(GuiChildPresenter presenter, GuiViewController parent, Type targetType) : base(presenter)
        {               //****************************************
            Control        ParentControl;
            IWinController ParentController = parent as IWinController;

            //****************************************

            if (ParentController == null)
            {
                throw new ArgumentException("Not a WinForms controller");
            }

            ParentControl = ParentController.Control;
            ParentController.Attach(this);

            //****************************************

            // Search the controls underneath the parent for our desired UserControl
            _UserControl = WalkControls(ParentControl, targetType);

            if (_UserControl == null)
            {
                throw new InvalidOperationException("Control does not exist");
            }

            _UserControl.Enter         += OnGotFocus;
            _UserControl.HandleCreated += OnLoad;
            _UserControl.Leave         += OnLostFocus;

            //****************************************

            _Provider = ((WinToolkit)GuiService.Toolkit).GetProvider(presenter.Host);
            _ViewDef  = _Provider.GetViewDef(this.Name);
        }
Exemplo n.º 3
0
        //---------------------------------------------------------------------
        public ViewModelBase GetVM(ViewDef viewName)
        {
            switch (viewName)
            {
            case ViewDef.Main:
                return(_mainVM);
            }

            return(null);
        }
Exemplo n.º 4
0
        //---------------------------------------------------------------------
        /// <summary>
        /// Create a view with its viewModel.
        /// </summary>
        /// <param name="view"></param>
        /// <returns></returns>
        public ViewModelBase ShowView(ViewDef view)
        {
            //switch (view)
            //{
            //    //case ViewDef.SplashScreen:
            //    //    return ShowSplashScreen();

            //    //case ViewDef.Main:
            //    //    return ShowMainView();
            //}

            return(null);
        }
Exemplo n.º 5
0
        //****************************************

        internal WinFormController(GuiFormPresenter presenter, Form form) : base(presenter)
        {
            _Form = form;

            form.FormClosing   += OnFormClosing;
            form.Activated     += OnGotFocus;
            form.HandleCreated += OnLoad;
            form.Deactivate    += OnLostFocus;

            //****************************************

            _Provider = ((WinToolkit)GuiService.Toolkit).GetProvider(presenter.Host);
            _ViewDef  = _Provider.GetViewDef(this.Name);
        }
Exemplo n.º 6
0
        //---------------------------------------------------------------------
        /// <summary>
        /// Close a View: a window/dlg.
        /// </summary>
        /// <param name="viewName"></param>
        /// <returns></returns>
        public bool CloseView(ViewDef viewName)
        {
            // check for modified data, ask the user to save it or not
            // TODO

            //switch (viewName)
            //{
            //    // close the dlg
            //    //case AppGenDef.View.DlgEditEntityPropertiesTags:
            //    //    return _appDlg.CloseViewDlgEditEntityPropertiesTags();
            //}

            return(false);
        }
Exemplo n.º 7
0
        //---------------------------------------------------------------------
        public ViewModelBase CreateVM(ViewDef viewName)
        {
            //switch (viewName)
            //{
            //    //case AppGenDef.View.UCTabCtrlEditMainObject:
            //    //    _ucTabCtrlEditMainObjectVM = new UCTabCtrlEditMainObjectVM();
            //    //    return _ucTabCtrlEditMainObjectVM;

            //    //case AppGenDef.View.UCMainTreeView:
            //    //    _ucMainTreeViewVM = new UCMainTreeViewVM();
            //    //    return _ucMainTreeViewVM;
            //}

            return(null);
        }
        internal ViewDef GetViewDef(string name)
        {               //****************************************
            ViewDef MyViewDef;

            //****************************************

            if (_Views.TryGetValue(name, out MyViewDef))
            {
                return(MyViewDef);
            }

            //****************************************

            _Views.Add(name, MyViewDef = new ViewDef(name));

            return(MyViewDef);
        }
        //****************************************

        internal void Load()
        {               //****************************************
            Stream    ResourceStream;
            XmlReader Reader;

            ViewDef MyViewDef;

            //****************************************

            _Views = new Dictionary <string, ViewDef>();

            using (ResourceStream = ResourceLoader.Load(_Provider.PrimaryAssembly, "WinForms.xml"))
            {
                Reader = XmlReader.Create(ResourceStream);

                if (!Reader.ReadToFollowing("WinForms"))
                {
                    throw new InvalidDataException("Not a valid WinForms Provider Definition");
                }

                while (Reader.Read())
                {
                    if (Reader.MoveToContent() == XmlNodeType.EndElement)
                    {
                        break;
                    }

                    switch (Reader.LocalName)
                    {
                    case "View":
                        MyViewDef = new ViewDef(this, Reader);

                        _Views.Add(MyViewDef.Name, MyViewDef);
                        break;

                    default:
                        Reader.Skip();
                        break;
                    }
                }

                Reader.Close();
            }
        }
Exemplo n.º 10
0
        //void GetFrameBounds(RenderEntity ent, out Bounds bounds);

        void DrawJoints(RenderEntity ent, ViewDef view)
        {
            int i; Vector3 pos;

            var num = ent.numJoints;

            for (i = 0; i < num; i++)
            {
                var joint    = ent.joints[i];
                var md5Joint = joints[i];
                pos = ent.origin + joint.ToVec3() * ent.axis;
                if (md5Joint.parent != null)
                {
                    var parentNum = md5Joint.parent - joints;
                    session.rw.DebugLine(colorWhite, ent.origin + ent.joints[parentNum].ToVec3() * ent.axis, pos);
                }

                session.rw.DebugLine(colorRed, pos, pos + joint.ToMat3()[0] * 2f * ent.axis);
                session.rw.DebugLine(colorGreen, pos, pos + joint.ToMat3()[1] * 2f * ent.axis);
                session.rw.DebugLine(colorBlue, pos, pos + joint.ToMat3()[2] * 2f * ent.axis);
            }

            Bounds bounds = new();

            bounds.FromTransformedBounds(ent.bounds, Vector3.origin, ent.axis);
            session.rw.DebugBounds(colorMagenta, bounds, ent.origin);

            if (r_jointNameScale.Float != 0f && bounds.Expand(128f).ContainsPoint(view.renderView.vieworg - ent.origin))
            {
                Vector3 offset = new(0f, 0f, r_jointNameOffset.Float);
                var     scale  = r_jointNameScale.Float;
                num = ent.numJoints;
                for (i = 0; i < num; i++)
                {
                    var joint = ent.joints[i];
                    pos = ent.origin + joint.ToVec3() * ent.axis;
                    session.rw.DrawText(joints[i].name, pos + offset, scale, colorWhite, view.renderView.viewaxis, 1);
                }
            }
        }
Exemplo n.º 11
0
        public override IRenderModel InstantiateDynamicModel(RenderEntity ent, ViewDef view, IRenderModel cachedModel)
        {
            int i, surfaceNum; MD5Mesh mesh; RenderModelStatic staticModel;

            if (cachedModel != null && !r_useCachedDynamicModels.Bool)
            {
                cachedModel.Dispose();
                cachedModel = null;
            }

            if (purged)
            {
                common.DWarning($"model {Name} instantiated while purged"); LoadModel();
            }

            if (ent.joints == null)
            {
                common.Printf($"RenderModelMD5::InstantiateDynamicModel: null joints on renderEntity for '{Name}'\n");
                cachedModel.Dispose();
                return(null);
            }
            else if (ent.numJoints != joints.Length)
            {
                common.Printf($"RenderModelMD5::InstantiateDynamicModel: renderEntity has different number of joints than model for '{Name}'\n");
                cachedModel.Dispose();
                return(null);
            }

            tr.pc.c_generateMd5++;

            if (cachedModel != null)
            {
                Debug.Assert(cachedModel is RenderModelStatic);
                Debug.Assert(string.Equals(cachedModel.Name, MD5_SnapshotName, StringComparison.OrdinalIgnoreCase));
                staticModel = (RenderModelStatic)cachedModel;
            }
            else
            {
                staticModel = new RenderModelStatic();
                staticModel.InitEmpty(MD5_SnapshotName);
            }

            staticModel.bounds.Clear();

            if (r_showSkel.Integer != 0)
            {
                if (view != null && (!r_skipSuppress.Bool || ent.suppressSurfaceInViewID == 0 || ent.suppressSurfaceInViewID != view.renderView.viewID))
                {
                    DrawJoints(ent, view);                                                                                                                                      // only draw the skeleton
                }
                if (r_showSkel.Integer > 1)
                {
                    staticModel.InitEmpty(MD5_SnapshotName); return(staticModel);
                }                                                                                            // turn off the model when showing the skeleton
            }

            // create all the surfaces
            for (i = 0; i < meshes.Length; i++)
            {
                mesh = meshes[i];

                // avoid deforming the surface if it will be a nodraw due to a skin remapping. FIXME: may have to still deform clipping hulls
                var shader = mesh.shader;

                shader = R_RemapShaderBySkin(shader, ent.customSkin, ent.customShader);

                if (shader == null || (!shader.IsDrawn && !shader.SurfaceCastsShadow))
                {
                    staticModel.DeleteSurfaceWithId(i); mesh.surfaceNum = -1; continue;
                }

                ModelSurface surf;
                if (staticModel.FindSurfaceWithId(i, out surfaceNum))
                {
                    mesh.surfaceNum = surfaceNum;
                    surf            = staticModel.surfaces[surfaceNum];
                }
                else
                {
                    // Remove Overlays before adding new surfaces
                    RenderModelOverlay.RemoveOverlaySurfacesFromModel(staticModel);

                    mesh.surfaceNum = staticModel.NumSurfaces;
                    surf            = staticModel.surfaces.Alloc();
                    surf.geometry   = null;
                    surf.shader     = null;
                    surf.id         = i;
                }

                mesh.UpdateSurface(ent, ent.joints, surf);

                staticModel.bounds.AddPoint(surf.geometry.bounds[0]);
                staticModel.bounds.AddPoint(surf.geometry.bounds[1]);
            }

            return(staticModel);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Fills the schema of the table consulting the schema of the sharepoint list.
        /// </summary>
        /// <param name="table">the DataTable object to change</param>
        /// <param name="connection">an open Sharepoint connection</param>
        protected void FillSchemaFromSharepoint(DataTable table, SpConnection connection)
        {
            if (table == null)
            {
                throw new ArgumentNullException("table");
            }

            ViewDef viewDef = null;
            ListDef listDef = null;

            if (this.ViewName != null)
            {
                viewDef = connection.GetViewSchema(this.ListName, this.ViewName);
                listDef = viewDef.ListDef;
            }
            else
            {
                listDef = connection.GetListSchema(this.ListName);
            }

            IList <DataColumn> primaryColumns = new List <DataColumn>();

            foreach (Field field in listDef.Fields)
            {
                DataColumn column;

                if (viewDef != null &&
                    viewDef.ViewFields.Count > 0 &&
                    !ContainsFieldRefWithName(viewDef.ViewFields, field.Name))
                {
                    continue;
                }

                if (!table.Columns.Contains(field.Name))
                {
                    column = new DataColumn();
                    table.Columns.Add(column);
                }
                else
                {
                    column = table.Columns[field.Name];
                }

                MapFromFieldToColumn(column, field);

                // sharepoint returns as primary key the ID
                // which is relevant to sharepoint list.
                if (field.IsPrimaryKey)
                {
                    primaryColumns.Add(column);
                }
            }

            bool primaryRemoved = false;

            if (DataColumns.Count > 0)
            {
                List <string> columnsToRemove = new List <string>();
                foreach (DataColumn tableColumn in table.Columns)
                {
                    if (!DataColumns.Contains(tableColumn.ColumnName))
                    {
                        columnsToRemove.Add(tableColumn.ColumnName);

                        if (primaryColumns.Contains(tableColumn))
                        {
                            primaryRemoved = true;
                        }
                    }
                }

                foreach (string tableColumn2 in columnsToRemove)
                {
                    table.Columns.Remove(tableColumn2);
                }
            }

            if (primaryColumns.Count > 0 && !primaryRemoved)
            {
                DataColumn[] primaryKey = new DataColumn[primaryColumns.Count];
                primaryColumns.CopyTo(primaryKey, 0);
                table.PrimaryKey = primaryKey;
            }

            table.TableName = this.TableName;
        }
Exemplo n.º 13
0
 public bool isShow(ViewDef viewConst)
 {
     return(isShow((int)viewConst));
 }
Exemplo n.º 14
0
    public void close(ViewDef viewConst, params object[] param)
    {
        int key = (int)viewConst;

        close(key, param);
    }
Exemplo n.º 15
0
 public IBaseView open(ViewDef key, params object[] param)
 {
     return(open((int)key, param));
 }
Exemplo n.º 16
0
 public void register(ViewDef key, IBaseView view)
 {
     register((int)key, view);
 }
Exemplo n.º 17
0
        public override IRenderModel InstantiateDynamicModel(RenderEntity ent, ViewDef view, IRenderModel cachedModel)
        {
            idRenderModelStatic *staticModel;

            if (cachedModel && !r_useCachedDynamicModels.GetBool())
            {
                delete cachedModel;
                cachedModel = NULL;
            }

            // this may be triggered by a model trace or other non-view related source, to which we should look like an empty model
            if (renderEntity == NULL || viewDef == NULL)
            {
                delete cachedModel;
                return(NULL);
            }

            if (r_skipParticles.GetBool())
            {
                delete cachedModel;
                return(NULL);
            }

            /*
             * // if the entire system has faded out
             * if ( renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] && viewDef->renderView.time * 0.001f >= renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] ) {
             *      delete cachedModel;
             *      return NULL;
             * }
             */

            if (cachedModel != NULL)
            {
                assert(dynamic_cast <idRenderModelStatic *>(cachedModel) != NULL);
                assert(idStr::Icmp(cachedModel->Name(), parametricParticle_SnapshotName) == 0);

                staticModel = static_cast <idRenderModelStatic *>(cachedModel);
            }
            else
            {
                staticModel = new idRenderModelStatic;
                staticModel->InitEmpty(parametricParticle_SnapshotName);
            }

            particleGen_t g;

            g.renderEnt  = renderEntity;
            g.renderView = &viewDef->renderView;
            g.origin.Zero();
            g.axis.Identity();

            for (int stageNum = 0; stageNum < particleSystem->stages.Num(); stageNum++)
            {
                idParticleStage *stage = particleSystem->stages[stageNum];

                if (!stage->material)
                {
                    continue;
                }
                if (!stage->cycleMsec)
                {
                    continue;
                }
                if (stage->hidden)
                {                       // just for gui particle editor use
                    staticModel->DeleteSurfaceWithId(stageNum);
                    continue;
                }

                idRandom steppingRandom, steppingRandom2;

                int stageAge   = g.renderView->time + renderEntity->shaderParms[SHADERPARM_TIMEOFFSET] * 1000 - stage->timeOffset * 1000;
                int stageCycle = stageAge / stage->cycleMsec;

                // some particles will be in this cycle, some will be in the previous cycle
                steppingRandom.SetSeed(((stageCycle << 10) & idRandom::MAX_RAND) ^ (int)(renderEntity->shaderParms[SHADERPARM_DIVERSITY] * idRandom::MAX_RAND));
                steppingRandom2.SetSeed((((stageCycle - 1) << 10) & idRandom::MAX_RAND) ^ (int)(renderEntity->shaderParms[SHADERPARM_DIVERSITY] * idRandom::MAX_RAND));

                int count = stage->totalParticles * stage->NumQuadsPerParticle();

                int             surfaceNum;
                modelSurface_t *surf;

                if (staticModel->FindSurfaceWithId(stageNum, surfaceNum))
                {
                    surf = &staticModel->surfaces[surfaceNum];
                    R_FreeStaticTriSurfVertexCaches(surf->geometry);
                }
                else
                {
                    surf           = &staticModel->surfaces.Alloc();
                    surf->id       = stageNum;
                    surf->shader   = stage->material;
                    surf->geometry = R_AllocStaticTriSurf();
                    R_AllocStaticTriSurfVerts(surf->geometry, 4 * count);
                    R_AllocStaticTriSurfIndexes(surf->geometry, 6 * count);
                    R_AllocStaticTriSurfPlanes(surf->geometry, 6 * count);
                }

                int         numVerts = 0;
                idDrawVert *verts    = surf->geometry->verts;

                for (int index = 0; index < stage->totalParticles; index++)
                {
                    g.index = index;

                    // bump the random
                    steppingRandom.RandomInt();
                    steppingRandom2.RandomInt();

                    // calculate local age for this index
                    int bunchOffset = stage->particleLife * 1000 * stage->spawnBunching * index / stage->totalParticles;

                    int particleAge   = stageAge - bunchOffset;
                    int particleCycle = particleAge / stage->cycleMsec;
                    if (particleCycle < 0)
                    {
                        // before the particleSystem spawned
                        continue;
                    }
                    if (stage->cycles && particleCycle >= stage->cycles)
                    {
                        // cycled systems will only run cycle times
                        continue;
                    }

                    if (particleCycle == stageCycle)
                    {
                        g.random = steppingRandom;
                    }
                    else
                    {
                        g.random = steppingRandom2;
                    }

                    int inCycleTime = particleAge - particleCycle * stage->cycleMsec;

                    if (renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] &&
                        g.renderView->time - inCycleTime >= renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] * 1000)
                    {
                        // don't fire any more particles
                        continue;
                    }

                    // supress particles before or after the age clamp
                    g.frac = (float)inCycleTime / (stage->particleLife * 1000);
                    if (g.frac < 0.0f)
                    {
                        // yet to be spawned
                        continue;
                    }
                    if (g.frac > 1.0f)
                    {
                        // this particle is in the deadTime band
                        continue;
                    }

                    // this is needed so aimed particles can calculate origins at different times
                    g.originalRandom = g.random;

                    g.age = g.frac * stage->particleLife;

                    // if the particle doesn't get drawn because it is faded out or beyond a kill region, don't increment the verts
                    numVerts += stage->CreateParticle(&g, verts + numVerts);
                }

                // numVerts must be a multiple of 4
                assert((numVerts & 3) == 0 && numVerts <= 4 * count);

                // build the indexes
                int        numIndexes = 0;
                glIndex_t *indexes    = surf->geometry->indexes;
                for (int i = 0; i < numVerts; i += 4)
                {
                    indexes[numIndexes + 0] = i;
                    indexes[numIndexes + 1] = i + 2;
                    indexes[numIndexes + 2] = i + 3;
                    indexes[numIndexes + 3] = i;
                    indexes[numIndexes + 4] = i + 3;
                    indexes[numIndexes + 5] = i + 1;
                    numIndexes += 6;
                }

                surf->geometry->tangentsCalculated   = false;
                surf->geometry->facePlanesCalculated = false;
                surf->geometry->numVerts             = numVerts;
                surf->geometry->numIndexes           = numIndexes;
                surf->geometry->bounds = stage->bounds;                     // just always draw the particles
            }

            return(staticModel);
        }
Exemplo n.º 18
0
        public override IRenderModel InstantiateDynamicModel(RenderEntity ent, ViewDef view, IRenderModel cachedModel)
        {
            RenderModelStatic staticModel;
            SrfTriangles      tri;
            ModelSurface      surf;

            if (cachedModel != null && !r_useCachedDynamicModels.Bool)
            {
                cachedModel.Dispose(); cachedModel = null;
            }

            if (ent == null || view == null)
            {
                cachedModel.Dispose(); cachedModel = null;
            }

            if (cachedModel != null)
            {
                Debug.Assert(cachedModel is RenderModelStatic);
                Debug.Assert(string.Equals(cachedModel.Name, sprite_SnapshotName, StringComparison.OrdinalIgnoreCase));

                staticModel = (RenderModelStatic)cachedModel;
                surf        = staticModel.Surface(0);
                tri         = surf.geometry;
            }
            else
            {
                staticModel = new RenderModelStatic();
                staticModel.InitEmpty(sprite_SnapshotName);

                tri = R_AllocStaticTriSurf();
                R_AllocStaticTriSurfVerts(tri, 4);
                R_AllocStaticTriSurfIndexes(tri, 6);

                tri.verts[0].Clear();
                tri.verts[0].normal.Set(1f, 0f, 0f);
                tri.verts[0].tangents0.Set(0f, 1f, 0f);
                tri.verts[0].tangents1.Set(0f, 0f, 1f);
                tri.verts[0].st.x = 0f;
                tri.verts[0].st.y = 0f;

                tri.verts[1].Clear();
                tri.verts[1].normal.Set(1f, 0f, 0f);
                tri.verts[1].tangents0.Set(0f, 1f, 0f);
                tri.verts[1].tangents1.Set(0f, 0f, 1f);
                tri.verts[1].st.x = 1f;
                tri.verts[1].st.y = 0f;

                tri.verts[2].Clear();
                tri.verts[2].normal.Set(1f, 0f, 0f);
                tri.verts[2].tangents0.Set(0f, 1f, 0f);
                tri.verts[2].tangents1.Set(0f, 0f, 1f);
                tri.verts[2].st.x = 1f;
                tri.verts[2].st.y = 1f;

                tri.verts[3].Clear();
                tri.verts[3].normal.Set(1f, 0f, 0f);
                tri.verts[3].tangents0.Set(0f, 1f, 0f);
                tri.verts[3].tangents1.Set(0f, 0f, 1f);
                tri.verts[3].st.x = 0f;
                tri.verts[3].st.y = 1f;

                tri.indexes[0] = 0;
                tri.indexes[1] = 1;
                tri.indexes[2] = 3;
                tri.indexes[3] = 1;
                tri.indexes[4] = 2;
                tri.indexes[5] = 3;

                tri.numVerts   = 4;
                tri.numIndexes = 6;

                surf          = new();
                surf.geometry = tri;
                surf.id       = 0;
                surf.shader   = tr.defaultMaterial;
                staticModel.AddSurface(surf);
            }

            var red   = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_RED] * 255f);
            var green = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_GREEN] * 255f);
            var blue  = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_BLUE] * 255f);
            var alpha = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_ALPHA] * 255f);

            var right = new Vector3(0f, ent.shaderParms[IRenderWorld.SHADERPARM_SPRITE_WIDTH] * 0.5f, 0f);
            var up    = new Vector3(0f, 0f, ent.shaderParms[IRenderWorld.SHADERPARM_SPRITE_HEIGHT] * 0.5f);

            tri.verts[0].xyz    = up + right;
            tri.verts[0].color0 = red;
            tri.verts[0].color1 = green;
            tri.verts[0].color2 = blue;
            tri.verts[0].color3 = alpha;

            tri.verts[1].xyz    = up - right;
            tri.verts[1].color0 = red;
            tri.verts[1].color1 = green;
            tri.verts[1].color2 = blue;
            tri.verts[1].color3 = alpha;

            tri.verts[2].xyz    = -right - up;
            tri.verts[2].color0 = red;
            tri.verts[2].color1 = green;
            tri.verts[2].color2 = blue;
            tri.verts[2].color3 = alpha;

            tri.verts[3].xyz    = right - up;
            tri.verts[3].color0 = red;
            tri.verts[3].color1 = green;
            tri.verts[3].color2 = blue;
            tri.verts[3].color3 = alpha;

            R_BoundTriSurf(tri);

            staticModel.bounds = tri.bounds;

            return(staticModel);
        }
Exemplo n.º 19
0
        => true;        // don't ever need to load

        public override IRenderModel InstantiateDynamicModel(RenderEntity ent, ViewDef view, IRenderModel cachedModel)
        {
            RenderModelStatic staticModel; SrfTriangles tri; ModelSurface surf;

            if (cachedModel != null)
            {
                cachedModel = null;
            }

            if (ent == null || view == null)
            {
                return(null);
            }

            if (cachedModel != null)
            {
                Debug.Assert(cachedModel is RenderModelStatic);
                Debug.Assert(string.Equals(cachedModel.Name, beam_SnapshotName, StringComparison.OrdinalIgnoreCase));

                staticModel = (RenderModelStatic)cachedModel;
                surf        = staticModel.Surface(0);
                tri         = surf.geometry;
            }
            else
            {
                staticModel = new RenderModelStatic();
                staticModel.InitEmpty(beam_SnapshotName);

                tri = R_AllocStaticTriSurf();
                R_AllocStaticTriSurfVerts(tri, 4);
                R_AllocStaticTriSurfIndexes(tri, 6);

                tri.verts[0].Clear(); tri.verts[0].st.x = 0; tri.verts[0].st.y = 0;
                tri.verts[1].Clear(); tri.verts[1].st.x = 0; tri.verts[1].st.y = 1;
                tri.verts[2].Clear(); tri.verts[2].st.x = 1; tri.verts[2].st.y = 0;
                tri.verts[3].Clear(); tri.verts[3].st.x = 1; tri.verts[3].st.y = 1;

                tri.indexes[0] = 0; tri.indexes[1] = 2; tri.indexes[2] = 1; tri.indexes[3] = 2; tri.indexes[4] = 3; tri.indexes[5] = 1;

                tri.numVerts   = 4;
                tri.numIndexes = 6;

                surf          = new();
                surf.geometry = tri;
                surf.id       = 0;
                surf.shader   = tr.defaultMaterial;
                staticModel.AddSurface(surf);
            }

            Vector3 target = reinterpret.cast_vec3(ent.shaderParms, IRenderWorld.SHADERPARM_BEAM_END_X);

            // we need the view direction to project the minor axis of the tube as the view changes
            var modelMatrix = stackalloc float[16];

            R_AxisToModelMatrix(ent.axis, ent.origin, modelMatrix);
            R_GlobalPointToLocal(modelMatrix, view.renderView.vieworg, out var localView);
            R_GlobalPointToLocal(modelMatrix, target, out var localTarget);

            Vector3 major = localTarget;
            Vector3 minor = default;

            Vector3 mid = 0.5f * localTarget;
            Vector3 dir = mid - localView;

            minor.Cross(major, dir);
            minor.Normalize();
            if (ent.shaderParms[IRenderWorld.SHADERPARM_BEAM_WIDTH] != 0f)
            {
                minor *= ent.shaderParms[IRenderWorld.SHADERPARM_BEAM_WIDTH] * 0.5f;
            }

            var red   = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_RED] * 255f);
            var green = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_GREEN] * 255f);
            var blue  = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_BLUE] * 255f);
            var alpha = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_ALPHA] * 255f);

            tri.verts[0].xyz = minor; tri.verts[0].color0 = red; tri.verts[0].color1 = green; tri.verts[0].color2 = blue; tri.verts[0].color3 = alpha;
            tri.verts[1].xyz = -minor; tri.verts[1].color0 = red; tri.verts[1].color1 = green; tri.verts[1].color2 = blue; tri.verts[1].color3 = alpha;
            tri.verts[2].xyz = localTarget + minor; tri.verts[2].color0 = red; tri.verts[2].color1 = green; tri.verts[2].color2 = blue; tri.verts[2].color3 = alpha;
            tri.verts[3].xyz = localTarget - minor; tri.verts[3].color0 = red; tri.verts[3].color1 = green; tri.verts[3].color2 = blue; tri.verts[3].color3 = alpha;

            R_BoundTriSurf(tri);

            staticModel.bounds = tri.bounds;

            return(staticModel);
        }