How to draw every characters with spritefont in monogame - c#

I'm new to monogame, and I'm trying to make a .spritefont file in order to draw string with the font I choose.
Strings with English characters can show well on the screen, but I wish to draw strings in multiple languages, like Japanese and Chinese.
So, I tried to load all characters in a Multi Language Font "Microsoft JhengHei".
The font's first character is !(U+0021) and the last one is ○(U+FFEE).
But when I tried to compile the program, the compiler gave me an error:
.../Content/MyFont.spritefont : error : Importer 'FontDescriptionImporter' had unexpected failure!
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: CharacterRegion.End must be greater than CharacterRegion.Start
at Microsoft.Xna.Framework.Content.Pipeline.Graphics.FontDescription.set_CharacterRegions(CharacterRegion[] value)
And when I changed the ○ to 忮, MSBuild stucks and takes forever to proceed the content.
Code in MyFont.spritefont below:
<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="Graphics:FontDescription">
<FontName>Microsoft JhengHei</FontName>
<Size>14</Size>
<Spacing>0</Spacing>
<UseKerning>true</UseKerning>
<Style>Regular</Style>
<CharacterRegions>
<CharacterRegion>
<Start>!</Start>
<End>○</End>
</CharacterRegion>
</CharacterRegions>
</Asset>
</XnaContent>
I searched for the solution for a few days but in vain, any help is appreciated.

I was not able to reproduce the steps of the accepted answer from J3soon in Monogame 3.7.1.
However in Monogame 3.7.1, it is not longer necessary to use the Custom Content Pipeline because the pipeline tool now natively contains a LocalizedFontProcessor.
My steps were :
Set the .spritefont Processor to LocalizedFontProcessor in the pipeline tool
In the .spritefont, include the path to the resx file.
In the .spritefont, replace Asset Type="Graphics:FontDescription" with Asset Type="Graphics:LocalizedFontDescription"
Rebuild the Content
I would have thought step #1 would have done #3 behind the scenes but for me it was necessary to do this both in the pipeline tool and the .spritefont file.
spritefont file
<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="Graphics:LocalizedFontDescription">
<FontName>Arial</FontName>
<Size>16</Size>
<Spacing>2</Spacing>
<UseKerning>true</UseKerning>
<Style>Regular</Style>
<CharacterRegions>
<CharacterRegion>
<Start> </Start>
<End>~</End>
</CharacterRegion>
</CharacterRegions>
<ResourceFiles>
<Resx>..\Strings.fr.resx</Resx>
</ResourceFiles>
</Asset>
</XnaContent>
Content file
#begin MyFont.spritefont
/importer:FontDescriptionImporter
/processor:LocalizedFontProcessor
/processorParam:PremultiplyAlpha=True
/processorParam:TextureFormat=Compressed
/build:MyFont.spritefont

