├── .gitattributes ├── .gitignore ├── HelperSuite ├── ContentLoader │ └── ThreadSafeContentManager.cs ├── GUI log.txt ├── GUI │ ├── GUIBlock.cs │ ├── GUICanvas.cs │ ├── GUIColorPicker.cs │ ├── GUIElement.cs │ ├── GUIList.cs │ ├── GUIStyle.cs │ ├── GUITextBlock.cs │ ├── GUITextBlockButton.cs │ ├── GUITextBlockToggle.cs │ ├── GuiDropList.cs │ ├── GuiListToggle.cs │ ├── GuiListToggleScroll.cs │ ├── GuiSliderFloat.cs │ ├── GuiSliderFloatText.cs │ ├── GuiSliderInt.cs │ ├── GuiSliderIntText.cs │ └── GuiTextBlockLoadDialog.cs ├── GUIHelper │ ├── GUIContentLoader.cs │ ├── GUIControl.cs │ └── MngStringBuilder.cs ├── GUIRenderer │ └── GUIRenderer.cs ├── HelperSuite.csproj └── Properties │ └── AssemblyInfo.cs ├── MGSkinnedAnimationAux ├── AnimationClip.cs ├── AnimationClipReader.cs ├── Bone.cs ├── MGSkinnedAnimationAux.csproj ├── ModelExtra.cs ├── ModelExtraReader.cs └── Properties │ └── AssemblyInfo.cs ├── MGSkinnedAnimationPipeline ├── AnimationClipWriter.cs ├── AnimationProcessor.cs ├── MGSkinnedAnimationPipeline.csproj ├── ModelExtraWriter.cs └── Properties │ └── AssemblyInfo.cs ├── ModelViewer.sln ├── ModelViewer ├── Content │ ├── Content.mgcb │ ├── Fonts │ │ ├── defaultfont.spritefont │ │ └── monospace.spritefont │ ├── Graphical User Interface │ │ ├── GUIEffect.fx │ │ ├── colorpickerbig.png │ │ ├── colorpickersmall.png │ │ └── ring.png │ ├── ProtonType.Content.Pipeline.DDSImporter.dll │ ├── ShaderModules │ │ ├── AmbientOcclusionShader │ │ │ └── AmbientOcclusionShader.fx │ │ ├── AnimatedModelShader │ │ │ ├── AnimatedModelShader.fx │ │ │ ├── cube.fbx │ │ │ ├── fresnel.png │ │ │ ├── fresnel2.png │ │ │ └── helper.fx │ │ ├── ScreenSpace │ │ │ └── GUIEffect.fx │ │ └── Skybox │ │ │ ├── Skybox.fx │ │ │ ├── isosphere.fbx │ │ │ ├── skyboxCubemap.dds │ │ │ └── skyboxCubemap_sec.dds │ └── mgcb │ │ ├── ATI.TextureConverter.dll │ │ ├── Assimp64.dll │ │ ├── AssimpNet.dll │ │ ├── AssimpNet.xml │ │ ├── CppNet.dll │ │ ├── FreeImage.dll │ │ ├── FreeImageNET.dll │ │ ├── MGCB.exe │ │ ├── MGCB.xml │ │ ├── MGSkinnedAnimationAux.dll │ │ ├── MGSkinnedAnimationPipeline.dll │ │ ├── MonoGame.Framework.Content.Pipeline.dll │ │ ├── MonoGame.Framework.dll │ │ ├── Nvidia.TextureTools.dll │ │ ├── PVRTexLibNET.dll │ │ ├── PVRTexLibWrapper.dll │ │ ├── ffmpeg.exe │ │ ├── ffprobe.exe │ │ ├── freetype6.dll │ │ ├── libmojoshader_64.dll │ │ ├── nvtt.dll │ │ ├── runtimeanimatedmodel.txt │ │ ├── runtimemodel.txt │ │ ├── runtimemodelnotangent.txt │ │ └── runtimetexture.txt ├── HelperSuiteExtension │ ├── GUI │ │ └── GuiTextBlockLoadDialog.cs │ └── GUIHelper │ │ └── GUIContentLoaderModelViewer.cs ├── Icon.ico ├── Logic │ ├── Camera.cs │ ├── GUILogic.cs │ ├── Input.cs │ └── MainLogic.cs ├── ModelViewer.cs ├── ModelViewer.csproj ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── Renderer │ ├── Renderer.cs │ └── ShaderModules │ │ ├── AmbientOcclusionShader.cs │ │ ├── AnimatedModelShader.cs │ │ ├── Helper │ │ ├── AnimatedModel.cs │ │ ├── AnimationPlayer.cs │ │ └── QuadRenderer.cs │ │ └── Skybox.cs ├── Static │ ├── DebugScreen.cs │ ├── Extension.cs │ ├── GameSettings.cs │ ├── GameStats.cs │ └── ScreenManager.cs └── app.manifest └── Readme.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | -------------------------------------------------------------------------------- /HelperSuite/ContentLoader/ThreadSafeContentManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Xna.Framework.Content; 3 | 4 | namespace HelperSuite.ContentLoader 5 | { 6 | public class ThreadSafeContentManager : ContentManager 7 | { 8 | private static readonly object LoadLock = new object(); 9 | 10 | public ThreadSafeContentManager(IServiceProvider serviceProvider) 11 | : base(serviceProvider) 12 | { 13 | } 14 | 15 | public ThreadSafeContentManager(IServiceProvider serviceProvider, string rootDirectory) 16 | : base(serviceProvider, rootDirectory) 17 | { 18 | } 19 | 20 | public override T Load(string assetName) 21 | { 22 | lock (LoadLock) 23 | { 24 | return base.Load(assetName); 25 | } 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /HelperSuite/GUI log.txt: -------------------------------------------------------------------------------- 1 | GUI LOG 2 | 3 | Requirements: 4 | MonospaceFont = Fonts/monospace 5 | 6 | images: 7 | colorPickerSmall = Graphical User Interface/colorpickersmall 8 | colorPickerBig = Graphical User Interface/colorpickerBig 9 | 10 | GUIControl needs to be updated with each Update Period and each Resolution Change 11 | 12 | Version 1.3 13 | 14 | 1.1 - Style added, now Elements can be created with Element(style, other properties...) to save time and have a unified appearance. 15 | 1.2 - Made it a seperate project, so it can easily be integrated into new projects. Added a global GUIControl 16 | 1.3 - GUI Sliders now easier to setup 17 | 18 | -------------------------------------------------------------------------------- /HelperSuite/GUI/GUIBlock.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | 3 | namespace HelperSuite.GUI 4 | { 5 | /// 6 | /// Just a colored block 7 | /// 8 | public class GUIBlock : GUIElement 9 | { 10 | public Color BlockColor; 11 | 12 | public GUIBlock(GUIStyle style) : this( 13 | position: Vector2.Zero, 14 | dimensions: style.DimensionsStyle, 15 | blockColor: style.BlockColorStyle, 16 | layer: 0, 17 | alignment: style.GuiAlignmentStyle, 18 | ParentDimensions: style.ParentDimensionsStyle) 19 | { 20 | //Filled by GuiStyle 21 | } 22 | 23 | public GUIBlock(Vector2 position, Vector2 dimensions, Color blockColor, int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 ParentDimensions = default(Vector2)) 24 | { 25 | Position = position; 26 | Dimensions = dimensions; 27 | BlockColor = blockColor; 28 | Layer = layer; 29 | Alignment = alignment; 30 | if (Alignment != GUIStyle.GUIAlignment.None) 31 | { 32 | ParentResized(ParentDimensions); 33 | } 34 | 35 | } 36 | 37 | private GUIBlock() 38 | { 39 | } 40 | 41 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 42 | { 43 | guiRenderer.DrawQuad(parentPosition+Position, Dimensions, BlockColor); 44 | } 45 | 46 | public override void ParentResized(Vector2 dimensions) 47 | { 48 | Position = GUICanvas.UpdateAlignment(Alignment, dimensions, Dimensions, Position, OffsetPosition); 49 | } 50 | 51 | public override int Layer { get; set; } 52 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 53 | { 54 | //; 55 | } 56 | 57 | 58 | public override GUIStyle.GUIAlignment Alignment { get; set; } 59 | 60 | public bool IsVisible 61 | { 62 | get 63 | { 64 | return !IsHidden; 65 | } 66 | 67 | set 68 | { 69 | IsHidden = !value; 70 | } 71 | } 72 | 73 | } 74 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GUICanvas.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.Xna.Framework; 4 | 5 | namespace HelperSuite.GUI 6 | { 7 | //todo: 8 | //Sort by layer to see which UIClick is the active one (only on top!) 9 | 10 | public class GUICanvas : GUIElement 11 | { 12 | public bool IsEnabled = true; 13 | 14 | private List _children = new List(); 15 | 16 | public GUICanvas(Vector2 position, Vector2 dimensions, int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 ParentDimensions = default(Vector2)) 17 | { 18 | Dimensions = dimensions; 19 | Alignment = alignment; 20 | Position = position; 21 | OffsetPosition = position; 22 | Layer = layer; 23 | if (Alignment != GUIStyle.GUIAlignment.None) 24 | { 25 | ParentResized(ParentDimensions); 26 | } 27 | } 28 | 29 | //Draw the GUI, cycle through the children 30 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 31 | { 32 | if (!IsEnabled) return; 33 | for (int index = 0; index < _children.Count; index++) 34 | { 35 | GUIElement child = _children[index]; 36 | if (child.IsHidden) continue; 37 | child.Draw(guiRenderer, parentPosition + Position, mousePosition); 38 | } 39 | } 40 | 41 | public void Resize(float width, float height) 42 | { 43 | Dimensions = new Vector2(width, height); 44 | ParentResized(Dimensions); 45 | } 46 | 47 | //Adjust things when resized 48 | public override void ParentResized(Vector2 parentDimensions) 49 | { 50 | Position = UpdateAlignment(Alignment, parentDimensions, Dimensions, Position, OffsetPosition); 51 | 52 | for (int index = 0; index < _children.Count; index++) 53 | { 54 | GUIElement child = _children[index]; 55 | if (child.IsHidden) continue; 56 | child.ParentResized(Dimensions); 57 | } 58 | 59 | } 60 | 61 | //If the parent resized then our alignemnt may have changed and we need new position coordinates 62 | public static Vector2 UpdateAlignment(GUIStyle.GUIAlignment alignment, Vector2 parentDimensions, Vector2 dimensions, Vector2 position, Vector2 offsetPosition) 63 | { 64 | if (parentDimensions == Vector2.Zero) throw new NotImplementedException(); 65 | 66 | switch (alignment) 67 | { 68 | case GUIStyle.GUIAlignment.None: 69 | break; 70 | case GUIStyle.GUIAlignment.TopLeft: 71 | position.X = 0; 72 | position.Y = 0; 73 | break; 74 | case GUIStyle.GUIAlignment.TopRight: 75 | position.X = parentDimensions.X - dimensions.X; 76 | position.Y = 0; 77 | break; 78 | case GUIStyle.GUIAlignment.BottomLeft: 79 | position.Y = parentDimensions.Y - dimensions.Y; 80 | position.X = 0; 81 | break; 82 | case GUIStyle.GUIAlignment.BottomRight: 83 | position = parentDimensions - dimensions; 84 | break; 85 | case GUIStyle.GUIAlignment.Center: 86 | position = parentDimensions/2 - dimensions/2; 87 | break; 88 | default: 89 | throw new ArgumentOutOfRangeException(); 90 | } 91 | return position + offsetPosition; 92 | } 93 | 94 | public void AddElement(GUIElement element) 95 | { 96 | //In Order 97 | for (int i = 0; i < _children.Count; i++) 98 | { 99 | if (_children[i].Layer > element.Layer) 100 | { 101 | _children.Insert(i, element); 102 | return; 103 | } 104 | } 105 | 106 | _children.Add(element); 107 | } 108 | 109 | public override int Layer { get; set; } 110 | 111 | /// 112 | /// Update our logic 113 | /// 114 | /// 115 | /// 116 | /// 117 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 118 | { 119 | if (!IsEnabled) return; 120 | for (int index = 0; index < _children.Count; index++) 121 | { 122 | GUIElement child = _children[index]; 123 | child.Update(gameTime, mousePosition, parentPosition + Position); 124 | } 125 | } 126 | 127 | public override GUIStyle.GUIAlignment Alignment { get; set; } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /HelperSuite/GUI/GUIElement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | 3 | namespace HelperSuite.GUI 4 | { 5 | public abstract class GUIElement 6 | { 7 | public Vector2 Position; 8 | public Vector2 OffsetPosition; 9 | public Vector2 ParentDimensions; 10 | public bool IsHidden; 11 | public virtual Vector2 Dimensions { get; set; } 12 | public abstract void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition); 13 | public abstract void ParentResized(Vector2 dimensions); 14 | public abstract int Layer { get; set; } 15 | public abstract void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition); 16 | public abstract GUIStyle.GUIAlignment Alignment { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GUIList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.Xna.Framework; 4 | 5 | namespace HelperSuite.GUI 6 | { 7 | public class GUIList : GUIElement 8 | { 9 | public Vector2 DefaultDimensions; 10 | 11 | protected List _children = new List(); 12 | 13 | private GUIStyle.GUIAlignment _alignment; 14 | public override GUIStyle.GUIAlignment Alignment 15 | { 16 | get 17 | { 18 | return _alignment; 19 | } 20 | set 21 | { 22 | _alignment = value; 23 | if (value != GUIStyle.GUIAlignment.None) 24 | { 25 | ParentResized(ParentDimensions); 26 | } 27 | } 28 | } 29 | 30 | public GUIList(Vector2 position, GUIStyle guiStyle) : this( 31 | position: position, 32 | defaultDimensions: guiStyle.DimensionsStyle, 33 | layer: 0, 34 | alignment: guiStyle.GuiAlignmentStyle, 35 | parentDimensions: guiStyle.ParentDimensionsStyle) 36 | { 37 | 38 | } 39 | 40 | /// 41 | /// A list has a unified width/height of the elements. Each element is rendered below the other one 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | public GUIList(Vector2 position, Vector2 defaultDimensions, int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 parentDimensions = default(Vector2)) 49 | { 50 | DefaultDimensions = defaultDimensions; 51 | ParentDimensions = parentDimensions; 52 | Position = position; 53 | OffsetPosition = position; 54 | Layer = layer; 55 | Alignment = alignment; 56 | } 57 | 58 | //Draw the GUI, cycle through the children 59 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 60 | { 61 | if (IsHidden) return; 62 | 63 | float height = 0; 64 | 65 | for (int index = 0; index < _children.Count; index++) 66 | { 67 | GUIElement child = _children[index]; 68 | 69 | if (child.IsHidden) continue; 70 | 71 | child.Draw(guiRenderer, parentPosition + Position + height * Vector2.UnitY, mousePosition); 72 | 73 | height += _children[index].Dimensions.Y; 74 | } 75 | } 76 | 77 | //Adjust things when resized 78 | public override void ParentResized(Vector2 parentDimensions) 79 | { 80 | //for (int index = 0; index < _children.Count; index++) 81 | //{ 82 | // GUIElement child = _children[index]; 83 | // child.ParentResized(ElementDimensions); 84 | //} 85 | 86 | Position = GUICanvas.UpdateAlignment(Alignment, parentDimensions, Dimensions, Position, OffsetPosition); 87 | } 88 | 89 | 90 | public virtual void AddElement(GUIElement element) 91 | { 92 | //element.Position = new Vector2(0, _children.Count*DefaultDimensions.Y); 93 | //element.Dimensions = DefaultDimensions; 94 | 95 | 96 | // I think it is acceptable to make a for loop everytime an element is added 97 | float height = 0; 98 | for (int i = 0; i < _children.Count; i++) 99 | { 100 | height += _children[i].Dimensions.Y; 101 | } 102 | //element.Position = new Vector2(0,height); 103 | 104 | Dimensions = new Vector2(DefaultDimensions.X, height+element.Dimensions.Y); 105 | 106 | //In Order 107 | _children.Add(element); 108 | } 109 | 110 | public override int Layer { get; set; } 111 | 112 | 113 | /// 114 | /// Update our logic 115 | /// 116 | /// 117 | /// 118 | /// 119 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 120 | { 121 | if (IsHidden) 122 | { 123 | return; 124 | } 125 | 126 | float height = 0; 127 | for (int index = 0; index < _children.Count; index++) 128 | { 129 | GUIElement child = _children[index]; 130 | 131 | if (child.IsHidden) continue; 132 | 133 | child.Update(gameTime, mousePosition, parentPosition + Position + height * Vector2.UnitY); 134 | 135 | height += _children[index].Dimensions.Y; 136 | 137 | } 138 | if (Math.Abs(Dimensions.Y - height) > 0.01f) 139 | Dimensions = new Vector2(Dimensions.X, height); 140 | } 141 | 142 | } 143 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GUIStyle.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Graphics; 3 | 4 | namespace HelperSuite.GUI 5 | { 6 | public class GUIStyle 7 | { 8 | public Vector2 DimensionsStyle; 9 | public Color BlockColorStyle; 10 | public Color TextColorStyle; 11 | public Color SliderColorStyle; 12 | public SpriteFont TextFontStyle; 13 | public GUIAlignment GuiAlignmentStyle; 14 | public TextAlignment TextAlignmentStyle; 15 | public TextAlignment TextButtonAlignmentStyle; 16 | public Vector2 ParentDimensionsStyle; 17 | public Vector2 TextBorderStyle; 18 | 19 | public GUIStyle(Vector2 dimensionsStyle, SpriteFont textFontStyle, Color blockColorStyle, Color textColorStyle, Color sliderColorStyle, GUIAlignment guiAlignmentStyle, TextAlignment textAlignmentStyle, TextAlignment textButtonAlignmentStyle, Vector2 textBorderStyle, Vector2 parentDimensionsStyle) 20 | { 21 | DimensionsStyle = dimensionsStyle; 22 | TextFontStyle = textFontStyle; 23 | BlockColorStyle = blockColorStyle; 24 | TextColorStyle = textColorStyle; 25 | GuiAlignmentStyle = guiAlignmentStyle; 26 | TextAlignmentStyle = textAlignmentStyle; 27 | ParentDimensionsStyle = parentDimensionsStyle; 28 | TextButtonAlignmentStyle = textButtonAlignmentStyle; 29 | TextBorderStyle = textBorderStyle; 30 | SliderColorStyle = sliderColorStyle; 31 | } 32 | 33 | public enum GUIAlignment 34 | { 35 | None, 36 | TopLeft, 37 | TopRight, 38 | BottomLeft, 39 | BottomRight, 40 | Center 41 | } 42 | 43 | public enum TextAlignment 44 | { 45 | Left, Center, Right 46 | } 47 | 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /HelperSuite/GUI/GUITextBlock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Microsoft.Xna.Framework; 4 | using Microsoft.Xna.Framework.Graphics; 5 | 6 | namespace HelperSuite.GUI 7 | { 8 | /// 9 | /// Just a colored block with a text inside 10 | /// 11 | public class GUITextBlock : GUIBlock 12 | { 13 | public Color TextColor; 14 | public SpriteFont TextFont; 15 | 16 | public override Vector2 Dimensions 17 | { 18 | get { return _dimensions; } 19 | set 20 | { 21 | _dimensions = value; 22 | ComputeFontPosition(); 23 | } 24 | } 25 | 26 | public StringBuilder Text 27 | { 28 | get { return _text; } 29 | set 30 | { 31 | _text = value; 32 | ComputeFontPosition(); 33 | } 34 | } 35 | 36 | public GUIStyle.TextAlignment TextAlignment 37 | { 38 | get { return _textAlignment; } 39 | set 40 | { 41 | _textAlignment = value; 42 | ComputeFontPosition(); 43 | } 44 | } 45 | 46 | protected StringBuilder _text; 47 | 48 | protected Vector2 _fontPosition; 49 | public GUIStyle.TextAlignment _textAlignment; 50 | protected Vector2 _textBorder = new Vector2(10,1); 51 | private Vector2 _dimensions; 52 | 53 | public GUITextBlock(GUIStyle guitStyle, String text) : this( 54 | position: Vector2.Zero, 55 | dimensions: guitStyle.DimensionsStyle, 56 | text: text, 57 | font: guitStyle.TextFontStyle, 58 | blockColor: guitStyle.BlockColorStyle, 59 | textColor: guitStyle.TextColorStyle, 60 | textAlignment: guitStyle.TextButtonAlignmentStyle, 61 | textBorder: guitStyle.TextBorderStyle, 62 | layer: 0, 63 | alignment: guitStyle.GuiAlignmentStyle, 64 | parentDimensions: guitStyle.ParentDimensionsStyle) 65 | { } 66 | 67 | /// 68 | /// A default colored block with text on top 69 | /// 70 | public GUITextBlock(Vector2 position, Vector2 dimensions, String text, SpriteFont font, Color blockColor, Color textColor, GUIStyle.TextAlignment textAlignment = GUIStyle.TextAlignment.Left, Vector2 textBorder = default(Vector2), int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 parentDimensions = default(Vector2)) : base(position,dimensions, blockColor, layer, alignment, parentDimensions) 71 | { 72 | _text = new StringBuilder(text); 73 | TextColor = textColor; 74 | TextFont = font; 75 | 76 | _textBorder = textBorder; 77 | 78 | TextAlignment = textAlignment; 79 | } 80 | 81 | protected virtual void FontWrap(ref Vector2 textDimension, Vector2 blockDimensions) 82 | { 83 | float textwidth = textDimension.X; 84 | float characterwidth = textwidth / _text.Length; 85 | int charactersperline = (int)((blockDimensions.X - _textBorder.X * 2) / characterwidth); 86 | 87 | int charactersprocessed = _text.Length; 88 | int lines = 1; 89 | while (charactersperline < charactersprocessed) 90 | { 91 | _text.Insert(charactersperline * lines + lines, '\n'); 92 | charactersprocessed -= charactersperline; 93 | lines++; 94 | } 95 | 96 | if (textDimension.Y * lines + 2 * _textBorder.Y > Dimensions.Y) 97 | { 98 | _dimensions = new Vector2(_dimensions.X, textDimension.Y * lines + 2 * _textBorder.Y); 99 | } 100 | 101 | if(charactersperline<_text.Length) 102 | textDimension = new Vector2(charactersperline * characterwidth, textDimension.Y * lines); 103 | } 104 | 105 | protected virtual void ComputeFontPosition() 106 | { 107 | if (_text == null) return; 108 | Vector2 textDimension = TextFont.MeasureString(_text); 109 | 110 | //Let's check wrap! 111 | 112 | FontWrap(ref textDimension, Dimensions); 113 | 114 | switch (_textAlignment) 115 | { 116 | case GUIStyle.TextAlignment.Left: 117 | _fontPosition = Dimensions * 0.5f * Vector2.UnitY + _textBorder * Vector2.UnitX - textDimension * 0.5f * Vector2.UnitY; 118 | break; 119 | case GUIStyle.TextAlignment.Center: 120 | _fontPosition = Dimensions * 0.5f - textDimension * 0.5f; 121 | break; 122 | case GUIStyle.TextAlignment.Right: 123 | _fontPosition = Dimensions * new Vector2(1, 0.5f) - _textBorder * Vector2.UnitX - textDimension * 0.5f; 124 | break; 125 | default: 126 | throw new ArgumentOutOfRangeException(); 127 | } 128 | } 129 | 130 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 131 | { 132 | guiRenderer.DrawQuad(parentPosition + Position, Dimensions, BlockColor); 133 | guiRenderer.DrawText(parentPosition + Position + _fontPosition, _text, TextFont, TextColor); 134 | } 135 | 136 | } 137 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GUITextBlockButton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using HelperSuite.GUIHelper; 4 | using Microsoft.Xna.Framework; 5 | using Microsoft.Xna.Framework.Graphics; 6 | 7 | namespace HelperSuite.GUI 8 | { 9 | public class GUITextBlockButton : GUITextBlock 10 | { 11 | public bool Toggle; 12 | 13 | private static readonly float ButtonBorder = 2; 14 | 15 | private static readonly Color HoverColor = Color.Tomato; 16 | 17 | private bool _isHovered; 18 | 19 | public MethodInfo ButtonMethod; 20 | public object[] ButtonMethodArgs = null; 21 | public Object ButtonObject; 22 | 23 | public GUITextBlockButton(GUIStyle guitStyle, String text) : this( 24 | position: Vector2.Zero, 25 | dimensions: guitStyle.DimensionsStyle, 26 | text: text, 27 | font: guitStyle.TextFontStyle, 28 | blockColor: guitStyle.BlockColorStyle, 29 | textColor: guitStyle.TextColorStyle, 30 | textAlignment: guitStyle.TextButtonAlignmentStyle, 31 | textBorder: guitStyle.TextBorderStyle, 32 | layer: 0, 33 | alignment: guitStyle.GuiAlignmentStyle, 34 | parentDimensions: guitStyle.ParentDimensionsStyle) 35 | { } 36 | 37 | public GUITextBlockButton(Vector2 position, Vector2 dimensions, String text, SpriteFont font, Color blockColor, Color textColor, GUIStyle.TextAlignment textAlignment = GUIStyle.TextAlignment.Center, Vector2 textBorder = default(Vector2), int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 parentDimensions = default(Vector2)) : base(position, dimensions, text, font, blockColor, textColor, textAlignment, textBorder, layer) 38 | { 39 | 40 | } 41 | 42 | public void SetButtonMethod(Object obj, string method, object[] args = null) 43 | { 44 | ButtonObject = obj; 45 | ButtonObject.GetType().GetMethod(method); 46 | ButtonMethodArgs = args; 47 | } 48 | 49 | 50 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 51 | { 52 | guiRenderer.DrawQuad(parentPosition + Position, Dimensions, Color.DimGray); 53 | guiRenderer.DrawQuad(parentPosition + Position + Vector2.One * ButtonBorder, Dimensions - 2*Vector2.One*ButtonBorder, _isHovered ? HoverColor : BlockColor); 54 | guiRenderer.DrawText(parentPosition + Position + _fontPosition, Text, TextFont, TextColor); 55 | } 56 | 57 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 58 | { 59 | _isHovered = false; 60 | 61 | Vector2 bound1 = Position + parentPosition; 62 | Vector2 bound2 = bound1 + Dimensions; 63 | 64 | if (mousePosition.X >= bound1.X && mousePosition.Y >= bound1.Y && mousePosition.X < bound2.X && 65 | mousePosition.Y < bound2.Y) 66 | { 67 | _isHovered = true; 68 | 69 | if (!GUIControl.WasLMBClicked()) return; 70 | 71 | GUIControl.UIWasUsed = true; 72 | 73 | if (ButtonObject != null) 74 | { 75 | if (ButtonMethod != null) ButtonMethod.Invoke(ButtonObject, ButtonMethodArgs); 76 | } 77 | } 78 | } 79 | 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GUITextBlockToggle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using HelperSuite.GUIHelper; 4 | using Microsoft.Xna.Framework; 5 | using Microsoft.Xna.Framework.Graphics; 6 | 7 | namespace HelperSuite.GUI 8 | { 9 | public class GUITextBlockToggle : GUITextBlock 10 | { 11 | public bool Toggle; 12 | 13 | private const float ToggleIndicatorSize = 20; 14 | private const float ToggleIndicatorBorder = 10; 15 | 16 | public PropertyInfo ToggleProperty; 17 | public FieldInfo ToggleField; 18 | public object ToggleObject; 19 | 20 | public GUITextBlockToggle(GUIStyle guitStyle, String text) : this( 21 | position: Vector2.Zero, 22 | dimensions: guitStyle.DimensionsStyle, 23 | text: text, 24 | font: guitStyle.TextFontStyle, 25 | blockColor: guitStyle.BlockColorStyle, 26 | textColor: guitStyle.TextColorStyle, 27 | textAlignment: guitStyle.TextAlignmentStyle, 28 | textBorder: guitStyle.TextBorderStyle, 29 | layer: 0, 30 | alignment: guitStyle.GuiAlignmentStyle, 31 | parentDimensions: guitStyle.ParentDimensionsStyle) 32 | { } 33 | 34 | public GUITextBlockToggle(Vector2 position, Vector2 dimensions, String text, SpriteFont font, Color blockColor, Color textColor, GUIStyle.TextAlignment textAlignment = GUIStyle.TextAlignment.Left, Vector2 textBorder = default(Vector2), int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 parentDimensions = default(Vector2)) : base(position, dimensions, text, font, blockColor, textColor, textAlignment, textBorder, layer) 35 | { 36 | 37 | } 38 | public void SetField(Object obj, string field) 39 | { 40 | ToggleObject = obj; 41 | ToggleField = obj.GetType().GetField(field); 42 | Toggle = (bool)ToggleField.GetValue(obj); 43 | } 44 | 45 | public void SetProperty(Object obj, string property) 46 | { 47 | ToggleObject = obj; 48 | ToggleProperty = obj.GetType().GetProperty(property); 49 | Toggle = (bool)ToggleProperty.GetValue(obj); 50 | } 51 | 52 | protected override void ComputeFontPosition() 53 | { 54 | if (Text == null) return; 55 | Vector2 textDimensions = TextFont.MeasureString(Text); 56 | 57 | FontWrap(ref textDimensions, Dimensions - Vector2.UnitX * (ToggleIndicatorSize + ToggleIndicatorBorder * 2)); 58 | 59 | switch (TextAlignment) 60 | { 61 | case GUIStyle.TextAlignment.Left: 62 | _fontPosition = (Dimensions - Vector2.UnitX * (ToggleIndicatorSize + ToggleIndicatorBorder * 2)) / 2 * Vector2.UnitY + _textBorder * Vector2.UnitX - textDimensions / 2 * Vector2.UnitY; 63 | break; 64 | case GUIStyle.TextAlignment.Center: 65 | _fontPosition = (Dimensions - Vector2.UnitX * (ToggleIndicatorSize + ToggleIndicatorBorder * 2)) / 2 - textDimensions / 2; 66 | break; 67 | case GUIStyle.TextAlignment.Right: 68 | _fontPosition = (Dimensions - Vector2.UnitX * (ToggleIndicatorSize + ToggleIndicatorBorder * 2)) * new Vector2(1, 0.5f) - _textBorder * Vector2.UnitX - textDimensions / 2; 69 | break; 70 | default: 71 | throw new ArgumentOutOfRangeException(); 72 | } 73 | } 74 | 75 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 76 | { 77 | guiRenderer.DrawQuad(parentPosition + Position, Dimensions, BlockColor); 78 | guiRenderer.DrawQuad(parentPosition + Position + Dimensions * new Vector2(1, 0.5f) - ToggleIndicatorBorder * Vector2.UnitX - ToggleIndicatorSize * new Vector2(1,0.5f) , Vector2.One * ToggleIndicatorSize, Toggle ? Color.LimeGreen : Color.Red); 79 | guiRenderer.DrawText(parentPosition + Position + _fontPosition, Text, TextFont, TextColor); 80 | } 81 | 82 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 83 | { 84 | if (!GUIControl.WasLMBClicked()) return; 85 | 86 | Vector2 bound1 = Position + parentPosition; 87 | Vector2 bound2 = bound1 + Dimensions; 88 | 89 | if (mousePosition.X >= bound1.X && mousePosition.Y >= bound1.Y && mousePosition.X < bound2.X && 90 | mousePosition.Y < bound2.Y) 91 | { 92 | Toggle = !Toggle; 93 | GUIControl.UIWasUsed = true; 94 | 95 | if (ToggleObject != null) 96 | { 97 | if (ToggleField != null) ToggleField.SetValue(ToggleObject, Toggle, BindingFlags.Public, null, null); 98 | if (ToggleProperty != null) ToggleProperty.SetValue(ToggleObject, Toggle); 99 | } 100 | else 101 | { 102 | if (ToggleField != null) ToggleField.SetValue(null, Toggle, BindingFlags.Static | BindingFlags.Public, null, null); 103 | if (ToggleProperty != null) ToggleProperty.SetValue(null, Toggle); 104 | } 105 | 106 | } 107 | } 108 | 109 | } 110 | 111 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GuiDropList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using HelperSuite.GUIHelper; 4 | using Microsoft.Xna.Framework; 5 | using Microsoft.Xna.Framework.Graphics; 6 | 7 | namespace HelperSuite.GUI 8 | { 9 | public class GuiDropList : GUITextBlock 10 | { 11 | public bool Toggle; 12 | 13 | private static readonly float ButtonBorder = 2; 14 | 15 | private static readonly Color HoverColor = Color.LightGray; 16 | 17 | private static readonly int HoverImageWidth = 250; 18 | 19 | private Vector2 _declarationTextDimensions; 20 | 21 | private bool _isHovered; 22 | 23 | private bool _isToggled = false; 24 | 25 | private Vector2 _baseDimensions; 26 | 27 | //Load 28 | private StringBuilder _selectedOptionName = new StringBuilder(100); 29 | 30 | public GuiDropList(GUIStyle style, string text) : this( 31 | position: Vector2.Zero, 32 | dimensions: style.DimensionsStyle, 33 | text: text, 34 | font: style.TextFontStyle, 35 | blockColor: style.BlockColorStyle, 36 | textColor: style.TextColorStyle, 37 | textAlignment: GUIStyle.TextAlignment.Left, 38 | textBorder: style.TextBorderStyle, 39 | layer: 0, 40 | alignment: style.GuiAlignmentStyle, 41 | parentDimensions: style.ParentDimensionsStyle 42 | ) 43 | { 44 | } 45 | 46 | public GuiDropList(Vector2 position, Vector2 dimensions, string text, SpriteFont font, Color blockColor, Color textColor, GUIStyle.TextAlignment textAlignment = GUIStyle.TextAlignment.Center, Vector2 textBorder = default(Vector2), int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 parentDimensions = default(Vector2)) : base(position, dimensions, text, font, blockColor, textColor, textAlignment, textBorder, layer) 47 | { 48 | _selectedOptionName.Append("..."); 49 | 50 | _baseDimensions = Dimensions; 51 | 52 | throw new NotImplementedException(); 53 | } 54 | 55 | protected override void ComputeFontPosition() 56 | { 57 | if (_text == null) return; 58 | _declarationTextDimensions = TextFont.MeasureString(_text); 59 | 60 | //Let's check wrap! 61 | 62 | //FontWrap(ref textDimension, Dimensions); 63 | 64 | _fontPosition = Dimensions * 0.5f * Vector2.UnitY + _textBorder * Vector2.UnitX - _declarationTextDimensions * 0.5f * Vector2.UnitY; 65 | } 66 | 67 | protected void ComputeObjectNameLength() 68 | { 69 | if (_selectedOptionName.Length > 0) 70 | { 71 | //Max length 72 | Vector2 textDimensions = TextFont.MeasureString(_selectedOptionName); 73 | 74 | float characterLength = textDimensions.X/_selectedOptionName.Length; 75 | 76 | Vector2 buttonLeft = (_declarationTextDimensions + _fontPosition * 1.5f) * Vector2.UnitX; 77 | Vector2 spaceAvailable = Dimensions - 2*Vector2.One*ButtonBorder - buttonLeft - 78 | (2 + _textBorder.X)*Vector2.UnitX; 79 | 80 | int characters = (int) (spaceAvailable.X/characterLength); 81 | 82 | _selectedOptionName.Length = characters < _selectedOptionName.Length ? characters : _selectedOptionName.Length; 83 | } 84 | } 85 | 86 | 87 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 88 | { 89 | Vector2 buttonLeft = (_declarationTextDimensions + _fontPosition * 1.2f)*Vector2.UnitX; 90 | guiRenderer.DrawQuad(parentPosition + Position, Dimensions, BlockColor); 91 | guiRenderer.DrawQuad(parentPosition + Position + buttonLeft + Vector2.One * ButtonBorder, Dimensions - 2*Vector2.One*ButtonBorder - buttonLeft - (2+_textBorder.X)*Vector2.UnitX, _isHovered ? HoverColor : Color.DimGray); 92 | 93 | guiRenderer.DrawText(parentPosition + Position + _fontPosition, Text, TextFont, TextColor); 94 | 95 | //Description 96 | guiRenderer.DrawText(parentPosition + Position + buttonLeft + new Vector2(4, _fontPosition.Y), _selectedOptionName, TextFont, TextColor); 97 | 98 | } 99 | 100 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 101 | { 102 | _isHovered = false; 103 | 104 | Vector2 bound1 = Position + parentPosition; 105 | Vector2 bound2 = bound1 + Dimensions; 106 | 107 | if (mousePosition.X >= bound1.X && mousePosition.Y >= bound1.Y && mousePosition.X < bound2.X && 108 | mousePosition.Y < bound2.Y) 109 | { 110 | _isHovered = true; 111 | 112 | if (!GUIControl.WasLMBClicked()) return; 113 | 114 | _isToggled = !_isToggled; 115 | Dimensions = new Vector2(_baseDimensions.X, _baseDimensions.Y + (_isToggled ? 100 : 0)); 116 | 117 | GUIControl.UIWasUsed = true; 118 | } 119 | } 120 | 121 | } 122 | 123 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GuiListToggle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using HelperSuite.GUIHelper; 3 | using Microsoft.Xna.Framework; 4 | 5 | namespace HelperSuite.GUI 6 | { 7 | public class GuiListToggle : GUIList 8 | { 9 | protected static float ToggleButtonHeight = 14; 10 | protected static float ArrowButtonHeight = 8; 11 | 12 | protected static readonly Color HoverColor = Color.Tomato; 13 | public Color ToggleBlockColor = Color.DimGray; 14 | 15 | protected Vector2 _toggleDimensions; 16 | 17 | protected bool _isHovered; 18 | 19 | public bool IsToggled = true; 20 | 21 | public GuiListToggle(Vector2 position, GUIStyle guiStyle) : this( 22 | position: position, 23 | defaultDimensions: guiStyle.DimensionsStyle, 24 | layer: 0, 25 | alignment: guiStyle.GuiAlignmentStyle, 26 | ParentDimensions: guiStyle.ParentDimensionsStyle) 27 | { } 28 | 29 | public GuiListToggle(Vector2 position, Vector2 defaultDimensions, int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 ParentDimensions = new Vector2()) : base(position, defaultDimensions, layer, alignment, ParentDimensions) 30 | { 31 | _toggleDimensions = new Vector2(defaultDimensions.X, ToggleButtonHeight); 32 | } 33 | 34 | public override void AddElement(GUIElement element) 35 | { 36 | // I think it is acceptable to make a for loop everytime an element is added 37 | float height = ToggleButtonHeight; 38 | 39 | for (int i = 0; i < _children.Count; i++) 40 | { 41 | height += _children[i].Dimensions.Y; 42 | } 43 | //element.Position = new Vector2(0, height); 44 | 45 | DefaultDimensions = new Vector2(DefaultDimensions.X, height + element.Dimensions.Y); 46 | Dimensions = DefaultDimensions; 47 | //In Order 48 | _children.Add(element); 49 | } 50 | 51 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 52 | { 53 | if (IsHidden) return; 54 | 55 | if (IsToggled) 56 | { 57 | float height = ToggleButtonHeight; 58 | for (int index = 0; index < _children.Count; index++) 59 | { 60 | GUIElement child = _children[index]; 61 | 62 | if (child.IsHidden) continue; 63 | 64 | child.Update(gameTime, mousePosition, parentPosition + Position + height*Vector2.UnitY); 65 | 66 | height += _children[index].Dimensions.Y; 67 | } 68 | 69 | if (Math.Abs(Dimensions.Y - height) > 0.01f) 70 | Dimensions = new Vector2(Dimensions.X, height); 71 | } 72 | else 73 | { 74 | Dimensions = _toggleDimensions; 75 | } 76 | 77 | _isHovered = false; 78 | 79 | if (GUIControl.UIElementEngaged) return; 80 | 81 | Vector2 bound1 = Position + parentPosition; 82 | Vector2 bound2 = bound1 + _toggleDimensions; 83 | 84 | if (mousePosition.X >= bound1.X && mousePosition.Y >= bound1.Y && mousePosition.X < bound2.X && 85 | mousePosition.Y < bound2.Y) 86 | { 87 | _isHovered = true; 88 | if (GUIControl.WasLMBClicked()) 89 | { 90 | GUIControl.UIWasUsed = true; 91 | 92 | IsToggled = !IsToggled; 93 | } 94 | } 95 | 96 | } 97 | 98 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 99 | { 100 | if (IsHidden) return; 101 | //Draw toggle element 102 | guiRenderer.DrawQuad(parentPosition + Position, _toggleDimensions, _isHovered ? HoverColor : ToggleBlockColor); 103 | 104 | //arrow 105 | if (IsToggled) 106 | { 107 | guiRenderer.DrawQuad( 108 | parentPosition + Position + _toggleDimensions*0.5f - ArrowButtonHeight*Vector2.One*0.5f, 109 | new Vector2(ArrowButtonHeight, ArrowButtonHeight*0.25f), Color.White); 110 | guiRenderer.DrawQuad( 111 | parentPosition + Position + _toggleDimensions*0.5f - ArrowButtonHeight*Vector2.UnitX*0.25f, 112 | new Vector2(ArrowButtonHeight, ArrowButtonHeight*0.5f)*0.5f, Color.White); 113 | } 114 | else 115 | { 116 | guiRenderer.DrawQuad( 117 | parentPosition + Position + _toggleDimensions * 0.5f - ArrowButtonHeight * Vector2.UnitX * 0.5f, 118 | new Vector2(ArrowButtonHeight, ArrowButtonHeight * 0.25f), Color.White); 119 | guiRenderer.DrawQuad( 120 | parentPosition + Position + _toggleDimensions * 0.5f - ArrowButtonHeight * new Vector2(0.25f, 0.5f), 121 | new Vector2(ArrowButtonHeight, ArrowButtonHeight * 0.5f) * 0.5f, Color.White); 122 | } 123 | 124 | if (IsToggled) 125 | { 126 | float height = ToggleButtonHeight; 127 | 128 | for (int index = 0; index < _children.Count; index++) 129 | { 130 | GUIElement child = _children[index]; 131 | child.Draw(guiRenderer, parentPosition + Position + height * Vector2.UnitY, mousePosition); 132 | 133 | height += _children[index].Dimensions.Y; 134 | } 135 | } 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GuiSliderFloat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using HelperSuite.GUIHelper; 4 | using Microsoft.Xna.Framework; 5 | 6 | namespace HelperSuite.GUI 7 | { 8 | /// 9 | /// A slider that can reference float values 10 | /// 11 | public class GuiSliderFloat : GUIBlock 12 | { 13 | protected bool IsEngaged = false; 14 | 15 | protected const float SliderIndicatorSize = 15; 16 | protected const float SliderIndicatorBorder = 10; 17 | protected const float SliderBaseHeight = 5; 18 | 19 | protected float _sliderPercent; 20 | 21 | private float _sliderValue; 22 | public float SliderValue 23 | { 24 | get { return _sliderValue; } 25 | set 26 | { 27 | _sliderValue = value; 28 | _sliderPercent = (_sliderValue - MinValue)/(MaxValue - MinValue); 29 | } 30 | } 31 | 32 | public float MaxValue = 1; 33 | public float MinValue; 34 | 35 | protected Color _sliderColor; 36 | 37 | public PropertyInfo SliderProperty; 38 | public FieldInfo SliderField; 39 | public Object SliderObject; 40 | 41 | public GuiSliderFloat(GUIStyle guiStyle, float min, float max) : this( 42 | position: Vector2.Zero, 43 | dimensions: new Vector2(guiStyle.DimensionsStyle.X, 35), 44 | min: min, 45 | max: max, 46 | blockColor: guiStyle.BlockColorStyle, 47 | sliderColor: guiStyle.SliderColorStyle, 48 | layer: 0, 49 | alignment: guiStyle.GuiAlignmentStyle, 50 | ParentDimensions: guiStyle.ParentDimensionsStyle 51 | ) 52 | { } 53 | 54 | public GuiSliderFloat(Vector2 position, Vector2 dimensions, float min, float max, Color blockColor, Color sliderColor, int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 ParentDimensions = new Vector2()) : base(position, dimensions, blockColor, layer, alignment, ParentDimensions) 55 | { 56 | _sliderColor = sliderColor; 57 | MinValue = min; 58 | MaxValue = max; 59 | _sliderValue = min; 60 | } 61 | 62 | public void SetField(Object obj, string field) 63 | { 64 | SliderObject = obj; 65 | SliderField = obj.GetType().GetField(field); 66 | SliderValue = (float) SliderField.GetValue(obj); 67 | } 68 | 69 | public void SetProperty(Object obj, string property) 70 | { 71 | SliderObject = obj; 72 | SliderProperty = obj.GetType().GetProperty(property); 73 | SliderValue = (float)SliderProperty.GetValue(obj); 74 | } 75 | 76 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 77 | { 78 | if (GUIControl.UIElementEngaged && !IsEngaged) return; 79 | 80 | //Break Engagement 81 | if (IsEngaged && !GUIControl.IsLMBPressed()) 82 | { 83 | GUIControl.UIElementEngaged = false; 84 | IsEngaged = false; 85 | } 86 | 87 | if (!GUIControl.IsLMBPressed()) return; 88 | 89 | Vector2 bound1 = Position + parentPosition /*+ SliderIndicatorBorder*Vector2.UnitX*/; 90 | Vector2 bound2 = bound1 + Dimensions/* - 2*SliderIndicatorBorder * Vector2.UnitX*/; 91 | 92 | if (mousePosition.X >= bound1.X && mousePosition.Y >= bound1.Y && mousePosition.X < bound2.X && 93 | mousePosition.Y < bound2.Y + 1) 94 | { 95 | GUIControl.UIElementEngaged = true; 96 | IsEngaged = true; 97 | } 98 | 99 | if (IsEngaged) 100 | { 101 | GUIControl.UIWasUsed = true; 102 | 103 | float lowerx = bound1.X + SliderIndicatorBorder; 104 | float upperx = bound2.X - SliderIndicatorBorder; 105 | 106 | _sliderPercent = MathHelper.Clamp((mousePosition.X - lowerx)/(upperx - lowerx), 0, 1); 107 | 108 | _sliderValue = _sliderPercent*(MaxValue - MinValue) + MinValue; 109 | 110 | if (SliderObject != null) 111 | { 112 | if (SliderField != null) 113 | SliderField.SetValue(SliderObject, SliderValue, BindingFlags.Public, null, null); 114 | else if (SliderProperty != null) SliderProperty.SetValue(SliderObject, SliderValue); 115 | } 116 | else 117 | { 118 | if (SliderField != null) 119 | SliderField.SetValue(null, SliderValue, BindingFlags.Static | BindingFlags.Public, null, null); 120 | else if (SliderProperty != null) SliderProperty.SetValue(null, SliderValue); 121 | } 122 | } 123 | } 124 | 125 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 126 | { 127 | guiRenderer.DrawQuad(parentPosition + Position, Dimensions, BlockColor); 128 | 129 | Vector2 slideDimensions = new Vector2(Dimensions.X - SliderIndicatorBorder*2, SliderBaseHeight); 130 | guiRenderer.DrawQuad(parentPosition + Position + new Vector2(SliderIndicatorBorder, 131 | Dimensions.Y* 0.5f - SliderBaseHeight * 0.5f), slideDimensions, Color.DarkGray); 132 | 133 | //slideDimensions = new Vector2(slideDimensions.X + SliderIndicatorSize* 0.5f, slideDimensions.Y); 134 | guiRenderer.DrawQuad(parentPosition + Position + new Vector2(SliderIndicatorBorder - SliderIndicatorSize* 0.5f, 135 | Dimensions.Y * 0.5f - SliderIndicatorSize * 0.5f) + _sliderPercent*slideDimensions * Vector2.UnitX, new Vector2(SliderIndicatorSize, SliderIndicatorSize), _sliderColor); 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GuiSliderFloatText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Text; 4 | using HelperSuite.GUIHelper; 5 | using Microsoft.Xna.Framework; 6 | using Microsoft.Xna.Framework.Graphics; 7 | 8 | namespace HelperSuite.GUI 9 | { 10 | public class GuiSliderFloatText : GUIBlock 11 | { 12 | protected bool IsEngaged = false; 13 | 14 | protected const float SliderIndicatorSize = 15; 15 | protected const float SliderIndicatorBorder = 10; 16 | protected const float SliderBaseHeight = 5; 17 | 18 | private Vector2 _tempPosition = Vector2.One; 19 | 20 | protected Vector2 SliderDimensions; 21 | 22 | protected float _sliderPercent; 23 | 24 | private float _sliderValue; 25 | public float SliderValue 26 | { 27 | get { return _sliderValue; } 28 | set 29 | { 30 | _sliderValue = value; 31 | _sliderPercent = (_sliderValue - MinValue)/(MaxValue - MinValue); 32 | UpdateText(); 33 | } 34 | } 35 | 36 | public float MaxValue = 1; 37 | public float MinValue; 38 | 39 | protected Color _sliderColor; 40 | 41 | //TextBlock associated 42 | protected GUITextBlock _textBlock; 43 | private uint roundDecimals = 1; 44 | protected String baseText; 45 | 46 | //Associated reference 47 | public PropertyInfo SliderProperty; 48 | public FieldInfo SliderField; 49 | public Object SliderObject; 50 | 51 | public GuiSliderFloatText(GUIStyle guiStyle, float min, float max, uint decimals, String text) : this( 52 | position: Vector2.Zero, 53 | sliderDimensions: new Vector2(guiStyle.DimensionsStyle.X, 35), 54 | textdimensions: new Vector2(guiStyle.DimensionsStyle.X, 20), 55 | min: min, 56 | max: max, 57 | decimals: decimals, 58 | text: text, 59 | font: guiStyle.TextFontStyle, 60 | textBorder: guiStyle.TextBorderStyle, 61 | textAlignment: GUIStyle.TextAlignment.Left, 62 | blockColor: guiStyle.BlockColorStyle, 63 | sliderColor: guiStyle.SliderColorStyle, 64 | layer: 0, 65 | alignment: guiStyle.GuiAlignmentStyle, 66 | ParentDimensions: guiStyle.ParentDimensionsStyle 67 | ) 68 | { } 69 | 70 | public GuiSliderFloatText(Vector2 position, Vector2 sliderDimensions, Vector2 textdimensions, float min, float max, uint decimals, String text, SpriteFont font, Color blockColor, Color sliderColor, int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, GUIStyle.TextAlignment textAlignment = GUIStyle.TextAlignment.Left, Vector2 textBorder = default(Vector2), Vector2 ParentDimensions = new Vector2()) : base(position, sliderDimensions, blockColor, layer, alignment, ParentDimensions) 71 | { 72 | _textBlock = new GUITextBlock(position, textdimensions, text, font, blockColor, sliderColor, textAlignment, textBorder, layer, alignment, ParentDimensions); 73 | 74 | Dimensions = sliderDimensions + _textBlock.Dimensions*Vector2.UnitY; 75 | SliderDimensions = sliderDimensions; 76 | _sliderColor = sliderColor; 77 | MinValue = min; 78 | MaxValue = max; 79 | _sliderValue = min; 80 | roundDecimals = decimals; 81 | baseText = text; 82 | 83 | UpdateText(); 84 | } 85 | 86 | public void SetText(StringBuilder text) 87 | { 88 | baseText = text.ToString(); 89 | _textBlock.Text = text; 90 | UpdateText(); 91 | } 92 | 93 | public void SetField(Object obj, string field) 94 | { 95 | SliderObject = obj; 96 | SliderField = obj.GetType().GetField(field); 97 | SliderProperty = null; 98 | SliderValue = (float)SliderField.GetValue(obj); 99 | } 100 | 101 | public void SetProperty(Object obj, string property) 102 | { 103 | SliderObject = obj; 104 | SliderProperty = obj.GetType().GetProperty(property); 105 | SliderField = null; 106 | SliderValue = (float)SliderProperty.GetValue(obj); 107 | } 108 | 109 | public void SetValues(string text, float minValue, float maxValue, uint decimals) 110 | { 111 | SetText(new StringBuilder(text)); 112 | MinValue = minValue; 113 | MaxValue = maxValue; 114 | roundDecimals = decimals; 115 | } 116 | 117 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 118 | { 119 | if (GUIControl.UIElementEngaged && !IsEngaged) return; 120 | 121 | //Break Engagement 122 | if (IsEngaged && !GUIControl.IsLMBPressed()) 123 | { 124 | GUIControl.UIElementEngaged = false; 125 | IsEngaged = false; 126 | } 127 | 128 | if (!GUIControl.IsLMBPressed()) return; 129 | 130 | Vector2 bound1 = Position + parentPosition + _textBlock.Dimensions * Vector2.UnitY /*+ SliderIndicatorBorder*Vector2.UnitX*/; 131 | Vector2 bound2 = bound1 + SliderDimensions/* - 2*SliderIndicatorBorder * Vector2.UnitX*/; 132 | 133 | if (mousePosition.X >= bound1.X && mousePosition.Y >= bound1.Y && mousePosition.X < bound2.X && 134 | mousePosition.Y < bound2.Y + 1) 135 | { 136 | GUIControl.UIElementEngaged = true; 137 | IsEngaged = true; 138 | } 139 | 140 | if (IsEngaged) 141 | { 142 | GUIControl.UIWasUsed = true; 143 | 144 | float lowerx = bound1.X + SliderIndicatorBorder; 145 | float upperx = bound2.X - SliderIndicatorBorder; 146 | 147 | _sliderPercent = MathHelper.Clamp((mousePosition.X - lowerx)/(upperx - lowerx), 0, 1); 148 | 149 | _sliderValue = _sliderPercent*(MaxValue - MinValue) + MinValue; 150 | 151 | UpdateText(); 152 | 153 | if (SliderObject != null) 154 | { 155 | if (SliderField != null) 156 | SliderField.SetValue(SliderObject, SliderValue, BindingFlags.Public, null, null); 157 | else if (SliderProperty != null) SliderProperty.SetValue(SliderObject, SliderValue); 158 | } 159 | else 160 | { 161 | if (SliderField != null) 162 | SliderField.SetValue(null, SliderValue, BindingFlags.Static | BindingFlags.Public, null, null); 163 | else if (SliderProperty != null) SliderProperty.SetValue(null, SliderValue); 164 | } 165 | } 166 | } 167 | 168 | private void UpdateText() 169 | { 170 | _textBlock.Text.Clear(); 171 | _textBlock.Text.Append(baseText); 172 | _textBlock.Text.Concat(_sliderValue, roundDecimals); 173 | } 174 | 175 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 176 | { 177 | _textBlock.Draw(guiRenderer, parentPosition, mousePosition); 178 | 179 | _tempPosition = parentPosition + Position + _textBlock.Dimensions*Vector2.UnitY; 180 | guiRenderer.DrawQuad(_tempPosition, SliderDimensions, BlockColor); 181 | 182 | Vector2 slideDimensions = new Vector2(SliderDimensions.X - SliderIndicatorBorder*2, SliderBaseHeight); 183 | guiRenderer.DrawQuad(_tempPosition + new Vector2(SliderIndicatorBorder, 184 | SliderDimensions.Y* 0.5f - SliderBaseHeight * 0.5f), slideDimensions, Color.DarkGray); 185 | 186 | //slideDimensions = new Vector2(slideDimensions.X + SliderIndicatorSize* 0.5f, slideDimensions.Y); 187 | guiRenderer.DrawQuad(_tempPosition + new Vector2(SliderIndicatorBorder - SliderIndicatorSize* 0.5f, 188 | SliderDimensions.Y * 0.5f - SliderIndicatorSize * 0.5f) + _sliderPercent*slideDimensions * Vector2.UnitX, new Vector2(SliderIndicatorSize, SliderIndicatorSize), _sliderColor); 189 | } 190 | } 191 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GuiSliderInt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using HelperSuite.GUIHelper; 4 | using Microsoft.Xna.Framework; 5 | 6 | namespace HelperSuite.GUI 7 | { 8 | public class GuiSliderInt : GuiSliderFloat 9 | { 10 | public int MaxValueInt = 1; 11 | public int MinValueInt = 0; 12 | public int StepSize = 1; 13 | 14 | public int _sliderValue; 15 | public int SliderValue 16 | { 17 | get { return _sliderValue; } 18 | set 19 | { 20 | _sliderValue = value; 21 | _sliderPercent = (_sliderValue - MinValue) / (MaxValue - MinValue); 22 | } 23 | } 24 | 25 | public GuiSliderInt(GUIStyle guiStyle, int min, int max, int stepSize) : this( 26 | position: Vector2.Zero, 27 | dimensions: new Vector2(guiStyle.DimensionsStyle.X, 35), 28 | min: min, 29 | max: max, 30 | stepSize: stepSize, 31 | blockColor: guiStyle.BlockColorStyle, 32 | sliderColor: guiStyle.SliderColorStyle, 33 | layer: 0, 34 | alignment: guiStyle.GuiAlignmentStyle, 35 | ParentDimensions: guiStyle.ParentDimensionsStyle 36 | ) 37 | { } 38 | 39 | public GuiSliderInt(Vector2 position, Vector2 dimensions, int min, int max, int stepSize, Color blockColor, Color sliderColor, int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 ParentDimensions = new Vector2()) : base(position, dimensions, min, max, blockColor, sliderColor, layer, alignment, ParentDimensions) 40 | { 41 | MaxValueInt = max; 42 | MinValueInt = min; 43 | StepSize = stepSize; 44 | } 45 | 46 | public void SetField(Object obj, string field) 47 | { 48 | SliderObject = obj; 49 | SliderField = obj.GetType().GetField(field); 50 | SliderValue = (int)SliderField.GetValue(obj); 51 | } 52 | 53 | public void SetProperty(Object obj, string property) 54 | { 55 | SliderObject = obj; 56 | SliderProperty = obj.GetType().GetProperty(property); 57 | SliderValue = (int)SliderProperty.GetValue(obj); 58 | } 59 | 60 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 61 | { 62 | if (GUIControl.UIElementEngaged && !IsEngaged) return; 63 | 64 | //Break Engagement 65 | if (IsEngaged && !GUIControl.IsLMBPressed()) 66 | { 67 | GUIControl.UIElementEngaged = false; 68 | IsEngaged = false; 69 | } 70 | 71 | if (!GUIControl.IsLMBPressed()) return; 72 | 73 | Vector2 bound1 = Position + parentPosition /*+ SliderIndicatorBorder*Vector2.UnitX*/; 74 | Vector2 bound2 = bound1 + Dimensions/* - 2*SliderIndicatorBorder * Vector2.UnitX*/; 75 | 76 | if (mousePosition.X >= bound1.X && mousePosition.Y >= bound1.Y && mousePosition.X < bound2.X && 77 | mousePosition.Y < bound2.Y + 1) 78 | { 79 | GUIControl.UIElementEngaged = true; 80 | IsEngaged = true; 81 | } 82 | 83 | if (IsEngaged) 84 | { 85 | GUIControl.UIWasUsed = true; 86 | 87 | float lowerx = bound1.X + SliderIndicatorBorder; 88 | float upperx = bound2.X - SliderIndicatorBorder; 89 | 90 | _sliderPercent = MathHelper.Clamp((mousePosition.X - lowerx) / (upperx - lowerx), 0, 1); 91 | 92 | _sliderValue = (int) Math.Round(_sliderPercent * (float)(MaxValue - MinValue) + MinValue) / StepSize * StepSize; 93 | 94 | _sliderPercent = (float)(_sliderValue - MinValueInt)/( MaxValueInt - MinValueInt); 95 | 96 | if (SliderObject != null) 97 | { 98 | if (SliderField != null) SliderField.SetValue(SliderObject, SliderValue, BindingFlags.Public, null, null); 99 | else if (SliderProperty != null) SliderProperty.SetValue(SliderObject, SliderValue); 100 | } 101 | else 102 | { 103 | if (SliderField != null) SliderField.SetValue(null, SliderValue, BindingFlags.Static | BindingFlags.Public, null, null); 104 | else if (SliderProperty != null) SliderProperty.SetValue(null, SliderValue); 105 | } 106 | } 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GuiSliderIntText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Text; 4 | using HelperSuite.GUIHelper; 5 | using Microsoft.Xna.Framework; 6 | using Microsoft.Xna.Framework.Graphics; 7 | 8 | namespace HelperSuite.GUI 9 | { 10 | public class GuiSliderIntText : GuiSliderFloatText 11 | { 12 | public int MaxValueInt = 1; 13 | public int MinValueInt = 0; 14 | public int StepSize = 1; 15 | 16 | public int _sliderValue; 17 | public int SliderValue 18 | { 19 | get { return _sliderValue; } 20 | set 21 | { 22 | _sliderValue = value; 23 | _sliderPercent = (float)(_sliderValue - MinValue) / (MaxValue - MinValue); 24 | 25 | UpdateText(); 26 | } 27 | } 28 | 29 | private void UpdateText() 30 | { 31 | _textBlock.Text.Clear(); 32 | _textBlock.Text.Append(baseText); 33 | _textBlock.Text.Concat(_sliderValue); 34 | } 35 | 36 | public GuiSliderIntText(GUIStyle guiStyle, int min, int max, int stepSize, String text) : this( 37 | position: Vector2.Zero, 38 | sliderDimensions: new Vector2(guiStyle.DimensionsStyle.X, 35), 39 | textdimensions: new Vector2(guiStyle.DimensionsStyle.X, 20), 40 | min: min, 41 | max: max, 42 | stepSize: stepSize, 43 | text: text, 44 | font: guiStyle.TextFontStyle, 45 | textBorder: guiStyle.TextBorderStyle, 46 | textAlignment: GUIStyle.TextAlignment.Left, 47 | blockColor: guiStyle.BlockColorStyle, 48 | sliderColor: guiStyle.SliderColorStyle, 49 | layer: 0, 50 | alignment: guiStyle.GuiAlignmentStyle, 51 | ParentDimensions: guiStyle.ParentDimensionsStyle 52 | ) 53 | { } 54 | 55 | public GuiSliderIntText(Vector2 position, Vector2 sliderDimensions, Vector2 textdimensions, int min, int max, int stepSize, String text, SpriteFont font, Color blockColor, Color sliderColor, int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, GUIStyle.TextAlignment textAlignment = GUIStyle.TextAlignment.Left, Vector2 textBorder = default(Vector2), Vector2 ParentDimensions = new Vector2()) : base(position, sliderDimensions, textdimensions, min, max, 0, text, font, blockColor, sliderColor, layer, alignment, textAlignment, textBorder, ParentDimensions) 56 | { 57 | MaxValueInt = max; 58 | MinValueInt = min; 59 | StepSize = stepSize; 60 | } 61 | 62 | public new void SetField(Object obj, string field) 63 | { 64 | SliderObject = obj; 65 | SliderField = obj.GetType().GetField(field); 66 | SliderValue = (int)SliderField.GetValue(obj); 67 | } 68 | 69 | public void SetValues(string text, int minValue, int maxValue, int stepSize) 70 | { 71 | SetText(new StringBuilder(text)); 72 | MinValueInt = minValue; 73 | MaxValueInt = maxValue; 74 | MinValue = minValue; 75 | MaxValue = maxValue; 76 | StepSize = stepSize; 77 | } 78 | 79 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 80 | { 81 | if (GUIControl.UIElementEngaged && !IsEngaged) return; 82 | 83 | //Break Engagement 84 | if (IsEngaged && !GUIControl.IsLMBPressed()) 85 | { 86 | GUIControl.UIElementEngaged = false; 87 | IsEngaged = false; 88 | } 89 | 90 | if (!GUIControl.IsLMBPressed()) return; 91 | 92 | Vector2 bound1 = Position + parentPosition + _textBlock.Dimensions * Vector2.UnitY /*+ SliderIndicatorBorder*Vector2.UnitX*/; 93 | Vector2 bound2 = bound1 + SliderDimensions/* - 2*SliderIndicatorBorder * Vector2.UnitX*/; 94 | 95 | if (mousePosition.X >= bound1.X && mousePosition.Y >= bound1.Y && mousePosition.X < bound2.X && 96 | mousePosition.Y < bound2.Y + 1) 97 | { 98 | GUIControl.UIElementEngaged = true; 99 | IsEngaged = true; 100 | } 101 | 102 | if (IsEngaged) 103 | { 104 | GUIControl.UIWasUsed = true; 105 | 106 | float lowerx = bound1.X + SliderIndicatorBorder; 107 | float upperx = bound2.X - SliderIndicatorBorder; 108 | 109 | _sliderPercent = MathHelper.Clamp((mousePosition.X - lowerx) / (upperx - lowerx), 0, 1); 110 | 111 | _sliderValue = (int)Math.Round(_sliderPercent * (MaxValue - MinValue) + MinValue) / StepSize * StepSize; 112 | 113 | UpdateText(); 114 | 115 | _sliderPercent = (float)(_sliderValue - MinValueInt) / (MaxValueInt - MinValueInt); 116 | 117 | if (SliderObject != null) 118 | { 119 | if (SliderField != null) SliderField.SetValue(SliderObject, SliderValue, BindingFlags.Public, null, null); 120 | else if (SliderProperty != null) SliderProperty.SetValue(SliderObject, SliderValue); 121 | } 122 | else 123 | { 124 | if (SliderField != null) SliderField.SetValue(null, SliderValue, BindingFlags.Static | BindingFlags.Public, null, null); 125 | else if (SliderProperty != null) SliderProperty.SetValue(null, SliderValue); 126 | } 127 | } 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /HelperSuite/GUI/GuiTextBlockLoadDialog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using HelperSuite.GUIHelper; 6 | using Microsoft.Xna.Framework; 7 | using Microsoft.Xna.Framework.Graphics; 8 | 9 | namespace HelperSuite.GUI 10 | { 11 | public class GuiTextBlockLoadDialog : GUITextBlock 12 | { 13 | public bool Toggle; 14 | 15 | private static readonly float ButtonBorder = 2; 16 | 17 | private static readonly Color HoverColor = Color.LightGray; 18 | 19 | private static readonly int HoverImageWidth = 250; 20 | 21 | private Vector2 _declarationTextDimensions; 22 | 23 | private bool _isHovered; 24 | 25 | private short _isLoaded; //0 -> 1 -> 2 26 | 27 | //Load 28 | private Task _loadTaskReference; 29 | public object LoadedObject; 30 | private int _loadedObjectPointer = -1; 31 | private StringBuilder _loadedObjectName = new StringBuilder(100); 32 | private StringBuilder _loadingStringBuilder = new StringBuilder("loading..."); 33 | 34 | public MethodInfo LoaderMethod; 35 | public GUIContentLoader GUILoader; 36 | 37 | public enum ContentType 38 | { 39 | Texture2D 40 | }; 41 | 42 | public GuiTextBlockLoadDialog(GUIStyle style, string text, GUIContentLoader contentLoader, ContentType contentType) : this( 43 | position: Vector2.Zero, 44 | dimensions: style.DimensionsStyle, 45 | text: text, 46 | guiContentLoader: contentLoader, 47 | contentType: contentType, 48 | font: style.TextFontStyle, 49 | blockColor: style.BlockColorStyle, 50 | textColor: style.TextColorStyle, 51 | textAlignment: GUIStyle.TextAlignment.Left, 52 | textBorder: style.TextBorderStyle, 53 | layer: 0, 54 | alignment: style.GuiAlignmentStyle, 55 | parentDimensions: style.ParentDimensionsStyle 56 | ) 57 | { 58 | } 59 | public GuiTextBlockLoadDialog(Vector2 position, Vector2 dimensions, string text, GUIContentLoader guiContentLoader, ContentType contentType, SpriteFont font, Color blockColor, Color textColor, GUIStyle.TextAlignment textAlignment = GUIStyle.TextAlignment.Center, Vector2 textBorder = default(Vector2), int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 parentDimensions = default(Vector2)) : base(position, dimensions, text, font, blockColor, textColor, textAlignment, textBorder, layer) 60 | { 61 | _loadedObjectName.Append("..."); 62 | 63 | //Initialize the loader and the kind of content we want to retrieve 64 | 65 | GUILoader = guiContentLoader; 66 | 67 | Type type = null; 68 | switch (contentType) 69 | { 70 | case ContentType.Texture2D: 71 | type = typeof(Texture2D); 72 | break; 73 | } 74 | 75 | LoaderMethod = GUILoader.GetType().GetMethod("LoadContentFile").MakeGenericMethod(type); 76 | } 77 | 78 | protected override void ComputeFontPosition() 79 | { 80 | if (_text == null) return; 81 | _declarationTextDimensions = TextFont.MeasureString(_text); 82 | 83 | //Let's check wrap! 84 | 85 | //FontWrap(ref textDimension, Dimensions); 86 | 87 | _fontPosition = Dimensions * 0.5f * Vector2.UnitY + _textBorder * Vector2.UnitX - _declarationTextDimensions * 0.5f * Vector2.UnitY; 88 | } 89 | 90 | protected void ComputeObjectNameLength() 91 | { 92 | if (_loadedObjectName.Length > 0) 93 | { 94 | //Max length 95 | Vector2 textDimensions = TextFont.MeasureString(_loadedObjectName); 96 | 97 | float characterLength = textDimensions.X/_loadedObjectName.Length; 98 | 99 | Vector2 buttonLeft = (_declarationTextDimensions + _fontPosition * 1.5f) * Vector2.UnitX; 100 | Vector2 spaceAvailable = Dimensions - 2*Vector2.One*ButtonBorder - buttonLeft - 101 | (2 + _textBorder.X)*Vector2.UnitX; 102 | 103 | int characters = (int) (spaceAvailable.X/characterLength); 104 | 105 | _loadedObjectName.Length = characters < _loadedObjectName.Length ? characters : _loadedObjectName.Length; 106 | } 107 | } 108 | 109 | 110 | public override void Draw(GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 111 | { 112 | Vector2 buttonLeft = (_declarationTextDimensions + _fontPosition * 1.2f)*Vector2.UnitX; 113 | guiRenderer.DrawQuad(parentPosition + Position, Dimensions, BlockColor); 114 | guiRenderer.DrawQuad(parentPosition + Position + buttonLeft + Vector2.One * ButtonBorder, Dimensions - 2*Vector2.One*ButtonBorder - buttonLeft - (2+_textBorder.X)*Vector2.UnitX, _isHovered ? HoverColor : Color.DimGray); 115 | 116 | Vector2 indicatorButton = parentPosition + new Vector2(Dimensions.X - (2 + _textBorder.X), Dimensions.Y/2 - 4); 117 | 118 | guiRenderer.DrawQuad(indicatorButton, Vector2.One * 8, _isLoaded < 1 ? Color.Red : (_isLoaded < 2 ? Color.Yellow : Color.LimeGreen )); 119 | 120 | guiRenderer.DrawText(parentPosition + Position + _fontPosition, Text, TextFont, TextColor); 121 | 122 | //Description 123 | guiRenderer.DrawText(parentPosition + Position + buttonLeft + new Vector2(4, _fontPosition.Y), _isLoaded == 1 ? _loadingStringBuilder : _loadedObjectName, TextFont, TextColor); 124 | 125 | //Show texture if _isHovered 126 | if (_isLoaded == 2) 127 | { 128 | LoadedObject = GUILoader.ContentArray[_loadedObjectPointer]; 129 | 130 | if (_isHovered) 131 | { 132 | //compute position 133 | 134 | Vector2 position = mousePosition; 135 | 136 | float overborder = position.X + HoverImageWidth - GUIControl.ScreenWidth; 137 | 138 | if (overborder > 0) 139 | position.X -= overborder; 140 | 141 | 142 | if (LoadedObject != null && LoadedObject.GetType() == typeof(Texture2D)) 143 | { 144 | Texture2D image = (Texture2D) LoadedObject; 145 | float height = (float) image.Height/image.Width*HoverImageWidth; 146 | guiRenderer.DrawImage(position, new Vector2(HoverImageWidth, height), 147 | image, Color.White, true); 148 | } 149 | } 150 | } 151 | 152 | } 153 | 154 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 155 | { 156 | if (_loadTaskReference != null) 157 | { 158 | _isLoaded = (short) (_loadTaskReference.IsCompleted ? 2 : 1); 159 | 160 | if (_isLoaded == 2) 161 | { 162 | if (_loadTaskReference.IsFaulted) 163 | { 164 | _isLoaded = 0; 165 | _loadedObjectName.Clear(); 166 | _loadedObjectName.Append("Loading failed"); 167 | } 168 | 169 | 170 | } 171 | } 172 | else 173 | { 174 | _isLoaded = 0; 175 | } 176 | 177 | _isHovered = false; 178 | 179 | Vector2 bound1 = Position + parentPosition; 180 | Vector2 bound2 = bound1 + Dimensions; 181 | 182 | if (mousePosition.X >= bound1.X && mousePosition.Y >= bound1.Y && mousePosition.X < bound2.X && 183 | mousePosition.Y < bound2.Y) 184 | { 185 | _isHovered = true; 186 | 187 | if (!GUIControl.WasLMBClicked()) return; 188 | 189 | GUIControl.UIWasUsed = true; 190 | 191 | if (GUILoader != null) 192 | { 193 | object[] args = {_loadTaskReference, _loadedObjectPointer, null}; 194 | if (LoaderMethod != null) LoaderMethod.Invoke(GUILoader, args); 195 | 196 | _loadTaskReference = (Task) args[0]; 197 | _loadedObjectPointer = (int) args[1]; 198 | _loadedObjectName.Clear(); 199 | _loadedObjectName.Append((string)args[2]); 200 | 201 | ComputeObjectNameLength(); 202 | } 203 | } 204 | } 205 | 206 | } 207 | 208 | } -------------------------------------------------------------------------------- /HelperSuite/GUIHelper/GUIControl.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Input; 3 | 4 | namespace HelperSuite.GUIHelper 5 | { 6 | public static class GUIControl 7 | { 8 | 9 | //UIWasUsed needs to be resettet each updated period to false. 10 | //It is useful for other parts of the program so they know they are obscured by UI and don't trigger actions. 11 | public static bool UIElementEngaged = false; 12 | public static bool UIWasUsed = false; 13 | 14 | public static MouseState LastMouseState; 15 | public static MouseState CurrentMouseState; 16 | private static Vector2 mousePosition = Vector2.Zero; 17 | public static int ScreenWidth; 18 | public static int ScreenHeight; 19 | 20 | public static void Initialize(int width, int height) 21 | { 22 | ScreenWidth = width; 23 | ScreenHeight = height; 24 | } 25 | 26 | public static void Update(MouseState lastMouseState, MouseState currentMouseState) 27 | { 28 | UIWasUsed = false; 29 | 30 | LastMouseState = lastMouseState; 31 | CurrentMouseState = currentMouseState; 32 | 33 | mousePosition.X = CurrentMouseState.X; 34 | mousePosition.Y = CurrentMouseState.Y; 35 | } 36 | 37 | public static void UpdateResolution(int width, int height) 38 | { 39 | ScreenWidth = width; 40 | ScreenHeight = height; 41 | } 42 | 43 | public static bool IsLMBPressed() 44 | { 45 | return CurrentMouseState.LeftButton == ButtonState.Pressed; 46 | } 47 | public static bool WasLMBClicked() 48 | { 49 | return CurrentMouseState.LeftButton == ButtonState.Pressed && 50 | LastMouseState.LeftButton == ButtonState.Released; 51 | } 52 | 53 | public static Vector2 GetMousePosition() 54 | { 55 | return mousePosition; 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /HelperSuite/GUIRenderer/GUIRenderer.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using HelperSuite.GUI; 3 | using HelperSuite.GUIHelper; 4 | using Microsoft.Xna.Framework; 5 | using Microsoft.Xna.Framework.Content; 6 | using Microsoft.Xna.Framework.Graphics; 7 | 8 | namespace HelperSuite.GUIRenderer 9 | { 10 | public class GUIRenderer 11 | { 12 | private GraphicsDevice _graphicsDevice; 13 | private SpriteBatch _spriteBatch; 14 | 15 | public Vector2 Resolution; 16 | 17 | private Texture2D _plainWhite; 18 | private Texture2D _colorPickerBig; 19 | private Texture2D _colorPickerSmall; 20 | public static SpriteFont MonospaceFont; 21 | 22 | private int _foregroundIndex; 23 | private ForegroundImage[] foregroundImages = new ForegroundImage[10]; 24 | 25 | public struct ForegroundImage 26 | { 27 | public Texture2D tex; 28 | public Vector2 pos; 29 | public Vector2 dim; 30 | public Color color; 31 | } 32 | 33 | public void Initialize(GraphicsDevice graphicsDevice, int width, int height) 34 | { 35 | _foregroundIndex = 0; 36 | 37 | _graphicsDevice = graphicsDevice; 38 | _spriteBatch = new SpriteBatch(graphicsDevice); 39 | 40 | Resolution = new Vector2(width, height); 41 | 42 | _plainWhite = new Texture2D(graphicsDevice, 1,1); 43 | _plainWhite.SetData(new[] { Color.White }); 44 | } 45 | 46 | public void Load(ContentManager content) 47 | { 48 | MonospaceFont = content.Load("Fonts/monospace"); 49 | 50 | _colorPickerSmall = content.Load("Graphical User Interface/colorpickersmall"); 51 | _colorPickerBig = content.Load("Graphical User Interface/colorpickerBig"); 52 | 53 | } 54 | 55 | public void Draw(GUICanvas canvas) 56 | { 57 | //if (!GameSettings.ui_DrawUI) return; 58 | 59 | _foregroundIndex = 0; 60 | //_graphicsDevice.SetRenderTarget(null); 61 | _graphicsDevice.RasterizerState = RasterizerState.CullNone; 62 | 63 | _spriteBatch.Begin(); 64 | canvas.Draw(this, Vector2.Zero, GUIControl.GetMousePosition()); 65 | 66 | //Now draw foregroundImages 67 | for (int index = 0; index <= _foregroundIndex-1; index++) 68 | { 69 | ForegroundImage image = foregroundImages[index]; 70 | DrawImage(image.pos, image.dim, image.tex, image.color, false); 71 | } 72 | _spriteBatch.End(); 73 | } 74 | 75 | public void DrawQuad(Vector2 pos, Vector2 dim, Color color) 76 | { 77 | _spriteBatch.Draw(_plainWhite, RectangleFromVectors(pos, dim), color); 78 | } 79 | 80 | public void DrawColorQuad(Vector2 pos, Vector2 dim, Color color) 81 | { 82 | _spriteBatch.Draw(_colorPickerSmall, RectangleFromVectors(pos, dim), color); 83 | //Vector2 resolution = new Vector2(GameSettings.g_ScreenWidth, GameSettings.g_ScreenHeight); 84 | //Vector2 ssPosition = pos/resolution * 2 - Vector2.One; 85 | //ssPosition.Y = -ssPosition.Y; 86 | //Vector2 ssEndPos = (pos+dim) / resolution * 2 - Vector2.One; 87 | //ssEndPos.Y = -ssEndPos.Y; 88 | //_guiEffect.CurrentTechnique.Passes[0].Apply(); 89 | //_quadRenderer.RenderQuad(_graphicsDevice, ssPosition, ssEndPos); 90 | } 91 | public void DrawColorQuad2(Vector2 pos, Vector2 dim, Color color) 92 | { 93 | _spriteBatch.Draw(_colorPickerBig, RectangleFromVectors(pos, dim), color); 94 | } 95 | 96 | public void DrawImage(Vector2 pos, Vector2 dim, Texture2D tex, Color color, bool drawLater) 97 | { 98 | if (!drawLater) 99 | { 100 | _spriteBatch.Draw(tex, RectangleFromVectors(pos, dim), color); 101 | } 102 | else 103 | { 104 | foregroundImages[_foregroundIndex].color = color; 105 | foregroundImages[_foregroundIndex].dim = dim; 106 | foregroundImages[_foregroundIndex].pos = pos; 107 | foregroundImages[_foregroundIndex].tex = tex; 108 | 109 | _foregroundIndex++; 110 | } 111 | } 112 | 113 | 114 | private Rectangle RectangleFromVectors(Vector2 pos, Vector2 dim) 115 | { 116 | return new Rectangle((int) pos.X, (int) pos.Y, (int) dim.X, (int) dim.Y); 117 | } 118 | 119 | public void DrawText(Vector2 position, StringBuilder text, SpriteFont textFont, Color textColor) 120 | { 121 | _spriteBatch.DrawString(textFont, text, new Vector2((int)position.X, (int)position.Y), textColor); 122 | } 123 | 124 | public void CalculateCoordinates(float x, float y, float w, float h, Vector2 resolution, out Vector2 v1, out Vector2 v2) 125 | { 126 | v1 = new Vector2(x, y) / resolution; 127 | v2 = new Vector2(x + w, y + h) / resolution; 128 | 129 | //Transform into VPS 130 | v1 = v1 * 2 - Vector2.One; 131 | v1.Y = -v1.Y; 132 | 133 | v2 = v2 * 2 - Vector2.One; 134 | v2.Y = -v2.Y; 135 | } 136 | 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /HelperSuite/HelperSuite.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {BBE5A22C-4774-4066-A51C-D689B1E8A2E6} 9 | Library 10 | Properties 11 | HelperSuite 12 | HelperSuite 13 | v4.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | true 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | $(MSBuildExtensionsPath)\MonoGame\v3.0\Tools\MonoGame.Framework.dll 38 | 39 | 40 | $(MSBuildExtensionsPath)\MonoGame\v3.0\Tools\MonoGame.Framework.Content.Pipeline.dll 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 80 | -------------------------------------------------------------------------------- /HelperSuite/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("HelperSuite")] 8 | [assembly: AssemblyProduct("HelperSuite")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyCopyright("Copyright © 2017")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("58e65e27-5d11-435c-9b8f-0876bf5bd231")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /MGSkinnedAnimationAux/AnimationClip.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.Xna.Framework; 3 | 4 | namespace MGSkinnedAnimationAux 5 | { 6 | /// 7 | /// An animation clip is a set of keyframes with associated bones. 8 | /// 9 | public class AnimationClip 10 | { 11 | #region Keyframe and Bone nested class 12 | 13 | /// 14 | /// An Keyframe is a rotation and translation for a moment in time. 15 | /// It would be easy to extend this to include scaling as well. 16 | /// 17 | public class Keyframe 18 | { 19 | public double Time; // The keyframe time 20 | public Quaternion Rotation; // The rotation for the bone 21 | public Vector3 Translation; // The translation for the bone 22 | 23 | public Matrix Transform 24 | { 25 | get 26 | { 27 | return Matrix.CreateFromQuaternion(Rotation) * Matrix.CreateTranslation(Translation); 28 | } 29 | set 30 | { 31 | Matrix transform = value; 32 | transform.Right = Vector3.Normalize(transform.Right); 33 | transform.Up = Vector3.Normalize(transform.Up); 34 | transform.Backward = Vector3.Normalize(transform.Backward); 35 | Rotation = Quaternion.CreateFromRotationMatrix(transform); 36 | Translation = transform.Translation; 37 | } 38 | } 39 | } 40 | 41 | /// 42 | /// Keyframes are grouped per bone for an animation clip 43 | /// 44 | public class Bone 45 | { 46 | /// 47 | /// Each bone has a name so we can associate it with a runtime model 48 | /// 49 | private string name = ""; 50 | 51 | /// 52 | /// The keyframes for this bone 53 | /// 54 | private List keyframes = new List(); 55 | 56 | /// 57 | /// The bone name for these keyframes 58 | /// 59 | public string Name { get { return name; } set { name = value; } } 60 | 61 | /// 62 | /// The keyframes for this bone 63 | /// 64 | public List Keyframes { get { return keyframes; } } 65 | } 66 | 67 | #endregion 68 | 69 | /// 70 | /// The bones for this animation 71 | /// 72 | private List bones = new List(); 73 | 74 | /// 75 | /// Name of the animation clip 76 | /// 77 | public string Name; 78 | 79 | /// 80 | /// Duration of the animation clip 81 | /// 82 | public double Duration; 83 | 84 | /// 85 | /// The bones for this animation clip with their keyframes 86 | /// 87 | public List Bones { get { return bones; } } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /MGSkinnedAnimationAux/AnimationClipReader.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework.Content; 2 | 3 | namespace MGSkinnedAnimationAux 4 | { 5 | public class AnimationClipReader : ContentTypeReader 6 | { 7 | protected override AnimationClip Read(ContentReader input, AnimationClip existingInstance) 8 | { 9 | AnimationClip clip = new AnimationClip(); 10 | clip.Name = input.ReadString(); 11 | clip.Duration = input.ReadDouble(); 12 | 13 | int boneCnt = input.ReadInt32(); 14 | for (int i = 0; i < boneCnt; i++) 15 | { 16 | AnimationClip.Bone bone = new AnimationClip.Bone(); 17 | clip.Bones.Add(bone); 18 | 19 | bone.Name = input.ReadString(); 20 | 21 | int cnt = input.ReadInt32(); 22 | 23 | for (int j = 0; j < cnt; j++) 24 | { 25 | AnimationClip.Keyframe keyframe = new AnimationClip.Keyframe(); 26 | keyframe.Time = input.ReadDouble(); 27 | keyframe.Rotation = input.ReadQuaternion(); 28 | keyframe.Translation = input.ReadVector3(); 29 | 30 | bone.Keyframes.Add(keyframe); 31 | 32 | } 33 | 34 | } 35 | 36 | return clip; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /MGSkinnedAnimationAux/Bone.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.Xna.Framework; 3 | 4 | namespace MGSkinnedAnimationAux 5 | { 6 | /// 7 | /// Bones in this model are represented by this class, which 8 | /// allows a bone to have more detail associatd with it. 9 | /// 10 | /// This class allows you to manipulate the local coordinate system 11 | /// for objects by changing the scaling, translation, and rotation. 12 | /// These are indepenent of the bind transformation originally supplied 13 | /// for the model. So, the actual transformation for a bone is 14 | /// the product of the: 15 | /// 16 | /// Scaling 17 | /// Bind scaling (scaling removed from the bind transform) 18 | /// Rotation 19 | /// Translation 20 | /// Bind Transformation 21 | /// Parent Absolute Transformation 22 | /// 23 | /// 24 | public class Bone 25 | { 26 | #region Fields 27 | 28 | /// 29 | /// Any parent for this bone 30 | /// 31 | private Bone parent = null; 32 | 33 | /// 34 | /// The children of this bone 35 | /// 36 | private List children = new List(); 37 | 38 | /// 39 | /// The bind transform is the transform for this bone 40 | /// as loaded from the original model. It's the base pose. 41 | /// I do remove any scaling, though. 42 | /// 43 | private Matrix bindTransform = Matrix.Identity; 44 | 45 | /// 46 | /// The bind scaling component extracted from the bind transform 47 | /// 48 | private Vector3 bindScale = Vector3.One; 49 | 50 | /// 51 | /// Any translation applied to the bone 52 | /// 53 | private Vector3 translation = Vector3.Zero; 54 | 55 | /// 56 | /// Any rotation applied to the bone 57 | /// 58 | private Quaternion rotation = Quaternion.Identity; 59 | 60 | /// 61 | /// Any scaling applied to the bone 62 | /// 63 | private Vector3 scale = Vector3.One; 64 | 65 | #endregion 66 | 67 | #region Properties 68 | 69 | /// 70 | /// The bone name 71 | /// 72 | public string Name = ""; 73 | 74 | /// 75 | /// The bone bind transform 76 | /// 77 | public Matrix BindTransform { get {return bindTransform;} } 78 | 79 | /// 80 | /// Inverse of absolute bind transform for skinnning 81 | /// 82 | public Matrix SkinTransform { get; set; } 83 | 84 | /// 85 | /// Bone rotation 86 | /// 87 | public Quaternion Rotation {get {return rotation;} set {rotation = value;}} 88 | 89 | /// 90 | /// Any translations 91 | /// 92 | public Vector3 Translation {get {return translation;} set {translation = value;}} 93 | 94 | /// 95 | /// Any scaling 96 | /// 97 | public Vector3 Scale { get { return scale; } set { scale = value; } } 98 | 99 | /// 100 | /// The parent bone or null for the root bone 101 | /// 102 | public Bone Parent { get { return parent; } } 103 | 104 | /// 105 | /// The children of this bone 106 | /// 107 | public List Children { get { return children; } } 108 | 109 | /// 110 | /// The bone absolute transform 111 | /// 112 | public Matrix AbsoluteTransform = Matrix.Identity; 113 | 114 | #endregion 115 | 116 | #region Operations 117 | 118 | /// 119 | /// Constructor for a bone object 120 | /// 121 | /// The name of the bone 122 | /// The initial bind transform for the bone 123 | /// A parent for this bone 124 | public Bone(string name, Matrix bindTransform, Bone parent) 125 | { 126 | this.Name = name; 127 | this.parent = parent; 128 | if (parent != null) 129 | parent.children.Add(this); 130 | 131 | // I am not supporting scaling in animation in this 132 | // example, so I extract the bind scaling from the 133 | // bind transform and save it. 134 | 135 | this.bindScale = new Vector3(bindTransform.Right.Length(), 136 | bindTransform.Up.Length(), bindTransform.Backward.Length()); 137 | 138 | bindTransform.Right = bindTransform.Right / bindScale.X; 139 | bindTransform.Up = bindTransform.Up / bindScale.Y; 140 | bindTransform.Backward = bindTransform.Backward / bindScale.Y; 141 | this.bindTransform = bindTransform; 142 | 143 | // Set the skinning bind transform 144 | // That is the inverse of the absolute transform in the bind pose 145 | 146 | ComputeAbsoluteTransform(); 147 | SkinTransform = Matrix.Invert(AbsoluteTransform); 148 | } 149 | 150 | /// 151 | /// Compute the absolute transformation for this bone. 152 | /// 153 | public void ComputeAbsoluteTransform() 154 | { 155 | Matrix transform = Matrix.CreateScale(Scale * bindScale) * 156 | Matrix.CreateFromQuaternion(Rotation) * 157 | Matrix.CreateTranslation(Translation) * 158 | BindTransform; 159 | 160 | if (Parent != null) 161 | { 162 | // This bone has a parent bone 163 | AbsoluteTransform = transform * Parent.AbsoluteTransform; 164 | } 165 | else 166 | { // The root bone 167 | AbsoluteTransform = transform; 168 | } 169 | } 170 | 171 | /// 172 | /// This sets the rotation and translation such that the 173 | /// rotation times the translation times the bind after set 174 | /// equals this matrix. This is used to set animation values. 175 | /// 176 | /// A matrix include translation and rotation 177 | public void SetCompleteTransform(Matrix m) 178 | { 179 | Matrix setTo = m * Matrix.Invert(BindTransform); 180 | 181 | Translation = setTo.Translation; 182 | Rotation = Quaternion.CreateFromRotationMatrix(setTo); 183 | } 184 | 185 | #endregion 186 | 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /MGSkinnedAnimationAux/MGSkinnedAnimationAux.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {D1CC382B-7D83-4AB0-9978-DFDAFDE7F027} 9 | Library 10 | Properties 11 | MGSkinnedAnimationAux 12 | MGSkinnedAnimationAux 13 | v4.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | $(MSBuildExtensionsPath)\MonoGame\v3.0\Tools\MonoGame.Framework.dll 37 | 38 | 39 | $(MSBuildExtensionsPath)\MonoGame\v3.0\Tools\MonoGame.Framework.Content.Pipeline.dll 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 58 | -------------------------------------------------------------------------------- /MGSkinnedAnimationAux/ModelExtra.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace MGSkinnedAnimationAux 4 | { 5 | /// 6 | /// Class that contains additional information attached to the model and 7 | /// shared with the runtime. 8 | /// 9 | public class ModelExtra 10 | { 11 | #region Fields 12 | 13 | /// 14 | /// The bone indices for the skeleton associated with any 15 | /// skinned model. 16 | /// 17 | private List skeleton = new List(); 18 | 19 | /// 20 | /// Any associated animation clips 21 | /// 22 | public List clips = new List(); 23 | 24 | #endregion 25 | 26 | #region Properties 27 | 28 | /// 29 | /// The bone indices for the skeleton associated with any 30 | /// skinned model. 31 | /// 32 | public List Skeleton { get { return skeleton; } set { skeleton = value; } } 33 | 34 | /// 35 | /// Animation clips associated with this model 36 | /// 37 | public List Clips { get { return clips; } set { clips = value; } } 38 | 39 | #endregion 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /MGSkinnedAnimationAux/ModelExtraReader.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.Xna.Framework.Content; 3 | 4 | namespace MGSkinnedAnimationAux 5 | { 6 | public class ModelExtraReader : ContentTypeReader 7 | { 8 | protected override ModelExtra Read(ContentReader input, ModelExtra existingInstance) 9 | { 10 | ModelExtra extra = new ModelExtra(); 11 | extra.Skeleton = input.ReadObject>(); 12 | extra.Clips = input.ReadObject>(); 13 | 14 | return extra; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MGSkinnedAnimationAux/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("MGSkinnedAnimationAux")] 8 | [assembly: AssemblyProduct("MGSkinnedAnimationAux")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyCopyright("Copyright © 2017")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("68b0a5de-0543-458f-8317-932918f3655e")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /MGSkinnedAnimationPipeline/AnimationClipWriter.cs: -------------------------------------------------------------------------------- 1 | using MGSkinnedAnimationAux; 2 | using Microsoft.Xna.Framework.Content.Pipeline; 3 | using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; 4 | 5 | namespace MGSkinnedAnimationPipeline 6 | { 7 | [ContentTypeWriter] 8 | public class AnimationClipWriter : ContentTypeWriter 9 | { 10 | protected override void Write(ContentWriter output, AnimationClip clip) 11 | { 12 | output.Write(clip.Name); 13 | output.Write(clip.Duration); 14 | output.Write(clip.Bones.Count); 15 | foreach (AnimationClip.Bone bone in clip.Bones) 16 | { 17 | output.Write(bone.Name); 18 | output.Write(bone.Keyframes.Count); 19 | foreach (AnimationClip.Keyframe keyframe in bone.Keyframes) 20 | { 21 | output.Write(keyframe.Time); 22 | output.Write(keyframe.Rotation); 23 | output.Write(keyframe.Translation); 24 | } 25 | } 26 | } 27 | 28 | public override string GetRuntimeReader(TargetPlatform targetPlatform) 29 | { 30 | return typeof(AnimationClipReader).AssemblyQualifiedName; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MGSkinnedAnimationPipeline/MGSkinnedAnimationPipeline.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {D19F0DBF-A3DE-4FC3-BB2A-F6AEBD8C50C7} 9 | Library 10 | Properties 11 | MGSkinnedAnimationPipeline 12 | MGSkinnedAnimationPipeline 13 | v4.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | $(MSBuildExtensionsPath)\MonoGame\v3.0\Tools\MonoGame.Framework.dll 37 | 38 | 39 | $(MSBuildExtensionsPath)\MonoGame\v3.0\Tools\MonoGame.Framework.Content.Pipeline.dll 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {d1cc382b-7d83-4ab0-9978-dfdafde7f027} 51 | MGSkinnedAnimationAux 52 | 53 | 54 | 55 | 62 | -------------------------------------------------------------------------------- /MGSkinnedAnimationPipeline/ModelExtraWriter.cs: -------------------------------------------------------------------------------- 1 | using MGSkinnedAnimationAux; 2 | using Microsoft.Xna.Framework.Content.Pipeline; 3 | using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; 4 | 5 | namespace MGSkinnedAnimationPipeline 6 | { 7 | [ContentTypeWriter] 8 | public class ModelExtraWriter : ContentTypeWriter 9 | { 10 | protected override void Write(ContentWriter output, ModelExtra extra) 11 | { 12 | output.WriteObject(extra.Skeleton); 13 | output.WriteObject(extra.Clips); 14 | } 15 | 16 | public override string GetRuntimeReader(TargetPlatform targetPlatform) 17 | { 18 | return typeof(ModelExtraReader).AssemblyQualifiedName; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MGSkinnedAnimationPipeline/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("MGSkinnedAnimationPipeline")] 8 | [assembly: AssemblyProduct("MGSkinnedAnimationPipeline")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyCopyright("Copyright © 2017")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("45546bc8-83cf-427a-92de-6212c038f91e")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /ModelViewer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D713AD7B-7B54-4772-87B0-D572CECEFA3F}" 7 | ProjectSection(SolutionItems) = preProject 8 | Readme.md = Readme.md 9 | EndProjectSection 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MGSkinnedAnimationAux", "MGSkinnedAnimationAux\MGSkinnedAnimationAux.csproj", "{D1CC382B-7D83-4AB0-9978-DFDAFDE7F027}" 12 | EndProject 13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MGSkinnedAnimationPipeline", "MGSkinnedAnimationPipeline\MGSkinnedAnimationPipeline.csproj", "{D19F0DBF-A3DE-4FC3-BB2A-F6AEBD8C50C7}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelViewer", "ModelViewer\ModelViewer.csproj", "{7FF8E367-E83B-4D02-A7E2-D8A7D8B0EB15}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelperSuite", "HelperSuite\HelperSuite.csproj", "{BBE5A22C-4774-4066-A51C-D689B1E8A2E6}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Debug|x86 = Debug|x86 23 | Release|Any CPU = Release|Any CPU 24 | Release|x86 = Release|x86 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {D1CC382B-7D83-4AB0-9978-DFDAFDE7F027}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {D1CC382B-7D83-4AB0-9978-DFDAFDE7F027}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {D1CC382B-7D83-4AB0-9978-DFDAFDE7F027}.Debug|x86.ActiveCfg = Debug|Any CPU 30 | {D1CC382B-7D83-4AB0-9978-DFDAFDE7F027}.Debug|x86.Build.0 = Debug|Any CPU 31 | {D1CC382B-7D83-4AB0-9978-DFDAFDE7F027}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {D1CC382B-7D83-4AB0-9978-DFDAFDE7F027}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {D1CC382B-7D83-4AB0-9978-DFDAFDE7F027}.Release|x86.ActiveCfg = Release|Any CPU 34 | {D1CC382B-7D83-4AB0-9978-DFDAFDE7F027}.Release|x86.Build.0 = Release|Any CPU 35 | {D19F0DBF-A3DE-4FC3-BB2A-F6AEBD8C50C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {D19F0DBF-A3DE-4FC3-BB2A-F6AEBD8C50C7}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {D19F0DBF-A3DE-4FC3-BB2A-F6AEBD8C50C7}.Debug|x86.ActiveCfg = Debug|Any CPU 38 | {D19F0DBF-A3DE-4FC3-BB2A-F6AEBD8C50C7}.Debug|x86.Build.0 = Debug|Any CPU 39 | {D19F0DBF-A3DE-4FC3-BB2A-F6AEBD8C50C7}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {D19F0DBF-A3DE-4FC3-BB2A-F6AEBD8C50C7}.Release|Any CPU.Build.0 = Release|Any CPU 41 | {D19F0DBF-A3DE-4FC3-BB2A-F6AEBD8C50C7}.Release|x86.ActiveCfg = Release|Any CPU 42 | {D19F0DBF-A3DE-4FC3-BB2A-F6AEBD8C50C7}.Release|x86.Build.0 = Release|Any CPU 43 | {7FF8E367-E83B-4D02-A7E2-D8A7D8B0EB15}.Debug|Any CPU.ActiveCfg = Debug|x86 44 | {7FF8E367-E83B-4D02-A7E2-D8A7D8B0EB15}.Debug|Any CPU.Build.0 = Debug|x86 45 | {7FF8E367-E83B-4D02-A7E2-D8A7D8B0EB15}.Debug|x86.ActiveCfg = Debug|x86 46 | {7FF8E367-E83B-4D02-A7E2-D8A7D8B0EB15}.Debug|x86.Build.0 = Debug|x86 47 | {7FF8E367-E83B-4D02-A7E2-D8A7D8B0EB15}.Release|Any CPU.ActiveCfg = Release|x86 48 | {7FF8E367-E83B-4D02-A7E2-D8A7D8B0EB15}.Release|x86.ActiveCfg = Release|x86 49 | {7FF8E367-E83B-4D02-A7E2-D8A7D8B0EB15}.Release|x86.Build.0 = Release|x86 50 | {BBE5A22C-4774-4066-A51C-D689B1E8A2E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {BBE5A22C-4774-4066-A51C-D689B1E8A2E6}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {BBE5A22C-4774-4066-A51C-D689B1E8A2E6}.Debug|x86.ActiveCfg = Debug|Any CPU 53 | {BBE5A22C-4774-4066-A51C-D689B1E8A2E6}.Debug|x86.Build.0 = Debug|Any CPU 54 | {BBE5A22C-4774-4066-A51C-D689B1E8A2E6}.Release|Any CPU.ActiveCfg = Release|Any CPU 55 | {BBE5A22C-4774-4066-A51C-D689B1E8A2E6}.Release|Any CPU.Build.0 = Release|Any CPU 56 | {BBE5A22C-4774-4066-A51C-D689B1E8A2E6}.Release|x86.ActiveCfg = Release|Any CPU 57 | {BBE5A22C-4774-4066-A51C-D689B1E8A2E6}.Release|x86.Build.0 = Release|Any CPU 58 | EndGlobalSection 59 | GlobalSection(SolutionProperties) = preSolution 60 | HideSolutionNode = FALSE 61 | EndGlobalSection 62 | EndGlobal 63 | -------------------------------------------------------------------------------- /ModelViewer/Content/Content.mgcb: -------------------------------------------------------------------------------- 1 | 2 | #----------------------------- Global Properties ----------------------------# 3 | 4 | /outputDir:bin/$(Platform) 5 | /intermediateDir:obj/$(Platform) 6 | /platform:Windows 7 | /config: 8 | /profile:Reach 9 | /compress:False 10 | 11 | #-------------------------------- References --------------------------------# 12 | 13 | /reference:ProtonType.Content.Pipeline.DDSImporter.dll 14 | /reference:..\..\MGSkinnedAnimationPipeline\bin\Debug\MGSkinnedAnimationAux.dll 15 | /reference:..\..\MGSkinnedAnimationPipeline\bin\Debug\MGSkinnedAnimationPipeline.dll 16 | 17 | #---------------------------------- Content ---------------------------------# 18 | 19 | #begin Fonts/defaultfont.spritefont 20 | /importer:FontDescriptionImporter 21 | /processor:FontDescriptionProcessor 22 | /processorParam:PremultiplyAlpha=True 23 | /processorParam:TextureFormat=Compressed 24 | /build:Fonts/defaultfont.spritefont 25 | 26 | #begin Fonts/monospace.spritefont 27 | /importer:FontDescriptionImporter 28 | /processor:FontDescriptionProcessor 29 | /processorParam:PremultiplyAlpha=True 30 | /processorParam:TextureFormat=Compressed 31 | /build:Fonts/monospace.spritefont 32 | 33 | #begin Graphical User Interface/GUIEffect.fx 34 | /importer:EffectImporter 35 | /processor:EffectProcessor 36 | /processorParam:DebugMode=Auto 37 | /build:Graphical User Interface/GUIEffect.fx 38 | 39 | #begin Graphical User Interface/ring.png 40 | /importer:TextureImporter 41 | /processor:TextureProcessor 42 | /processorParam:ColorKeyColor=255,0,255,255 43 | /processorParam:ColorKeyEnabled=False 44 | /processorParam:GenerateMipmaps=False 45 | /processorParam:PremultiplyAlpha=True 46 | /processorParam:ResizeToPowerOfTwo=False 47 | /processorParam:MakeSquare=False 48 | /processorParam:TextureFormat=NoChange 49 | /build:Graphical User Interface/ring.png 50 | 51 | #begin Graphical User Interface/colorpickersmall.png 52 | /importer:TextureImporter 53 | /processor:TextureProcessor 54 | /processorParam:ColorKeyColor=255,0,255,255 55 | /processorParam:ColorKeyEnabled=True 56 | /processorParam:GenerateMipmaps=False 57 | /processorParam:PremultiplyAlpha=True 58 | /processorParam:ResizeToPowerOfTwo=False 59 | /processorParam:MakeSquare=False 60 | /processorParam:TextureFormat=Color 61 | /build:Graphical User Interface/colorpickersmall.png 62 | 63 | #begin Graphical User Interface/colorpickerbig.png 64 | /importer:TextureImporter 65 | /processor:TextureProcessor 66 | /processorParam:ColorKeyColor=255,0,255,255 67 | /processorParam:ColorKeyEnabled=True 68 | /processorParam:GenerateMipmaps=False 69 | /processorParam:PremultiplyAlpha=True 70 | /processorParam:ResizeToPowerOfTwo=False 71 | /processorParam:MakeSquare=False 72 | /processorParam:TextureFormat=Color 73 | /build:Graphical User Interface/colorpickerbig.png 74 | 75 | #begin ShaderModules/Skybox/Skybox.fx 76 | /importer:EffectImporter 77 | /processor:EffectProcessor 78 | /processorParam:DebugMode=Auto 79 | /build:ShaderModules/Skybox/Skybox.fx 80 | 81 | #begin ShaderModules/Skybox/isosphere.fbx 82 | /importer:FbxImporter 83 | /processor:ModelProcessor 84 | /processorParam:ColorKeyColor=0,0,0,0 85 | /processorParam:ColorKeyEnabled=True 86 | /processorParam:DefaultEffect=BasicEffect 87 | /processorParam:GenerateMipmaps=False 88 | /processorParam:GenerateTangentFrames=True 89 | /processorParam:PremultiplyTextureAlpha=False 90 | /processorParam:PremultiplyVertexColors=True 91 | /processorParam:ResizeTexturesToPowerOfTwo=False 92 | /processorParam:RotationX=0 93 | /processorParam:RotationY=0 94 | /processorParam:RotationZ=0 95 | /processorParam:Scale=1 96 | /processorParam:SwapWindingOrder=False 97 | /processorParam:TextureFormat=Compressed 98 | /build:ShaderModules/Skybox/isosphere.fbx 99 | 100 | #begin ShaderModules/Skybox/skyboxCubemap.dds 101 | /importer:TextureImporter 102 | /processor:PassThroughProcessor 103 | /build:ShaderModules/Skybox/skyboxCubemap.dds 104 | 105 | #begin ShaderModules/AnimatedModelShader/AnimatedModelShader.fx 106 | /importer:EffectImporter 107 | /processor:EffectProcessor 108 | /processorParam:DebugMode=Auto 109 | /build:ShaderModules/AnimatedModelShader/AnimatedModelShader.fx 110 | 111 | #begin ShaderModules/AnimatedModelShader/cube.fbx 112 | /importer:FbxImporter 113 | /processor:AnimationProcessor 114 | /processorParam:ColorKeyColor=0,0,0,0 115 | /processorParam:ColorKeyEnabled=True 116 | /processorParam:DefaultEffect=BasicEffect 117 | /processorParam:GenerateMipmaps=True 118 | /processorParam:GenerateTangentFrames=False 119 | /processorParam:PremultiplyTextureAlpha=True 120 | /processorParam:PremultiplyVertexColors=True 121 | /processorParam:ResizeTexturesToPowerOfTwo=False 122 | /processorParam:RotationX=0 123 | /processorParam:RotationY=0 124 | /processorParam:RotationZ=0 125 | /processorParam:Scale=1 126 | /processorParam:SwapWindingOrder=False 127 | /processorParam:TextureFormat=Compressed 128 | /build:ShaderModules/AnimatedModelShader/cube.fbx 129 | 130 | #begin ShaderModules/AnimatedModelShader/fresnel.png 131 | /importer:TextureImporter 132 | /processor:TextureProcessor 133 | /processorParam:ColorKeyColor=255,0,255,255 134 | /processorParam:ColorKeyEnabled=True 135 | /processorParam:GenerateMipmaps=False 136 | /processorParam:PremultiplyAlpha=True 137 | /processorParam:ResizeToPowerOfTwo=False 138 | /processorParam:MakeSquare=False 139 | /processorParam:TextureFormat=Color 140 | /build:ShaderModules/AnimatedModelShader/fresnel.png 141 | 142 | #begin ShaderModules/AnimatedModelShader/fresnel2.png 143 | /importer:TextureImporter 144 | /processor:TextureProcessor 145 | /processorParam:ColorKeyColor=255,0,255,255 146 | /processorParam:ColorKeyEnabled=True 147 | /processorParam:GenerateMipmaps=False 148 | /processorParam:PremultiplyAlpha=True 149 | /processorParam:ResizeToPowerOfTwo=False 150 | /processorParam:MakeSquare=False 151 | /processorParam:TextureFormat=Color 152 | /build:ShaderModules/AnimatedModelShader/fresnel2.png 153 | 154 | #begin ShaderModules/AmbientOcclusionShader/AmbientOcclusionShader.fx 155 | /importer:EffectImporter 156 | /processor:EffectProcessor 157 | /processorParam:DebugMode=Auto 158 | /build:ShaderModules/AmbientOcclusionShader/AmbientOcclusionShader.fx 159 | 160 | -------------------------------------------------------------------------------- /ModelViewer/Content/Fonts/defaultfont.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 15 | Arial 16 | 17 | 21 | 10 22 | 23 | 27 | 0 28 | 29 | 33 | true 34 | 35 | 39 | 40 | 41 | 45 | 46 | 47 | 54 | 55 | 56 | 57 | ~ 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /ModelViewer/Content/Fonts/monospace.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 15 | Lucida Console 16 | 17 | 21 | 10 22 | 23 | 27 | 0 28 | 29 | 33 | true 34 | 35 | 39 | 40 | 41 | 45 | 46 | 47 | 54 | 55 | 56 | 57 | ~ 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /ModelViewer/Content/Graphical User Interface/GUIEffect.fx: -------------------------------------------------------------------------------- 1 | // 2 | //Texture2D BaseTexture; 3 | //SamplerState u_texture 4 | //{ 5 | // Texture = ; 6 | // 7 | // MagFilter = LINEAR; 8 | // MinFilter = LINEAR; 9 | // Mipfilter = LINEAR; 10 | // 11 | // AddressU = CLAMP; 12 | // AddressV = CLAMP; 13 | //}; 14 | 15 | struct VertexShaderInput 16 | { 17 | float3 Position : POSITION0; 18 | float4 Color : COLOR0; 19 | }; 20 | 21 | struct VertexShaderOutput 22 | { 23 | float4 Position : POSITION0; 24 | float4 Color : TEXCOORD0; 25 | }; 26 | 27 | VertexShaderOutput VertexShaderFunction(VertexShaderInput input) 28 | { 29 | VertexShaderOutput output; 30 | output.Position = float4(input.Position, 1); 31 | output.Color = input.Color; 32 | return output; 33 | } 34 | 35 | float4 FlatPS(VertexShaderOutput input) : SV_TARGET0 36 | { 37 | return float4(input.Color); 38 | } 39 | 40 | 41 | technique Flat 42 | { 43 | pass Flat 44 | { 45 | VertexShader = compile vs_4_0 VertexShaderFunction(); 46 | PixelShader = compile ps_4_0 FlatPS(); 47 | } 48 | } -------------------------------------------------------------------------------- /ModelViewer/Content/Graphical User Interface/colorpickerbig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/Graphical User Interface/colorpickerbig.png -------------------------------------------------------------------------------- /ModelViewer/Content/Graphical User Interface/colorpickersmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/Graphical User Interface/colorpickersmall.png -------------------------------------------------------------------------------- /ModelViewer/Content/Graphical User Interface/ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/Graphical User Interface/ring.png -------------------------------------------------------------------------------- /ModelViewer/Content/ProtonType.Content.Pipeline.DDSImporter.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/ProtonType.Content.Pipeline.DDSImporter.dll -------------------------------------------------------------------------------- /ModelViewer/Content/ShaderModules/AnimatedModelShader/cube.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/ShaderModules/AnimatedModelShader/cube.fbx -------------------------------------------------------------------------------- /ModelViewer/Content/ShaderModules/AnimatedModelShader/fresnel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/ShaderModules/AnimatedModelShader/fresnel.png -------------------------------------------------------------------------------- /ModelViewer/Content/ShaderModules/AnimatedModelShader/fresnel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/ShaderModules/AnimatedModelShader/fresnel2.png -------------------------------------------------------------------------------- /ModelViewer/Content/ShaderModules/AnimatedModelShader/helper.fx: -------------------------------------------------------------------------------- 1 |  2 | float2 InverseResolution = float2(1.0f / 1280.0f, 1.0f / 800.0f); 3 | 4 | #define SAMPLE_COUNT 9 5 | static float2 SampleOffsets[9] = 6 | { 7 | float2(-1, -1), float2(0, -1), float2(1, -1), 8 | float2(-1, 0), float2(0, 0), float2(1, 0), 9 | float2(-1, 1), float2(0, 1), float2(1, 1) 10 | }; 11 | 12 | static float SampleWeights[9] = 13 | { 14 | 0.077847f, 15 | 0.123317f, 16 | 0.077847f, 17 | 0.123317f, 18 | 0.195346f, 19 | 0.123317f, 20 | 0.077847f, 21 | 0.123317f, 22 | 0.077847f, 23 | }; 24 | 25 | //float2 encode(float3 n) 26 | //{ 27 | // half2 enc = normalize(n.xy) * (sqrt(-n.z * 0.5 + 0.5)); 28 | // enc = enc * 0.5 + 0.5; 29 | // return enc; 30 | //} 31 | 32 | //float3 decode(float4 enc) 33 | //{ 34 | // half4 nn = enc * half4(2, 2, 0, 0) + half4(-1, -1, 1, -1); 35 | // half l = dot(nn.xyz, -nn.xyw); 36 | // nn.z = l; 37 | // nn.xy *= sqrt(l); 38 | // return nn.xyz * 2 + half3(0, 0, -1); 39 | //} 40 | 41 | //half4 encode(half3 n) 42 | //{ 43 | // return half4(n.xy * 0.5 + 0.5, 0, 0); 44 | //} 45 | 46 | //half3 decode(half2 enc) 47 | //{ 48 | // half3 n; 49 | // n.xy = enc * 2 - 1; 50 | // n.z = sqrt(1 - dot(n.xy, n.xy)); 51 | // return n; 52 | //} 53 | 54 | 55 | float3 encode(float3 n) 56 | { 57 | return 0.5f * (n + 1.0f); 58 | } 59 | 60 | float3 decode(float3 n) 61 | { 62 | return 2.0f * n.xyz - 1.0f; 63 | } 64 | 65 | float encodeMetallicMattype(float metalness, float mattype) 66 | { 67 | return metalness * 0.1f * 0.5f + mattype * 0.1f; 68 | } 69 | 70 | float decodeMetalness(float input) 71 | { 72 | input *= 10; 73 | return frac(input) * 2; 74 | } 75 | 76 | float decodeMattype(float input) 77 | { 78 | input *= 10; 79 | return trunc(input); 80 | } 81 | 82 | 83 | float3 SpecularCookTorrance(float NdotL, float3 normal, float3 negativeLightDirection, float3 cameraDirectionP, float diffuseIntensity, float3 diffuseColor, float f0, float roughness) 84 | { 85 | float3 specular = float3(0, 0, 0); 86 | 87 | [branch] 88 | if (NdotL > 0.0f) 89 | { 90 | float3 halfVector = normalize(negativeLightDirection + cameraDirectionP); 91 | 92 | float NdotH = saturate(dot(normal, halfVector)); 93 | float NdotV = saturate(dot(normal, cameraDirectionP)); 94 | float VdotH = saturate(dot(cameraDirectionP, halfVector)); 95 | float mSquared = roughness * roughness; 96 | 97 | 98 | //Trowbridge-Reitz 99 | float D_lowerTerm = (NdotH * NdotH * (mSquared * mSquared - 1) + 1); 100 | float D = mSquared * mSquared / (3.14 * D_lowerTerm * D_lowerTerm); 101 | 102 | //fresnel (Schlick) 103 | float F = pow(1.0 - VdotH, 5.0); 104 | F *= (1.0 - f0); 105 | F += f0; 106 | 107 | //Schlick Smith 108 | float k = (roughness + 1) * (roughness + 1) / 8; 109 | float g_v = NdotV / (NdotV * (1 - k) + k); 110 | float g_l = NdotL / (NdotL * (1 - k) + k); 111 | 112 | float G = g_l * g_v; 113 | 114 | specular = max(0, (D * F * G) / (4 * NdotV * NdotL)) * diffuseIntensity * diffuseColor * NdotL; //todo check this!!!!!!!!!!! why 3.14?j only relevant if we have it 115 | 116 | //http://malcolm-mcneely.co.uk/blog/?p=214 117 | } 118 | return specular; 119 | } 120 | 121 | float3 DiffuseOrenNayar(float NdotL, float3 normal, float3 lightDirection, float3 cameraDirection, float lightIntensity, float3 lightColor, float roughness) 122 | { 123 | const float PI = 3.14159; 124 | 125 | // calculate intermediary values 126 | float NdotV = dot(normal, cameraDirection); 127 | 128 | float angleVN = acos(NdotV); 129 | float angleLN = acos(NdotL); 130 | 131 | float alpha = max(angleVN, angleLN); 132 | float beta = min(angleVN, angleLN); 133 | float gamma = dot(cameraDirection - normal * NdotV, lightDirection - normal * NdotL); 134 | 135 | float roughnessSquared = roughness * roughness; 136 | 137 | // calculate A and B 138 | float A = 1.0 - 0.5 * (roughnessSquared / (roughnessSquared + 0.57)); 139 | 140 | float B = 0.45 * (roughnessSquared / (roughnessSquared + 0.09)); 141 | 142 | float C = sin(alpha) * tan(beta); 143 | 144 | // put it all together 145 | float L1 = max(0.0, NdotL) * (A + B * max(0.0, gamma) * C); 146 | 147 | // get the final color 148 | return L1 * lightColor * lightIntensity / 4; 149 | } 150 | 151 | float3 SpecularCookTorranceCube(float3 normal,float3 cameraDirectionP, float f0, float roughness) 152 | { 153 | float3 specular = float3(0, 0, 0); 154 | 155 | float3 halfVector = normalize(normal + cameraDirectionP); 156 | 157 | float NdotH = saturate(dot(normal, halfVector)); 158 | float NdotV = saturate(dot(normal, cameraDirectionP)); 159 | float VdotH = saturate(dot(cameraDirectionP, halfVector)); 160 | float mSquared = roughness * roughness; 161 | 162 | //Trowbridge-Reitz 163 | float D_lowerTerm = (NdotH * NdotH * (mSquared * mSquared - 1) + 1); 164 | float D = mSquared * mSquared / (3.14 * D_lowerTerm * D_lowerTerm); 165 | 166 | //fresnel (Schlick) 167 | float F = pow(1.0 - VdotH, 5.0); 168 | F *= (1.0 - f0); 169 | F += f0; 170 | 171 | //Schlick Smith 172 | float k = (roughness + 1) * (roughness + 1) / 8; 173 | float g_v = NdotV / (NdotV * (1 - k) + k); 174 | float g_l = 1 / (1 * (1 - k) + k); 175 | 176 | float G = g_l * g_v; 177 | 178 | specular = max(0, (D * F * G) / (4)); //todo check this!!!!!!!!!!! why 3.14?j only relevant if we have it 179 | 180 | 181 | return specular; 182 | } 183 | 184 | //half2 encode(float3 n) 185 | //{ 186 | // half f = sqrt(8 * n.z + 8); 187 | // return n.xy / f + 0.5; 188 | //} 189 | //half3 decode(half4 enc) 190 | //{ 191 | // half2 fenc = enc * 4 - 2; 192 | // half f = dot(fenc, fenc); 193 | // half g = sqrt(1 - f / 4); 194 | // half3 n; 195 | // n.xy = fenc * g; 196 | // n.z = 1 - f / 2; 197 | // return n; 198 | //} 199 | -------------------------------------------------------------------------------- /ModelViewer/Content/ShaderModules/ScreenSpace/GUIEffect.fx: -------------------------------------------------------------------------------- 1 |  2 | Texture2D Tex; 3 | SamplerState PointSampler 4 | { 5 | Texture = ; 6 | MagFilter = POINT; 7 | MinFilter = POINT; 8 | Mipfilter = POINT; 9 | AddressU = CLAMP; 10 | AddressV = CLAMP; 11 | }; 12 | 13 | struct VertexShaderInput 14 | { 15 | float3 Position : POSITION0; 16 | float4 TexCoord : TEXCOORD0; 17 | }; 18 | 19 | struct VertexShaderOutput 20 | { 21 | float4 Position : POSITION0; 22 | float4 TexCoord : TEXCOORD0; 23 | }; 24 | 25 | VertexShaderOutput VertexShaderFunction(VertexShaderInput input) 26 | { 27 | VertexShaderOutput output; 28 | output.Position = float4(input.Position, 1); 29 | output.TexCoord = input.TexCoord; 30 | return output; 31 | } 32 | 33 | float4 FlatPS(VertexShaderOutput input) : SV_TARGET0 34 | { 35 | return Tex.Sample(PointSampler, input.TexCoord); 36 | } 37 | 38 | 39 | technique Texture 40 | { 41 | pass Texture 42 | { 43 | VertexShader = compile vs_4_0 VertexShaderFunction(); 44 | PixelShader = compile ps_4_0 FlatPS(); 45 | } 46 | } -------------------------------------------------------------------------------- /ModelViewer/Content/ShaderModules/Skybox/Skybox.fx: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 by kosmonautgames 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 11 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 12 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 13 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | */ 15 | 16 | // Basic Skybox shader 17 | 18 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Variables 20 | 21 | float4x4 WorldViewProj; 22 | float3x3 World; 23 | 24 | float CubeSize = 512; 25 | 26 | TextureCube SkyboxTexture; 27 | SamplerState CubeMapSampler 28 | { 29 | Texture = ; 30 | AddressU = CLAMP; 31 | AddressV = CLAMP; 32 | MagFilter = LINEAR; 33 | MinFilter = LINEAR; 34 | Mipfilter = LINEAR; 35 | }; 36 | 37 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 | // Structs 39 | 40 | struct DrawBasic_VSIn 41 | { 42 | float4 Position : POSITION0; 43 | float3 Normal : NORMAL0; 44 | float2 TexCoord : TEXCOORD0; 45 | }; 46 | 47 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | // Functions 49 | 50 | DrawBasic_VSIn DrawSkybox_VertexShader(DrawBasic_VSIn input) 51 | { 52 | DrawBasic_VSIn Output; 53 | //input.Position.z *= input.Position.z+0.5f; 54 | Output.Position = mul(input.Position, WorldViewProj); 55 | Output.Normal = mul(input.Normal, World); 56 | Output.TexCoord = input.TexCoord; 57 | return Output; 58 | } 59 | 60 | //http://the-witness.net/news/2012/02/seamless-cube-map-filtering/ 61 | float3 FixCubeLookup(float3 v, int level) 62 | { 63 | float M = max(max(abs(v.x), abs(v.y)), abs(v.z)); 64 | //float size = CubeSize >> level; 65 | //float scale = (size - 1) / size; 66 | 67 | float scale = 1 - exp2(level) / CubeSize; 68 | if (abs(v.x) != M) v.x *= scale; 69 | if (abs(v.y) != M) v.y *= scale; 70 | if (abs(v.z) != M) v.z *= scale; 71 | return v; 72 | } 73 | 74 | float4 DrawSkybox_PixelShader(DrawBasic_VSIn input) : COLOR 75 | { 76 | float3 normal = normalize(input.Normal); 77 | return SkyboxTexture.SampleLevel(CubeMapSampler, FixCubeLookup(normal.xzy,4),4); 78 | } 79 | 80 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | // Techniques 82 | 83 | technique DrawSkybox 84 | { 85 | pass Pass1 86 | { 87 | VertexShader = compile vs_4_0 DrawSkybox_VertexShader(); 88 | PixelShader = compile ps_5_0 DrawSkybox_PixelShader(); 89 | } 90 | } -------------------------------------------------------------------------------- /ModelViewer/Content/ShaderModules/Skybox/isosphere.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/ShaderModules/Skybox/isosphere.fbx -------------------------------------------------------------------------------- /ModelViewer/Content/ShaderModules/Skybox/skyboxCubemap.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/ShaderModules/Skybox/skyboxCubemap.dds -------------------------------------------------------------------------------- /ModelViewer/Content/ShaderModules/Skybox/skyboxCubemap_sec.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/ShaderModules/Skybox/skyboxCubemap_sec.dds -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/ATI.TextureConverter.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/ATI.TextureConverter.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/Assimp64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/Assimp64.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/AssimpNet.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/AssimpNet.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/CppNet.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/CppNet.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/FreeImage.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/FreeImage.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/FreeImageNET.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/FreeImageNET.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/MGCB.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/MGCB.exe -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/MGCB.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MGCB 5 | 6 | 7 | 8 | 9 | Adapted from this generic command line argument parser: 10 | http://blogs.msdn.com/b/shawnhar/archive/2012/04/20/a-reusable-reflection-based-command-line-parser.aspx 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/MGSkinnedAnimationAux.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/MGSkinnedAnimationAux.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/MGSkinnedAnimationPipeline.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/MGSkinnedAnimationPipeline.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/MonoGame.Framework.Content.Pipeline.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/MonoGame.Framework.Content.Pipeline.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/MonoGame.Framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/MonoGame.Framework.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/Nvidia.TextureTools.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/Nvidia.TextureTools.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/PVRTexLibNET.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/PVRTexLibNET.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/PVRTexLibWrapper.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/PVRTexLibWrapper.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/ffmpeg.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/ffmpeg.exe -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/ffprobe.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/ffprobe.exe -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/freetype6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/freetype6.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/libmojoshader_64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/libmojoshader_64.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/nvtt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Content/mgcb/nvtt.dll -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/runtimeanimatedmodel.txt: -------------------------------------------------------------------------------- 1 | /outputDir:Content/Runtime/Textures 2 | 3 | /reference:MGSkinnedAnimationAux.dll 4 | /reference:MGSkinnedAnimationPipeline.dll 5 | 6 | /importer:FbxImporter 7 | /processor:AnimationProcessor 8 | /processorParam:ColorKeyColor=0,0,0,0 9 | /processorParam:ColorKeyEnabled=True 10 | /processorParam:DefaultEffect=BasicEffect 11 | /processorParam:GenerateMipmaps=False 12 | /processorParam:GenerateTangentFrames=True 13 | /processorParam:PremultiplyTextureAlpha=False 14 | /processorParam:PremultiplyVertexColors=True 15 | /processorParam:ResizeTexturesToPowerOfTwo=False 16 | /processorParam:RotationX=0 17 | /processorParam:RotationY=0 18 | /processorParam:RotationZ=0 19 | /processorParam:Scale=1 20 | /processorParam:SwapWindingOrder=False 21 | /processorParam:TextureFormat=Compressed -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/runtimemodel.txt: -------------------------------------------------------------------------------- 1 | /outputDir:Content/Runtime/Textures 2 | 3 | /importer:FbxImporter 4 | /processor:ModelProcessor 5 | /processorParam:ColorKeyColor=0,0,0,0 6 | /processorParam:ColorKeyEnabled=True 7 | /processorParam:DefaultEffect=BasicEffect 8 | /processorParam:GenerateMipmaps=False 9 | /processorParam:GenerateTangentFrames=True 10 | /processorParam:PremultiplyTextureAlpha=False 11 | /processorParam:PremultiplyVertexColors=True 12 | /processorParam:ResizeTexturesToPowerOfTwo=False 13 | /processorParam:RotationX=0 14 | /processorParam:RotationY=0 15 | /processorParam:RotationZ=0 16 | /processorParam:Scale=1 17 | /processorParam:SwapWindingOrder=False 18 | /processorParam:TextureFormat=Compressed -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/runtimemodelnotangent.txt: -------------------------------------------------------------------------------- 1 | /outputDir:Content/Runtime/Textures 2 | 3 | /importer:FbxImporter 4 | /processor:ModelProcessor 5 | /processorParam:ColorKeyColor=0,0,0,0 6 | /processorParam:ColorKeyEnabled=True 7 | /processorParam:DefaultEffect=BasicEffect 8 | /processorParam:GenerateMipmaps=False 9 | /processorParam:GenerateTangentFrames=False 10 | /processorParam:PremultiplyTextureAlpha=False 11 | /processorParam:PremultiplyVertexColors=True 12 | /processorParam:ResizeTexturesToPowerOfTwo=False 13 | /processorParam:RotationX=0 14 | /processorParam:RotationY=0 15 | /processorParam:RotationZ=0 16 | /processorParam:Scale=1 17 | /processorParam:SwapWindingOrder=False 18 | /processorParam:TextureFormat=Compressed -------------------------------------------------------------------------------- /ModelViewer/Content/mgcb/runtimetexture.txt: -------------------------------------------------------------------------------- 1 | /outputDir:Content/Runtime/Textures 2 | /intermediateDir:Content/Runtime 3 | /importer:TextureImporter 4 | /processor:TextureProcessor 5 | /processorParam:ColorKeyColor=255,0,255,255 6 | /processorParam:ColorKeyEnabled=True 7 | /processorParam:GenerateMipmaps=True 8 | /processorParam:PremultiplyAlpha=True 9 | /processorParam:ResizeToPowerOfTwo=False 10 | /processorParam:MakeSquare=False 11 | /processorParam:TextureFormat=Color -------------------------------------------------------------------------------- /ModelViewer/HelperSuiteExtension/GUI/GuiTextBlockLoadDialog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using HelperSuite.GUI; 6 | using HelperSuite.GUIHelper; 7 | using Microsoft.Xna.Framework; 8 | using Microsoft.Xna.Framework.Graphics; 9 | using ModelViewer.HelperSuiteExtension.GUIHelper; 10 | using ModelViewer.Renderer.ShaderModules.Helper; 11 | 12 | namespace ModelViewer.HelperSuiteExtension.GUI 13 | { 14 | public class GuiTextBlockLoadDialog : GUITextBlock 15 | { 16 | public bool Toggle; 17 | 18 | private static readonly float ButtonBorder = 2; 19 | 20 | private static readonly Color HoverColor = Color.LightGray; 21 | 22 | private static readonly int HoverImageWidth = 250; 23 | 24 | private Vector2 _declarationTextDimensions; 25 | 26 | private bool _isHovered; 27 | 28 | private short _isLoaded; //0 -> 1 -> 2 29 | 30 | //Load 31 | private Task _loadTaskReference; 32 | public object LoadedObject; 33 | private int _loadedObjectPointer = -1; 34 | private StringBuilder _loadedObjectName = new StringBuilder(100); 35 | private StringBuilder _loadingStringBuilder = new StringBuilder("loading..."); 36 | 37 | public MethodInfo LoaderMethod; 38 | public GUIContentLoaderModelViewer GUILoader; 39 | 40 | public enum ContentType 41 | { 42 | Texture2D, 43 | Model 44 | }; 45 | 46 | public GuiTextBlockLoadDialog(GUIStyle style, string text, GUIContentLoaderModelViewer contentLoader, ContentType contentType) : this( 47 | position: Vector2.Zero, 48 | dimensions: style.DimensionsStyle, 49 | text: text, 50 | guiContentLoader: contentLoader, 51 | contentType: contentType, 52 | font: style.TextFontStyle, 53 | blockColor: style.BlockColorStyle, 54 | textColor: style.TextColorStyle, 55 | textAlignment: GUIStyle.TextAlignment.Left, 56 | textBorder: style.TextBorderStyle, 57 | layer: 0, 58 | alignment: style.GuiAlignmentStyle, 59 | parentDimensions: style.ParentDimensionsStyle 60 | ) 61 | { 62 | } 63 | public GuiTextBlockLoadDialog(Vector2 position, Vector2 dimensions, string text, GUIContentLoaderModelViewer guiContentLoader, ContentType contentType, SpriteFont font, Color blockColor, Color textColor, GUIStyle.TextAlignment textAlignment = GUIStyle.TextAlignment.Center, Vector2 textBorder = default(Vector2), int layer = 0, GUIStyle.GUIAlignment alignment = GUIStyle.GUIAlignment.None, Vector2 parentDimensions = default(Vector2)) : base(position, dimensions, text, font, blockColor, textColor, textAlignment, textBorder, layer) 64 | { 65 | _loadedObjectName.Append("..."); 66 | 67 | //Initialize the loader and the kind of content we want to retrieve 68 | 69 | GUILoader = guiContentLoader; 70 | 71 | Type type = null; 72 | switch (contentType) 73 | { 74 | case ContentType.Texture2D: 75 | type = typeof(Texture2D); 76 | break; 77 | case ContentType.Model: 78 | type = typeof(AnimatedModel); 79 | break; 80 | } 81 | 82 | LoaderMethod = GUILoader.GetType().GetMethod("LoadContentFile").MakeGenericMethod(type); 83 | } 84 | 85 | protected override void ComputeFontPosition() 86 | { 87 | if (_text == null) return; 88 | _declarationTextDimensions = TextFont.MeasureString(_text); 89 | 90 | //Let's check wrap! 91 | 92 | //FontWrap(ref textDimension, Dimensions); 93 | 94 | _fontPosition = Dimensions * 0.5f * Vector2.UnitY + _textBorder * Vector2.UnitX - _declarationTextDimensions * 0.5f * Vector2.UnitY; 95 | } 96 | 97 | protected void ComputeObjectNameLength() 98 | { 99 | if (_loadedObjectName.Length > 0) 100 | { 101 | //Max length 102 | Vector2 textDimensions = TextFont.MeasureString(_loadedObjectName); 103 | 104 | float characterLength = textDimensions.X/_loadedObjectName.Length; 105 | 106 | Vector2 buttonLeft = (_declarationTextDimensions + _fontPosition * 1.5f) * Vector2.UnitX; 107 | Vector2 spaceAvailable = Dimensions - 2*Vector2.One*ButtonBorder - buttonLeft - 108 | (2 + _textBorder.X)*Vector2.UnitX; 109 | 110 | int characters = (int) (spaceAvailable.X/characterLength); 111 | 112 | _loadedObjectName.Length = characters < _loadedObjectName.Length ? characters : _loadedObjectName.Length; 113 | } 114 | } 115 | 116 | 117 | public override void Draw(HelperSuite.GUIRenderer.GUIRenderer guiRenderer, Vector2 parentPosition, Vector2 mousePosition) 118 | { 119 | Vector2 buttonLeft = (_declarationTextDimensions + _fontPosition * 1.2f)*Vector2.UnitX; 120 | guiRenderer.DrawQuad(parentPosition + Position, Dimensions, BlockColor); 121 | guiRenderer.DrawQuad(parentPosition + Position + buttonLeft + Vector2.One * ButtonBorder, Dimensions - 2*Vector2.One*ButtonBorder - buttonLeft - (2+_textBorder.X)*Vector2.UnitX, _isHovered ? HoverColor : Color.DimGray); 122 | 123 | Vector2 indicatorButton = parentPosition + new Vector2(Dimensions.X - (2 + _textBorder.X), Dimensions.Y/2 - 4); 124 | 125 | guiRenderer.DrawQuad(indicatorButton, Vector2.One * 8, _isLoaded < 1 ? Color.Red : (_isLoaded < 2 ? Color.Yellow : Color.LimeGreen )); 126 | 127 | guiRenderer.DrawText(parentPosition + Position + _fontPosition, Text, TextFont, TextColor); 128 | 129 | //Description 130 | guiRenderer.DrawText(parentPosition + Position + buttonLeft + new Vector2(4, _fontPosition.Y), _isLoaded == 1 ? _loadingStringBuilder : _loadedObjectName, TextFont, TextColor); 131 | 132 | //Show texture if _isHovered 133 | if (_isLoaded == 2) 134 | { 135 | LoadedObject = GUILoader.ContentArray[_loadedObjectPointer]; 136 | 137 | if (_isHovered) 138 | { 139 | //compute position 140 | 141 | Vector2 position = mousePosition; 142 | 143 | float overborder = position.X + HoverImageWidth - GUIControl.ScreenWidth; 144 | 145 | if (overborder > 0) 146 | position.X -= overborder; 147 | 148 | 149 | if (LoadedObject != null && LoadedObject.GetType() == typeof(Texture2D)) 150 | { 151 | Texture2D image = (Texture2D) LoadedObject; 152 | float height = (float) image.Height/image.Width*HoverImageWidth; 153 | guiRenderer.DrawImage(position, new Vector2(HoverImageWidth, height), 154 | image, Color.White, true); 155 | } 156 | } 157 | } 158 | 159 | } 160 | 161 | public override void Update(GameTime gameTime, Vector2 mousePosition, Vector2 parentPosition) 162 | { 163 | if (_loadTaskReference != null) 164 | { 165 | _isLoaded = (short) (_loadTaskReference.IsCompleted ? 2 : 1); 166 | 167 | if (_isLoaded == 2) 168 | { 169 | if (_loadTaskReference.IsFaulted) 170 | { 171 | _isLoaded = 0; 172 | _loadedObjectName.Clear(); 173 | _loadedObjectName.Append("Loading failed"); 174 | } 175 | 176 | 177 | } 178 | } 179 | else 180 | { 181 | _isLoaded = 0; 182 | } 183 | 184 | _isHovered = false; 185 | 186 | Vector2 bound1 = Position + parentPosition; 187 | Vector2 bound2 = bound1 + Dimensions; 188 | 189 | if (mousePosition.X >= bound1.X && mousePosition.Y >= bound1.Y && mousePosition.X < bound2.X && 190 | mousePosition.Y < bound2.Y) 191 | { 192 | _isHovered = true; 193 | 194 | if (!GUIControl.WasLMBClicked()) return; 195 | 196 | GUIControl.UIWasUsed = true; 197 | 198 | if (GUILoader != null) 199 | { 200 | object[] args = {_loadTaskReference, _loadedObjectPointer, ""}; 201 | if (LoaderMethod != null) LoaderMethod.Invoke(GUILoader, args); 202 | 203 | _loadTaskReference = (Task) args[0]; 204 | _loadedObjectPointer = (int) args[1]; 205 | _loadedObjectName.Clear(); 206 | _loadedObjectName.Append((string)args[2]); 207 | 208 | ComputeObjectNameLength(); 209 | } 210 | } 211 | } 212 | 213 | } 214 | 215 | } -------------------------------------------------------------------------------- /ModelViewer/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kosmonaut3d/Modelviewer/4596c2a9e83d2f5b8c0c60cb479bf9bde197609a/ModelViewer/Icon.ico -------------------------------------------------------------------------------- /ModelViewer/Logic/Camera.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Xna.Framework; 3 | 4 | namespace ModelViewer.Logic 5 | { 6 | public class Camera 7 | { 8 | private Vector3 _position; 9 | private Vector3 _up = Vector3.UnitZ; 10 | private Vector3 _forward = Vector3.Up; 11 | private float _fieldOfView = (float) Math.PI/4; 12 | public float DistanceFromCenter; 13 | 14 | public bool HasChanged = true; 15 | public bool HasMoved; 16 | private Vector3 _lookat; 17 | 18 | public Camera(Vector3 position, Vector3 lookat) 19 | { 20 | _position = position; 21 | _forward = lookat - position; 22 | DistanceFromCenter = _forward.Length(); 23 | //normalize 24 | _forward /= DistanceFromCenter; 25 | Lookat = lookat; 26 | 27 | } 28 | 29 | public Vector3 Position 30 | { 31 | get 32 | { 33 | return _position; 34 | } 35 | set 36 | { 37 | if (_position != value) 38 | { 39 | _position = value; 40 | HasChanged = true; 41 | HasMoved = true; 42 | } 43 | } 44 | } 45 | 46 | public Vector3 Up 47 | { 48 | get 49 | { 50 | return _up; 51 | } 52 | set 53 | { 54 | if (_up != value) 55 | { 56 | _up = value; 57 | HasChanged = true; 58 | } 59 | } 60 | } 61 | 62 | public Vector3 Forward 63 | { 64 | get 65 | { 66 | return _forward; 67 | } 68 | set 69 | { 70 | if (_forward != value) 71 | { 72 | _forward = value; 73 | HasChanged = true; 74 | } 75 | } 76 | } 77 | 78 | public float FieldOfView 79 | { 80 | get { return _fieldOfView; } 81 | set 82 | { 83 | _fieldOfView = value; 84 | HasChanged = true; 85 | } 86 | } 87 | 88 | public Vector3 Lookat 89 | { 90 | get { return _lookat; } 91 | set { _lookat = value; } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /ModelViewer/Logic/Input.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Xna.Framework; 3 | using Microsoft.Xna.Framework.Input; 4 | using ModelViewer.Static; 5 | 6 | namespace ModelViewer.Logic 7 | { 8 | public static class Input 9 | { 10 | public static KeyboardState keyboardState, keyboardLastState; 11 | public static MouseState mouseState, mouseLastState; 12 | 13 | 14 | public static void Update(GameTime gameTime) 15 | { 16 | mouseLastState = mouseState; 17 | keyboardLastState = keyboardState; 18 | mouseState = Mouse.GetState(); 19 | keyboardState = Keyboard.GetState(); 20 | 21 | // KeyboardEvents(gameTime, camera); 22 | } 23 | 24 | 25 | public static Point GetMousePosition() 26 | { 27 | return mouseState.Position; 28 | } 29 | 30 | public static Vector2 GetMousePositionNormalized() 31 | { 32 | return new Vector2((float)mouseState.X / GameSettings.g_ScreenWidth, (float)mouseState.Y / GameSettings.g_ScreenHeight); 33 | } 34 | 35 | private static void KeyboardEvents(GameTime gameTime, Camera camera) 36 | { 37 | if (DebugScreen.ConsoleOpen) return; 38 | 39 | if (!GameSettings.RotateOrbit) 40 | { 41 | float delta = (float) gameTime.ElapsedGameTime.TotalMilliseconds*60/1000; 42 | 43 | Vector3 direction = camera.Forward; 44 | direction.Normalize(); 45 | 46 | Vector3 normal = Vector3.Cross(direction, camera.Up); 47 | 48 | float amount = 0.8f*delta; 49 | 50 | float amountNormal = 0.2f*delta; 51 | 52 | if (keyboardState.IsKeyDown(Keys.W)) 53 | { 54 | camera.Position += direction*amount; 55 | } 56 | 57 | if (keyboardState.IsKeyDown(Keys.S)) 58 | { 59 | camera.Position -= direction*amount; 60 | } 61 | 62 | if (keyboardState.IsKeyDown(Keys.D)) 63 | { 64 | camera.Position += normal*amountNormal; 65 | } 66 | 67 | if (keyboardState.IsKeyDown(Keys.A)) 68 | { 69 | camera.Position -= normal*amountNormal; 70 | } 71 | } 72 | } 73 | 74 | public static bool IsKeyDown(Keys key) 75 | { 76 | return keyboardState.IsKeyDown(key); 77 | } 78 | 79 | // Checks if a key was just pressed down 80 | public static bool WasKeyPressed(Keys key) 81 | { 82 | return keyboardLastState.IsKeyUp(key) && keyboardState.IsKeyDown(key); 83 | } 84 | 85 | public static bool WasLMBClicked() 86 | { 87 | return mouseState.LeftButton == ButtonState.Pressed && mouseLastState.LeftButton == ButtonState.Released; 88 | } 89 | 90 | public static bool IsLMBPressed() 91 | { 92 | return mouseState.LeftButton == ButtonState.Pressed; 93 | } 94 | 95 | public static bool WasKeyReleased(Keys key) 96 | { 97 | return keyboardState.IsKeyUp(key) && keyboardLastState.IsKeyDown(key); 98 | } 99 | 100 | public static string GetKeyPressed() 101 | { 102 | Keys[] lastpressed = keyboardState.GetPressedKeys(); 103 | if (lastpressed.Length < 1) return null; 104 | 105 | foreach (Keys key in lastpressed) 106 | { 107 | if (keyboardLastState.IsKeyUp(key)) 108 | { 109 | Char keyChar = TranslateChar(key, keyboardState.IsKeyDown(Keys.LeftShift), false, false); 110 | if (keyChar == (char)0) return null; 111 | if (keyChar == '\t' || keyChar == '\\' || keyChar == '\'') return null; 112 | return keyChar.ToString(); 113 | } 114 | } 115 | return null; 116 | } 117 | 118 | public static char TranslateChar(Keys key, bool shift, bool capsLock, bool numLock) 119 | { 120 | switch (key) 121 | { 122 | case Keys.A: return TranslateAlphabetic('a', shift, capsLock); 123 | case Keys.B: return TranslateAlphabetic('b', shift, capsLock); 124 | case Keys.C: return TranslateAlphabetic('c', shift, capsLock); 125 | case Keys.D: return TranslateAlphabetic('d', shift, capsLock); 126 | case Keys.E: return TranslateAlphabetic('e', shift, capsLock); 127 | case Keys.F: return TranslateAlphabetic('f', shift, capsLock); 128 | case Keys.G: return TranslateAlphabetic('g', shift, capsLock); 129 | case Keys.H: return TranslateAlphabetic('h', shift, capsLock); 130 | case Keys.I: return TranslateAlphabetic('i', shift, capsLock); 131 | case Keys.J: return TranslateAlphabetic('j', shift, capsLock); 132 | case Keys.K: return TranslateAlphabetic('k', shift, capsLock); 133 | case Keys.L: return TranslateAlphabetic('l', shift, capsLock); 134 | case Keys.M: return TranslateAlphabetic('m', shift, capsLock); 135 | case Keys.N: return TranslateAlphabetic('n', shift, capsLock); 136 | case Keys.O: return TranslateAlphabetic('o', shift, capsLock); 137 | case Keys.P: return TranslateAlphabetic('p', shift, capsLock); 138 | case Keys.Q: return TranslateAlphabetic('q', shift, capsLock); 139 | case Keys.R: return TranslateAlphabetic('r', shift, capsLock); 140 | case Keys.S: return TranslateAlphabetic('s', shift, capsLock); 141 | case Keys.T: return TranslateAlphabetic('t', shift, capsLock); 142 | case Keys.U: return TranslateAlphabetic('u', shift, capsLock); 143 | case Keys.V: return TranslateAlphabetic('v', shift, capsLock); 144 | case Keys.W: return TranslateAlphabetic('w', shift, capsLock); 145 | case Keys.X: return TranslateAlphabetic('x', shift, capsLock); 146 | case Keys.Y: return TranslateAlphabetic('y', shift, capsLock); 147 | case Keys.Z: return TranslateAlphabetic('z', shift, capsLock); 148 | 149 | case Keys.D0: return (shift) ? ')' : '0'; 150 | case Keys.D1: return (shift) ? '!' : '1'; 151 | case Keys.D2: return (shift) ? '@' : '2'; 152 | case Keys.D3: return (shift) ? '#' : '3'; 153 | case Keys.D4: return (shift) ? '$' : '4'; 154 | case Keys.D5: return (shift) ? '%' : '5'; 155 | case Keys.D6: return (shift) ? '^' : '6'; 156 | case Keys.D7: return (shift) ? '&' : '7'; 157 | case Keys.D8: return (shift) ? '*' : '8'; 158 | case Keys.D9: return (shift) ? '(' : '9'; 159 | 160 | case Keys.Add: return '+'; 161 | case Keys.Divide: return '/'; 162 | case Keys.Multiply: return '*'; 163 | case Keys.Subtract: return '-'; 164 | 165 | case Keys.Space: return ' '; 166 | case Keys.Tab: return '\t'; 167 | 168 | case Keys.Decimal: if (numLock && !shift) return '.'; break; 169 | case Keys.NumPad0: if (numLock && !shift) return '0'; break; 170 | case Keys.NumPad1: if (numLock && !shift) return '1'; break; 171 | case Keys.NumPad2: if (numLock && !shift) return '2'; break; 172 | case Keys.NumPad3: if (numLock && !shift) return '3'; break; 173 | case Keys.NumPad4: if (numLock && !shift) return '4'; break; 174 | case Keys.NumPad5: if (numLock && !shift) return '5'; break; 175 | case Keys.NumPad6: if (numLock && !shift) return '6'; break; 176 | case Keys.NumPad7: if (numLock && !shift) return '7'; break; 177 | case Keys.NumPad8: if (numLock && !shift) return '8'; break; 178 | case Keys.NumPad9: if (numLock && !shift) return '9'; break; 179 | 180 | case Keys.OemBackslash: return shift ? '|' : '\\'; 181 | case Keys.OemCloseBrackets: return shift ? '}' : ']'; 182 | case Keys.OemComma: return shift ? '<' : ','; 183 | case Keys.OemMinus: return shift ? '_' : '-'; 184 | case Keys.OemOpenBrackets: return shift ? '{' : '['; 185 | case Keys.OemPeriod: return shift ? '>' : '.'; 186 | case Keys.OemPipe: return shift ? '|' : '\\'; 187 | case Keys.OemPlus: return shift ? '+' : '='; 188 | case Keys.OemQuestion: return shift ? '?' : '/'; 189 | case Keys.OemQuotes: return shift ? '"' : '\''; 190 | case Keys.OemSemicolon: return shift ? ':' : ';'; 191 | case Keys.OemTilde: return shift ? '~' : '`'; 192 | } 193 | 194 | return (char)0; 195 | } 196 | 197 | public static char TranslateAlphabetic(char baseChar, bool shift, bool capsLock) 198 | { 199 | return (capsLock ^ shift) ? char.ToUpper(baseChar) : baseChar; 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /ModelViewer/Logic/MainLogic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Windows.Forms; 4 | using HelperSuite.ContentLoader; 5 | using HelperSuite.GUIHelper; 6 | using Microsoft.Xna.Framework; 7 | using Microsoft.Xna.Framework.Content; 8 | using Microsoft.Xna.Framework.Graphics; 9 | using ModelViewer.Static; 10 | using ButtonState = Microsoft.Xna.Framework.Input.ButtonState; 11 | using GuiTextBlockLoadDialog = ModelViewer.HelperSuiteExtension.GUI.GuiTextBlockLoadDialog; 12 | using Keys = Microsoft.Xna.Framework.Input.Keys; 13 | 14 | namespace ModelViewer.Logic 15 | { 16 | public class MainLogic 17 | { 18 | private ContentManager _contentManager; 19 | 20 | public Texture2D loadedTexture; 21 | public GuiTextBlockLoadDialog modelLoader; 22 | public GuiTextBlockLoadDialog albedoLoader; 23 | public GuiTextBlockLoadDialog normalLoader; 24 | public GuiTextBlockLoadDialog roughnessLoader; 25 | public GuiTextBlockLoadDialog metallicLoader; 26 | public GuiTextBlockLoadDialog bumpLoader; 27 | private Texture2D rollTexture2D; 28 | private SpriteBatch _spriteBatch; 29 | private Camera _camera; 30 | public Vector3 modelPosition; 31 | public Matrix modelRotation = Matrix.Identity; 32 | private double defaultphi = 0; 33 | 34 | 35 | public void Initialize(GraphicsDevice graphicsDevice) 36 | { 37 | _spriteBatch = new SpriteBatch(graphicsDevice); 38 | 39 | _camera = new Camera(new Vector3(15,-15,12), new Vector3(0,0,0)); 40 | } 41 | 42 | public void Load(ContentManager contentManager) 43 | { 44 | _contentManager = new ThreadSafeContentManager(contentManager.ServiceProvider) {RootDirectory = "Content"}; 45 | 46 | rollTexture2D = _contentManager.Load("Graphical User Interface/ring"); 47 | 48 | } 49 | 50 | public void CenterModel() 51 | { 52 | modelPosition = Vector3.Zero; 53 | modelRotation = Matrix.Identity; 54 | 55 | defaultphi = 0; 56 | } 57 | 58 | private void MouseEvents(Camera camera, ref Vector3 position) 59 | { 60 | if (!DebugScreen.ConsoleOpen && Input.WasKeyPressed(Keys.Space)) 61 | { 62 | CenterModel(); 63 | } 64 | if (Input.mouseState.ScrollWheelValue != Input.mouseLastState.ScrollWheelValue) 65 | { 66 | camera.DistanceFromCenter += ((float)(Input.mouseState.ScrollWheelValue - Input.mouseLastState.ScrollWheelValue)/100); 67 | camera.DistanceFromCenter = camera.DistanceFromCenter.Clamp(0.01f, 1000); 68 | 69 | Vector3 length = (camera.Position - camera.Lookat); 70 | length.Normalize(); 71 | //camera.Forward = new Vector3(x, y, z); 72 | camera.Position = camera.Lookat + length*camera.DistanceFromCenter; 73 | } 74 | if (Input.mouseState.RightButton == ButtonState.Pressed) 75 | { 76 | if (!GameSettings.RotateOrbit) 77 | { 78 | float mouseAmount = 0.01f; 79 | 80 | Vector3 direction = camera.Forward; 81 | direction.Normalize(); 82 | 83 | Vector3 normal = Vector3.Cross(direction, camera.Up); 84 | 85 | float y = Input.mouseState.Y - Input.mouseLastState.Y; 86 | float x = Input.mouseState.X - Input.mouseLastState.X; 87 | 88 | y *= GameSettings.g_ScreenHeight/800.0f; 89 | x *= GameSettings.g_ScreenWidth/1280.0f; 90 | 91 | camera.Forward += x*mouseAmount*normal; 92 | 93 | camera.Forward -= y*mouseAmount*camera.Up; 94 | camera.Forward.Normalize(); 95 | } 96 | else 97 | { 98 | var tan = Math.Atan2(-camera.Forward.X, -camera.Forward.Y); 99 | 100 | //lookat 101 | 102 | //tan += (float)(_mouseState.X - _lastMouseState.X) / 60; 103 | 104 | //Convert into spherical coordinates. 105 | var x = camera.Forward.X; 106 | var y = camera.Forward.Y; 107 | var z = camera.Position.Z; 108 | 109 | var r = camera.DistanceFromCenter; //Math.Sqrt(x*x + y*y + z*z); 110 | var tau = Math.Acos(z/r); 111 | var phi = Math.Atan2(y, x); 112 | 113 | phi += (Input.mouseState.X - Input.mouseLastState.X)/60.0f; 114 | if(!Input.IsKeyDown(Keys.LeftControl)) 115 | tau = (tau + (Input.mouseState.Y - Input.mouseLastState.Y)/100.0f).Clamp(0.01f, Math.PI - 0.1f); 116 | 117 | //Convert back 118 | x = (float) (r*Math.Sin(tau)*Math.Cos(phi)); 119 | y = (float) (r*Math.Sin(tau)*Math.Sin(phi)); 120 | z = (float) (r*Math.Cos(tau)); 121 | 122 | //camera.Forward = new Vector3(x, y, 0); 123 | camera.Position = camera.Lookat + new Vector3(-x, -y, z); 124 | camera.Forward = (camera.Lookat - camera.Position); 125 | 126 | if (!Input.IsKeyDown(Keys.LeftAlt)) 127 | { 128 | r = modelPosition.Length(); //Math.Sqrt(x*x + y*y + z*z); 129 | tau = Math.Acos(modelPosition.Z / r); 130 | phi = Math.Atan2(modelPosition.Y, modelPosition.X); 131 | 132 | phi += (Input.mouseState.X - Input.mouseLastState.X) / 60.0f; 133 | tau = (tau + (Input.mouseState.Y - Input.mouseLastState.Y) / 100.0f).Clamp(0.01f, Math.PI - 0.1f); 134 | 135 | //Convert back 136 | x = (float)(r * Math.Sin(tau) * Math.Cos(phi)); 137 | y = (float)(r * Math.Sin(tau) * Math.Sin(phi)); 138 | z = modelPosition.Z;// (float)(r * Math.Cos(tau)); 139 | modelPosition = new Vector3(x,y,z); 140 | } 141 | 142 | if (Input.IsKeyDown(Keys.LeftShift)) 143 | { 144 | defaultphi += (Input.mouseState.X - Input.mouseLastState.X) / 60.0f; 145 | modelRotation = Matrix.CreateRotationZ((float) (defaultphi)); 146 | } 147 | } 148 | } 149 | if (Input.mouseState.LeftButton == ButtonState.Pressed) 150 | { 151 | float x = (Input.mouseState.X - Input.mouseLastState.X) / 1000.0f * camera.DistanceFromCenter; 152 | float y = -(Input.mouseState.Y - Input.mouseLastState.Y) / 1000.0f * camera.DistanceFromCenter; 153 | 154 | Vector3 normal = Vector3.Cross(camera.Up, camera.Forward); 155 | Vector3 realup = Vector3.Cross(normal, camera.Forward); 156 | 157 | normal.Normalize(); 158 | realup.Normalize(); 159 | 160 | position += normal * x + realup * y; 161 | //camera.Position += normal * x + realup * y; 162 | 163 | } 164 | 165 | } 166 | 167 | public void Update(GameTime gameTime) 168 | { 169 | if(!GUIControl.UIWasUsed) 170 | MouseEvents(_camera, ref modelPosition); 171 | } 172 | 173 | public void Draw(GameTime gameTime) 174 | { 175 | 176 | } 177 | 178 | public void Unload() 179 | { 180 | string MGCBpathDirectory = Application.StartupPath + "/Content/Runtime"; 181 | DirectoryInfo di = new DirectoryInfo(MGCBpathDirectory); 182 | 183 | foreach (FileInfo file in di.GetFiles()) 184 | { 185 | file.Delete(); 186 | } 187 | foreach (DirectoryInfo dir in di.GetDirectories()) 188 | { 189 | dir.Delete(true); 190 | } 191 | 192 | _contentManager.Dispose(); 193 | } 194 | 195 | public Camera GetCamera() 196 | { 197 | return _camera; 198 | } 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /ModelViewer/ModelViewer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Xna.Framework; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using Microsoft.Xna.Framework.Input; 5 | using ModelViewer.Logic; 6 | using ModelViewer.Static; 7 | 8 | namespace ModelViewer 9 | { 10 | /// 11 | /// This is the main type for your game. 12 | /// 13 | public class ModelViewer : Game 14 | { 15 | readonly GraphicsDeviceManager _graphics; 16 | SpriteBatch _spriteBatch; 17 | 18 | private ScreenManager _screenManager; 19 | private bool _isActive = true; 20 | 21 | public ModelViewer() 22 | { 23 | _graphics = new GraphicsDeviceManager(this); 24 | Content.RootDirectory = "Content"; 25 | 26 | _screenManager = new ScreenManager(); 27 | 28 | //Set up graphics properties, no vsync, no framelock 29 | _graphics.SynchronizeWithVerticalRetrace = false; 30 | IsFixedTimeStep = true; 31 | //TargetElapsedTime = TimeSpan.FromMilliseconds(100); 32 | 33 | //Size of our application / starting back buffer 34 | _graphics.PreferredBackBufferWidth = GameSettings.g_ScreenWidth; 35 | _graphics.PreferredBackBufferHeight = GameSettings.g_ScreenHeight; 36 | 37 | _graphics.PreferMultiSampling = true; 38 | _graphics.PreferredBackBufferFormat = SurfaceFormat.Color; 39 | _graphics.PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8; 40 | 41 | //_graphics.PreferredDepthStencilFormat = DepthFormat.Depth24; 42 | //HiDef enables usable shaders 43 | _graphics.GraphicsProfile = GraphicsProfile.HiDef; 44 | 45 | _graphics.ApplyChanges(); 46 | 47 | //Mouse should not disappear 48 | IsMouseVisible = true; 49 | 50 | //Window settings 51 | Window.AllowUserResizing = true; 52 | Window.IsBorderless = false; 53 | 54 | //Update all our rendertargets when we resize 55 | Window.ClientSizeChanged += ClientChangedWindowSize; 56 | 57 | //Update framerate etc. when not the active window 58 | Activated += IsActivated; 59 | Deactivated += IsDeactivated; 60 | } 61 | private void IsActivated(object sender, EventArgs e) 62 | { 63 | Input.mouseState = Mouse.GetState(); 64 | _isActive = true; 65 | } 66 | 67 | private void IsDeactivated(object sender, EventArgs e) 68 | { 69 | _isActive = false; 70 | } 71 | 72 | /// 73 | /// Update rendertargets and backbuffer when resizing window size 74 | /// 75 | private void ClientChangedWindowSize(object sender, EventArgs e) 76 | { 77 | if (GraphicsDevice.Viewport.Width != _graphics.PreferredBackBufferWidth || 78 | GraphicsDevice.Viewport.Height != _graphics.PreferredBackBufferHeight) 79 | { 80 | if (Window.ClientBounds.Width == 0) return; 81 | //_graphics.PreferredBackBufferWidth = Window.ClientBounds.Width; 82 | //_graphics.PreferredBackBufferHeight = Window.ClientBounds.Height; 83 | 84 | //_graphics.ApplyChanges(); 85 | 86 | GameSettings.g_ScreenWidth = Window.ClientBounds.Width; 87 | GameSettings.g_ScreenHeight = Window.ClientBounds.Height; 88 | 89 | _screenManager.UpdateResolution(); 90 | } 91 | } 92 | 93 | /// 94 | /// Allows the game to perform any initialization it needs to before starting to run. 95 | /// This is where it can query for any required services and load any non-graphic 96 | /// related content. Calling base.Initialize will enumerate through any components 97 | /// and initialize them as well. 98 | /// 99 | protected override void Initialize() 100 | { 101 | // TODO: Add your initialization logic here 102 | 103 | base.Initialize(); 104 | } 105 | 106 | /// 107 | /// LoadContent will be called once per game and is the place to load 108 | /// all of your content. 109 | /// 110 | protected override void LoadContent() 111 | { 112 | // Create a new SpriteBatch, which can be used to draw textures. 113 | _spriteBatch = new SpriteBatch(GraphicsDevice); 114 | 115 | _screenManager.Load(Content, GraphicsDevice); 116 | 117 | _screenManager.Initialize(GraphicsDevice); 118 | // TODO: use this.Content to load your game content here 119 | } 120 | 121 | /// 122 | /// UnloadContent will be called once per game and is the place to unload 123 | /// game-specific content. 124 | /// 125 | protected override void UnloadContent() 126 | { 127 | // TODO: Unload any non ContentManager content here 128 | _screenManager.Unload(Content); 129 | } 130 | 131 | /// 132 | /// Allows the game to run logic such as updating the world, 133 | /// checking for collisions, gathering input, and playing audio. 134 | /// 135 | /// Provides a snapshot of timing values. 136 | protected override void Update(GameTime gameTime) 137 | { 138 | // TODO: Add your update logic here 139 | 140 | 141 | _screenManager.Update(gameTime, _isActive); 142 | 143 | if (!_isActive) return; 144 | 145 | if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || 146 | Input.WasKeyPressed(Keys.Escape)) 147 | { 148 | UnloadContent(); 149 | Exit(); 150 | } 151 | 152 | base.Update(gameTime); 153 | } 154 | 155 | /// 156 | /// This is called when the game should draw itself. 157 | /// 158 | /// Provides a snapshot of timing values. 159 | protected override void Draw(GameTime gameTime) 160 | { 161 | if (!_isActive) return; 162 | 163 | //GraphicsDevice.Clear(new Color(GameSettings.testvaluer, GameSettings.testvalueg, GameSettings.testvalueb)); 164 | GraphicsDevice.Clear(GameSettings.bgColor); 165 | _screenManager.Draw(gameTime); 166 | 167 | //// TODO: Add your drawing code here 168 | 169 | base.Draw(gameTime); 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /ModelViewer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ModelViewer 4 | { 5 | #if WINDOWS || LINUX 6 | /// 7 | /// The main class. 8 | /// 9 | public static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | using (var game = new ModelViewer()) 18 | game.Run(); 19 | } 20 | } 21 | #endif 22 | } 23 | -------------------------------------------------------------------------------- /ModelViewer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("ModelViewer")] 8 | [assembly: AssemblyProduct("ModelViewer")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyCopyright("Copyright TheKosmonaut© 2017")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("8a6c4f83-5833-4727-bc3a-934115d3f09d")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /ModelViewer/Renderer/ShaderModules/AmbientOcclusionShader.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Content; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using ModelViewer.Renderer.ShaderModules.Helper; 5 | 6 | /* 7 | Copyright 2017 by kosmonautgames 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 10 | to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 16 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 17 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 18 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | */ 20 | 21 | namespace ModelViewer.Renderer.ShaderModules 22 | { 23 | /// 24 | /// A shader to draw a uniform color across a mesh 25 | /// 26 | public class AmbientOcclusionShader 27 | { 28 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | // Variables 30 | 31 | private GraphicsDevice _graphicsDevice; 32 | private QuadRenderer _quadRenderer; 33 | 34 | private Effect _shaderEffect; 35 | 36 | private EffectParameter _resolutionParameter; 37 | private EffectParameter _inverseResolutionParameter; 38 | private EffectParameter _frustumCornersParameter; 39 | private EffectParameter _samplesParameter; 40 | private EffectParameter _sampleRadiusParameter; 41 | private EffectParameter _sampleStrengthParameter; 42 | 43 | private EffectParameter _depthMapParameter; 44 | private EffectParameter _targetMapParameter; 45 | 46 | private EffectPass _ssaoPass; 47 | private EffectPass _blurVerticalPass; 48 | private EffectPass _blurHorizontalPass; 49 | 50 | private Vector3[] _frustumCorners; 51 | 52 | public Vector3[] FrustumCorners 53 | { 54 | get { return _frustumCorners; } 55 | set 56 | { 57 | _frustumCorners = value; 58 | _frustumCornersParameter.SetValue(_frustumCorners); 59 | } 60 | } 61 | 62 | private Texture2D _depthMap; 63 | public Texture2D DepthMap 64 | { 65 | get { return _depthMap; } 66 | set 67 | { 68 | if (_depthMap != value) 69 | { 70 | _depthMap = value; 71 | _depthMapParameter.SetValue(_depthMap); 72 | } 73 | } 74 | } 75 | 76 | private Texture2D _targetMap; 77 | public Texture2D TargetMap 78 | { 79 | get { return _targetMap; } 80 | set 81 | { 82 | if (_targetMap != value) 83 | { 84 | _targetMap = value; 85 | _targetMapParameter.SetValue(_targetMap); 86 | } 87 | } 88 | } 89 | 90 | private Vector2 _resolution; 91 | 92 | public Vector2 Resolution 93 | { 94 | get { return _resolution; } 95 | set 96 | { 97 | _resolution = value; 98 | _resolutionParameter.SetValue(_resolution); 99 | _inverseResolutionParameter.SetValue(Vector2.One/_resolution); 100 | } 101 | } 102 | 103 | private int _samples; 104 | 105 | public int Samples 106 | { 107 | get { return _samples; } 108 | set 109 | { 110 | _samples = value; 111 | _samplesParameter.SetValue(_samples); 112 | } 113 | } 114 | 115 | private float _sampleRadii; 116 | 117 | public float SampleRadii 118 | { 119 | get { return _sampleRadii; } 120 | set 121 | { 122 | _sampleRadii = value; 123 | _sampleRadiusParameter.SetValue(_sampleRadii); 124 | } 125 | } 126 | 127 | private float _sampleStrength; 128 | 129 | public float SampleStrength 130 | { 131 | get { return _sampleStrength; } 132 | set 133 | { 134 | _sampleStrength = value; 135 | _sampleStrengthParameter.SetValue(_sampleStrength); 136 | } 137 | } 138 | 139 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 140 | // Functions 141 | 142 | /// 143 | /// Needs to be called to load all the shader fx files 144 | /// 145 | /// 146 | /// 147 | public void Load(ContentManager content, string shaderPath) 148 | { 149 | _shaderEffect = content.Load(shaderPath); 150 | 151 | _resolutionParameter = _shaderEffect.Parameters["Resolution"]; 152 | _inverseResolutionParameter = _shaderEffect.Parameters["InverseResolution"]; 153 | _frustumCornersParameter = _shaderEffect.Parameters["FrustumCorners"]; 154 | _samplesParameter = _shaderEffect.Parameters["Samples"]; 155 | _sampleRadiusParameter = _shaderEffect.Parameters["SampleRadius"]; 156 | _sampleStrengthParameter = _shaderEffect.Parameters["Strength"]; 157 | 158 | _depthMapParameter = _shaderEffect.Parameters["DepthMap"]; 159 | _targetMapParameter = _shaderEffect.Parameters["TargetMap"]; 160 | 161 | _ssaoPass = _shaderEffect.Techniques["SSAO"].Passes[0]; 162 | _blurVerticalPass = _shaderEffect.Techniques["BilateralVertical"].Passes[0]; 163 | _blurHorizontalPass = _shaderEffect.Techniques["BilateralHorizontal"].Passes[0]; 164 | } 165 | 166 | public void Initialize(GraphicsDevice graphicsDevice) 167 | { 168 | _graphicsDevice = graphicsDevice; 169 | _quadRenderer = new QuadRenderer(); 170 | } 171 | 172 | public void DrawAmbientOcclusion() 173 | { 174 | _ssaoPass.Apply(); 175 | _quadRenderer.RenderQuad(_graphicsDevice, -Vector2.One, Vector2.One); 176 | } 177 | 178 | internal void BlurAmbientOcclusion(RenderTarget2D ao, RenderTarget2D blur0, RenderTarget2D blur1) 179 | { 180 | TargetMap = ao; 181 | 182 | _graphicsDevice.SetRenderTarget(blur0); 183 | _blurVerticalPass.Apply(); 184 | _quadRenderer.RenderQuad(_graphicsDevice, -Vector2.One, Vector2.One); 185 | 186 | _graphicsDevice.SetRenderTarget(blur1); 187 | TargetMap = blur0; 188 | _blurHorizontalPass.Apply(); 189 | _quadRenderer.RenderQuad(_graphicsDevice, -Vector2.One, Vector2.One); 190 | 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /ModelViewer/Renderer/ShaderModules/Helper/QuadRenderer.cs: -------------------------------------------------------------------------------- 1 | 2 | #region Using Statements 3 | 4 | using Microsoft.Xna.Framework; 5 | using Microsoft.Xna.Framework.Graphics; 6 | 7 | #endregion 8 | 9 | namespace ModelViewer.Renderer.ShaderModules.Helper 10 | { 11 | public class QuadRenderer 12 | { 13 | //buffers for rendering the quad 14 | private readonly VertexPositionTexture[] _vertexBuffer; 15 | private readonly short[] _indexBuffer; 16 | 17 | public QuadRenderer() 18 | { 19 | _vertexBuffer = new VertexPositionTexture[4]; 20 | _vertexBuffer[0] = new VertexPositionTexture(new Vector3(-1, 1, 1), new Vector2(0, 0)); 21 | _vertexBuffer[1] = new VertexPositionTexture(new Vector3(1, 1, 1), new Vector2(1, 0)); 22 | _vertexBuffer[2] = new VertexPositionTexture(new Vector3(-1, -1, 1), new Vector2(0, 1)); 23 | _vertexBuffer[3] = new VertexPositionTexture(new Vector3(1, -1, 1), new Vector2(1, 1)); 24 | 25 | _indexBuffer = new short[] { 0, 3, 2, 0, 1, 3 }; 26 | } 27 | 28 | public void RenderQuad(GraphicsDevice graphicsDevice, Vector2 v1, Vector2 v2) 29 | { 30 | _vertexBuffer[0].Position.X = v1.X; 31 | _vertexBuffer[0].Position.Y = v2.Y; 32 | 33 | _vertexBuffer[1].Position.X = v2.X; 34 | _vertexBuffer[1].Position.Y = v2.Y; 35 | 36 | _vertexBuffer[2].Position.X = v1.X; 37 | _vertexBuffer[2].Position.Y = v1.Y; 38 | 39 | _vertexBuffer[3].Position.X = v2.X; 40 | _vertexBuffer[3].Position.Y = v1.Y; 41 | 42 | graphicsDevice.DrawUserIndexedPrimitives 43 | (PrimitiveType.TriangleList, _vertexBuffer, 0, 4, _indexBuffer, 0, 2); 44 | } 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ModelViewer/Renderer/ShaderModules/Skybox.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Content; 3 | using Microsoft.Xna.Framework.Graphics; 4 | 5 | namespace ModelViewer.Renderer.ShaderModules 6 | { 7 | public class SkyboxRenderModule 8 | { 9 | private Effect _shaderEffect; 10 | private GraphicsDevice _graphicsDevice; 11 | 12 | private VertexBuffer _sphereVertexBuffer; 13 | private IndexBuffer _sphereIndexBuffer; 14 | private int _spherePrimitiveCount; 15 | 16 | private EffectParameter _worldViewProjParameter; 17 | private EffectParameter _worldParameter; 18 | private EffectParameter _skyboxTexture; 19 | 20 | private EffectPass _drawSkyboxPass; 21 | 22 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 23 | // Functions 24 | 25 | public void Initialize(GraphicsDevice graphicsDevice) 26 | { 27 | _graphicsDevice = graphicsDevice; 28 | } 29 | 30 | /// 31 | /// Needs to be called to load all the shader fx files 32 | /// 33 | /// 34 | /// The path in our content to the shader file, for example "Shaders/Skybox" 35 | /// should be of size 1 36 | public void Load(ContentManager content, string shaderPath, string sphereLoadingPath) 37 | { 38 | _shaderEffect = content.Load(shaderPath); 39 | 40 | _worldViewProjParameter = _shaderEffect.Parameters["WorldViewProj"]; 41 | _worldParameter = _shaderEffect.Parameters["World"]; 42 | _skyboxTexture = _shaderEffect.Parameters["SkyboxTexture"]; 43 | 44 | _drawSkyboxPass = _shaderEffect.Techniques["DrawSkybox"].Passes[0]; 45 | 46 | ModelMeshPart sphere = content.Load(sphereLoadingPath).Meshes[0].MeshParts[0]; 47 | _sphereIndexBuffer = sphere.IndexBuffer; 48 | _sphereVertexBuffer = sphere.VertexBuffer; 49 | _spherePrimitiveCount = sphere.PrimitiveCount; 50 | } 51 | 52 | public void SetSkybox(TextureCube cubemap) 53 | { 54 | _skyboxTexture.SetValue(cubemap); 55 | } 56 | 57 | 58 | public void Draw(Matrix viewProjection, Vector3 origin, float size) 59 | { 60 | _graphicsDevice.SetVertexBuffer(_sphereVertexBuffer); 61 | _graphicsDevice.Indices = (_sphereIndexBuffer); 62 | int primitiveCount = _spherePrimitiveCount; 63 | 64 | Matrix world = Matrix.CreateScale(size) * Matrix.CreateTranslation(origin); 65 | 66 | _worldViewProjParameter.SetValue(world * viewProjection); 67 | _worldParameter.SetValue(world); 68 | 69 | _drawSkyboxPass.Apply(); 70 | 71 | _graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, primitiveCount); 72 | } 73 | } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /ModelViewer/Static/Extension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ModelViewer.Static 4 | { 5 | public static class Extension 6 | { 7 | 8 | public static T Clamp(this T val, T min, T max) where T : IComparable 9 | { 10 | if (val.CompareTo(min) < 0) return min; 11 | if (val.CompareTo(max) > 0) return max; 12 | return val; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /ModelViewer/Static/GameSettings.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | 3 | namespace ModelViewer.Static 4 | { 5 | public static class GameSettings 6 | { 7 | public static int ShowDisplayInfo = 3; 8 | 9 | public static int g_ScreenWidth = 1280; 10 | public static int g_ScreenHeight = 800; 11 | public static bool ui_DrawUI = true; 12 | 13 | public static bool ui_debug = false; 14 | 15 | public static Color bgColor = Color.White; 16 | public static float g_FarPlane = 500; 17 | public static bool RotateOrbit = true; 18 | public static bool m_orientationy = true; 19 | public static float m_size = 1; 20 | public static float m_roughness = 0.8f; 21 | public static float m_metallic = 0.0f; 22 | 23 | public static bool r_UseLinear = true; 24 | public static bool m_startClip = true; 25 | public static bool m_updateAnimation = true; 26 | public static bool ao_Enable = true; 27 | public static bool r_DrawDepthMap = false; 28 | public static bool d_log = true; 29 | public static int ao_Samples = 16; 30 | public static float ao_Radii = 1; 31 | public static float ao_Strength = 2; 32 | public static bool r_DrawAoMap; 33 | public static bool ao_UseStencil = true; 34 | public static bool ao_UseBlur = true; 35 | public static bool ao_HalfRes = true; 36 | public static float pomScale = 0.3f; 37 | public static bool r_UsePOM = false; 38 | public static bool r_POMCutoff = true; 39 | public static float r_POMQuality = 1; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ModelViewer/Static/GameStats.cs: -------------------------------------------------------------------------------- 1 | namespace ModelViewer.Static 2 | { 3 | public static class GameStats 4 | { 5 | public static string Version = "Version 0.6"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ModelViewer/Static/ScreenManager.cs: -------------------------------------------------------------------------------- 1 | using HelperSuite.GUIRenderer; 2 | using Microsoft.Xna.Framework; 3 | using Microsoft.Xna.Framework.Content; 4 | using Microsoft.Xna.Framework.Graphics; 5 | using ModelViewer.Logic; 6 | 7 | namespace ModelViewer.Static 8 | { 9 | /// 10 | /// Manages our different screens and passes information accordingly 11 | /// 12 | public class ScreenManager 13 | { 14 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | // VARIABLES 16 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | private DebugScreen _debug; 19 | private GuiLogicSample _guiLogicSample; 20 | private MainLogic _mainLogic; 21 | private GUIRenderer _guiRenderer; 22 | private Renderer.Renderer _renderer; 23 | 24 | //private bool _wasInactive = true; 25 | 26 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | // FUNCTIONS 28 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | 30 | public void Initialize(GraphicsDevice graphicsDevice) 31 | { 32 | _debug.Initialize(graphicsDevice); 33 | _mainLogic.Initialize(graphicsDevice); 34 | _guiRenderer.Initialize(graphicsDevice, GameSettings.g_ScreenWidth, GameSettings.g_ScreenHeight); 35 | _guiLogicSample.Initialize(_mainLogic); 36 | _renderer.Initialize(graphicsDevice); 37 | } 38 | 39 | //Update per frame 40 | public void Update(GameTime gameTime, bool isActive) 41 | { 42 | //if (!isActive) 43 | //{ 44 | // _wasInactive = true; 45 | // return; 46 | //} 47 | 48 | //if (_wasInactive) 49 | //{ 50 | // Input.mouseLastState = Mouse.GetState(); 51 | // _wasInactive = false; 52 | //} 53 | 54 | 55 | Input.Update(gameTime); 56 | 57 | _guiLogicSample.Update(gameTime); 58 | 59 | _mainLogic.Update(gameTime); 60 | 61 | _debug.Update(gameTime); 62 | } 63 | 64 | //Load content 65 | public void Load(ContentManager content, GraphicsDevice graphicsDevice) 66 | { 67 | _debug = new DebugScreen(); 68 | _debug.LoadContent(content); 69 | 70 | _mainLogic = new MainLogic(); 71 | _mainLogic.Load(content); 72 | 73 | _guiRenderer = new GUIRenderer(); 74 | _guiRenderer.Load(content); 75 | 76 | _guiLogicSample = new GuiLogicSample(); 77 | _guiLogicSample.Load(content); 78 | 79 | _renderer = new Renderer.Renderer(); 80 | _renderer.Load(content); 81 | } 82 | 83 | public void Unload(ContentManager content) 84 | { 85 | content.Dispose(); 86 | _mainLogic.Unload(); 87 | } 88 | 89 | public void Draw(GameTime gameTime) 90 | { 91 | _renderer.Draw(_mainLogic.GetCamera(), _mainLogic, _mainLogic.modelPosition, _mainLogic.modelRotation, gameTime); 92 | 93 | _mainLogic.Draw(gameTime); 94 | 95 | //Our renderer gives us information on what id is currently hovered over so we can update / manipulate objects in the logic functions 96 | _debug.Draw(gameTime); 97 | 98 | _guiRenderer.Draw(_guiLogicSample.getCanvas()); 99 | } 100 | 101 | public void UpdateResolution() 102 | { 103 | _guiLogicSample.UpdateResolution(); 104 | _renderer.UpdateRenderTargets(); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /ModelViewer/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | true/pm 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Modelviewer for Monogame 2 | 3 | ## Features: 4 | 5 | - Import a variety of .obj and .fbx files. They must contain texture coordinates. A mesh cannot have different materials for submeshes (yet?). 6 | - Meshes without normals are supported. Meshes without texcoords/uv are supported, too, but they won't display textures. 7 | - Skinned Meshes with up to 4 bones per vertex are supported 8 | - Animated Skinned Meshes 9 | - plausible environment lighting, with support for 4 texture inputs - albedo, normal, roughness, metallic (no alpha yet) 10 | - HBAO solution 11 | - Parallax Occlusion Mapping 12 | - Intuitive UI 13 | 14 | ## Controls 15 | 16 | - LMB drag the object 17 | - RMB -rotate around the object 18 | - Shift+RMB - rotate the environment 19 | - MW - zoom in/out 20 | - space - center object 21 | 22 | 23 | ## Discussion Thread 24 | http://community.monogame.net/t/3d-model-viewer-for-monogame-ver-0-6/8696 25 | 26 | 27 | ## Version history: 28 | 29 | 0.6 - Added Parallax Occlusion mapping to textures. Added the ability to shift-right click to rotate the sky. Added button to center model. 30 | 0.7 - added mip mapping again 31 | 32 | 33 | Cubemaps from 34 | http://www.humus.name/index.php?page=Textures 35 | 36 | by Emil Persson, licensed under Creative Commons Attribution 3.0 Unported License. 37 | 38 | --------------------------------------------------------------------------------