Since processing all 65 thousand characters takes too much time. We should only process the characters we are using.
So the easiest way is to make a MonoGame Custom Content Pipeline and load the characters we are using by some .resx files.
It took me so much time searching for this solution. So I'll post how did I succeed, hope it can help someone who has the same question in the future.
Step-by-step Tutorial
Create a Class Library.
Reference the MonoGame.Framework.Content.Pipeline.Portable package using NuGet. (Make sure you checked the Include Prerelease checkbox )
Download the LocalizationSample here and unzip the file.
Under LocalizationPipeline\ copy LocalizedFontDescription.cs and LocalizedFontProcessor.cs into the class library
Build the class library so it outputs a LocalizationPipeline.dll file.
Open Myfont.spritefont and change its Asset Type to LocalizationPipeline.LocalizedFontDescription
Then add the resources <ResourceFiles><Resx>..\strings.resx</Resx></ResourceFiles> (these files should contain the string we want to draw)
Open Content.mgcb and reference to LocalizationPipeline.dll
Set the MyFont.spritefont's processor to LocalizedFontProcessor
ReBuild the project.
MyFont.spritefont
<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="LocalizationPipeline.LocalizedFontDescription">
<FontName>Microsoft JhengHei</FontName>
<Size>14</Size>
<Spacing>0</Spacing>
<UseKerning>true</UseKerning>
<Style>Regular</Style>
<CharacterRegions>
<CharacterRegion>
<Start> </Start>
<End>~</End>
</CharacterRegion>
</CharacterRegions>
<ResourceFiles>
<Resx>..\strings.resx</Resx>
</ResourceFiles>
</Asset>
</XnaContent>
Content.mgcb
...
#-------------------------------- References --------------------------------#
/reference:..\LocalizationPipeline.dll
#---------------------------------- Content ---------------------------------#
...
#begin MyFont.spritefont
/importer:FontDescriptionImporter
/processor:LocalizedFontProcessor
/build:MyFont.spritefont
...
Sources
Part 1 of Creating custom content importers for the MonoGame Pipeline
How to: Create a Localized Game
LocalizationSample (Thanks to #Groo for giving me this link.)

Related

C# XML documentation '<include>' tag not appearing in intellisense?

I developing a C# class library in Visual Studio, and I have been making use of XML Documentation Comments primarily for their integration with Intellisense. However, the bulk of comments has become quite cluttered, so now I am endeavoring to use the <include> tag, and an external XML document to reduce the clutter.
My issue is that when using the <include> tag Intellisense seems to not update with the information, not show any of the <summary> and <param> tags that I've assigned to some of my classes and methods.
For Example I could have a class 'Test' documented as shown:
/// <include file="docs.xml" path='extradoc/class[#name="Test"]/*' />
class Test { string foo = "bar"; }
And have docs.xml:
<?xml version="1.0" encoding="utf-8" ?>
<extradoc>
<class name="Test">
<summary>
Contains some Foo.
</summary>
</class>
</extradoc>
And upon build the output XML populates correctly:
<?xml version="1.0"?>
<doc>
<assembly>
<name>Example Program</name>
</assembly>
<members>
<member name="T:Example_Program.Program.Test">
<summary>
Contains some Foo.
</summary>
</member>
</members>
</doc>
The only issue is that, try as I might, this documentation will not appear in the intellisense boxes while appending my code. Is there some Visual Studio configuration setting I'm missing? I've scoured the msn documentation to no avail.
My issue is that when using the tag Intellisense seems to
not update with the information, not show any of the and
tags that I've assigned to some of my classes and methods.
1.Avoid that your issue is being not able to see summary in Intellisense in current project A.
You can get help from this document, this technology is used to provide better reading experience. So assuming you have the Test class in current priject A, when you see the content in VS code editor, you'll see something like:
It's expected behavior that you won't see that rich comments in project A any more cause they have been moved to docs.xml.
2.If you mean when you create a new Project B(or share the assembly to other developers), the Intellisense can't recognize your Test class.
Two possible causes:
1.The output xx.dll and xx.xml from project A are not in the same folder, so when you reference that xx.dll in your new project, Intellisense won't display the documentation comments.
2.I guess there's something wrong with your docs.xml file. (I can't find any official document which indicates this technology supports user-defined nodes like extradoc and class in docs.xml, I used these two nodes and the Intellisense did not work, after changing them to normal docs and members, it works now)
Try using docs.xml and include in this way:
<?xml version="1.0" encoding="utf-8" ?>
<docs>
<members name="MyTests">
<Test>
<summary>
This class is public, but do nothing
</summary>
<remarks>
Just write something here to indicate this is remarks.
</remarks>
</Test>
</members>
</docs>
and
/// <include file="docs.xml" path='docs/members[#name="MyTests"]/Test/*' />
public class Test { }
I suggest you use a public class to test... After that create a new project and reference that xx.dll, when calling Test class you can see the summary:
And if we F12 we can see detailed comments:
Hope it helps :)

c# autocad dllimport by autocad version

i have been using the the program from "Detecting entities under cursor while selection is running" By Philippe Leefsma located here1. it worked in ACAD2014 however now we are using ACAD2016. it will not work because of the DLLImport of acdb19.dll and autocad2016 needs acdb20.dll. Is there a way to make the program load eighter dll version? i tried using netload and assembly.loadfrom and neither worked.
Point Monitor callback
The DLL import is set at compile time so the best bet is to compile two versions for each release of AutoCAD.
Once the project is compiled, you could set up an autoloader by creating an application.bundle folder. this folder can be placed in c:\programdata\Autodesk\applicationPlugins. In the application.bundle folder, create a subfolder called Application and place the compiled .DLL file in there.
The loader is controlled with an XML file which should be named PackageContents.xml. Here's some example code for the xml file:-
<?xml version="1.0" encoding="utf-8"?>
<ApplicationPackage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Name="My AutoCAD App"
Description="Does something in AutoCAD"
Icon="./Application/MyIcon.ico"
Author="Paul Nelson">
<CompanyDetails Name="Paul Nelson"
Url="http://www.stackoverflow.com"
Email="myemail#email.com">
</CompanyDetails>
<Components>
<!-- define the min and max versions of AutoCA in the next line -->
<RuntimeRequirements OS="Win64" Platform="AutoCAD" SeriesMin="R19.0" SeriesMax="R22.0" />
<ComponentEntry
ModuleName=".\Application\MyApp.dll"
LoadOnAutoCADStartup="true"
LoadOnCommandInvocation="false"
AppDescription="This is assembly MyApp."
AppName="My AutoCAD App"
AppType=".NET">
<Commands GroupName="My Apps">
<Command Local="MYAPP" Global="MYAPP" />
</Commands>
</ComponentEntry>
</Components>
</ApplicationPackage>
One last tip - make sure the .dll filename does not contain spaces.

Missing stylable field MvxExpandableListView_GroupItemTemplate

I've noticed the following MvxBind info message being output to logcat while debugging on Android:
Missing stylable field MvxExpandableListView_GroupItemTemplate
I've tried adding the MvxBindingAttributes.xml file from GitHub to the DroidProject\Resources\values folder and set the Build Action to AndroidResource. This causes a compiler error for each <declare-stylable> XML tag like:
Attribute "XXX" has already been defined
It's interesting because it claims MvxGroupItemTemplate is already defined when I compile, yet when I run the program a message is displayed saying it's missing.
What should I do to fix this?
I had the same problem this morning when updating to the latest version of Xamarin Studio. Fixed it for now by including this:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<declare-styleable name="MvxExpandableListView">
<attr name="GroupItemTemplate" format="reference"/>
</declare-styleable>
</resources>
In the Resources\values\attrs.xml file.

CA1701 / Custom Dictionary

In the CustomDictionary.xml, where / how do I put my entry to avoid these two warnings from VS2015 Code Analysis?
Warning CA1701 In resource 'xxx.yyy.Properties.Resources.resx',
referenced by name 'LoggerMustSpecifyFilename' the discrete term
'Filename' in string value 'Filename must be specified.' should be
expressed as a compound word. If 'Filename' refers to an API
identifier, case it as 'FileName', otherwise split it into two words
separated by a space.
Warning CA1701 In resource 'xxx.yyy.Properties.Resources.resx',
referenced by name 'LoggerInvalidFilename' the discrete term
'filename' in string value 'The specified filename '{0}' is invalid.'
should be expressed as a compound word. If 'filename' refers to an API
identifier, case it as 'fileName', otherwise split it into two words
separated by a space.
I don't want to suppress CA1701, nor do I want to change my string casing. I used the CustomDictionary.xml to block a few other warnings and those all work fine, just can't get rid of these last two.
The problem is that Code Analysis uses it's own CustomDictionary, located at C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\FxCop or equivalent.
These can't be overridden with your own dictionary. There is a user voice for this issue.
For Filename in particular, it's this that is causing your problem:
<?xml version="1.0" encoding="utf-8" ?>
<Dictionary>
<Words>
<Unrecognized>
<!-- .. snip .. -->
</Unrecognized>
<Recognized>
<!-- .. snip .. -->
</Recognized>
<Deprecated>
<!-- .. snip .. -->
</Deprecated>
<Compound>
<!-- .. snip .. -->
<Term CompoundAlternate="FileName">filename</Term>
<!-- .. snip .. -->
</Compound>
<DiscreteExceptions>
<!-- .. snip .. -->
</DiscreteExceptions>
</Words>
<Acronyms>
<CasingExceptions>
<!-- .. snip .. -->
</CasingExceptions>
</Acronyms>
</Dictionary>
(I've snipped the items out of the default dictionary that aren't relevant, there is a lot more)
You can either:
Suppress the message
Change your casing to match this custom dictionary
Edit this default dictionary. This is particularly troublesome, as you would need to keep this in sync on all developer machines and on the build server.

Trouble referencing a file in a visual studio project on a unit test

I'm having quite a bit of trouble in resolving an issue dealing with referencing a custom text file in my project. NOTE: the file contains text, but its of a custom type '.rit'
I'm currently building and running some test cases for a new application and one of them involves reading a file that resides in a sample folder of my project called 'TestFiles'. At first, I ran the test locally using the absolute path of the file and it ran with no issues. However, I am using TFS to check in my code and once the test runs in the server it fails immediately because it can't locate the file, which was obvious because I was using an absolute path to a file in my local drive, so I NEED to change how the test accesses this file to make it work both locally and on the server.
I've looked at a look of examples as I was looking for help but none seem to work... I've tried:
DeploymentItem:
[DeploymentItem(#"TestProject\TestFiles\test file.rit", "TestData")]
[TestMethod]
public void LoadFileTest()
{
//Assert.IsTrue(File.Exists("test file.rit"));
var obj = new obj();
var tstFile = #"TestData\\test file.rit";
var file = new StreamReader(tstFile);
obj.OpenRitFileInTextFormat(file);
}
The hierarchy of the file is: Solution\TestProject\TestFiles\test file.rit and I made sure to set the Copy to Output to "copy always"
Adding it as a Resource:
//[DeploymentItem(#"TestProject\\TestFiles\\test file.rit", "TestData")]
[TestMethod]
public void LoadFileTest()
{
//Assert.IsTrue(File.Exists("test file.rit"));
var obj = new obj();
var tstFile = Properties.Resources.test_file;
//this one throws an error however because it says the type of tstFile is now
//a byte[] instead of a stream reader
*var file = new StreamReader(tstFile);*
obj.OpenRitFileInTextFormat(file);
}
I'm not very experienced in this one, so I might be doing something wrong... If anyone could please enlighten me or give me some guidance as to where else I could look for help I would GREATLY appreciate it!
Thanks,
EDIT: I have found out my TestData folder I'm specifying to be copied in the DeploymentItem path is not being created/copied to the Out folder of the test run. I'm starting to think this is more of a settings file problem, here's the contents of my settings file:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<!-- Configurations that affect the Test Framework -->
<RunConfiguration>
<!-- Path relative to solution directory -->
<ResultsDirectory>.\TestResults</ResultsDirectory>
<!-- [x86] | x64
- You can also change it from menu Test, Test Settings, Default Processor Architecture -->
<TargetPlatform>x86</TargetPlatform>
<!-- Framework35 | [Framework40] | Framework45 -->
<TargetFrameworkVersion>Framework40</TargetFrameworkVersion>
</RunConfiguration>
<!-- Configurations for data collectors -->
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Configuration>
<CodeCoverage>
<ModulePaths>
<Exclude>
<ModulePath>.*CPPUnitTestFramework.*</ModulePath>
</Exclude>
</ModulePaths>
</CodeCoverage>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
<!-- Adapter Specific sections -->
<!-- MSTest adapter -->
<MSTest>
<MapInconclusiveToFailed>True</MapInconclusiveToFailed>
<CaptureTraceOutput>false</CaptureTraceOutput>
<DeleteDeploymentDirectoryAfterTestRunIsComplete>False</DeleteDeploymentDirectoryAfterTestRunIsComplete>
<DeploymentEnabled>True</DeploymentEnabled>
</MSTest>
</RunSettings>
When using the # modifier you shouldn't escape the backslashes. So use either [DeploymentItem("TestProject\\TestFiles\\test file.rit", "TestData")] or [DeploymentItem(#"TestProject\TestFiles\test file.rit", "TestData")]. The second version is preferable.
From my experience, if a file is added to the project at its root level, then it can be referenced just by [DeploymentItem("file.xyz")] in the test case. So in your case [DeploymentItem(#"TestFiles\test file.rit", "TestData")] should be fine.
You also need to remember to "Enable deployment" in "Solution items" -> Local.testsettings:

Categories

Resources