<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Блог Дмитрия Андреева [MSFT]</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/dmandreev/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/dmandreev/feed.xml</link>
    <description>Driving perception change.</description>
    <lastBuildDate>Tue, 16 Apr 2019 05:48:53 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Анонс продуктовой линейки Visual Studio 2015</title>
      <link>https://docs.microsoft.com/archive/blogs/dmandreev/visual-studio-2015</link>
      <pubDate>Thu, 02 Apr 2015 01:51:00 GMT</pubDate>
      <dc:creator><![CDATA[Dmitry Andreev]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmandreev/2015/04/02/visual-studio-2015/</guid>
      <description><![CDATA[Мы продолжаем улучшать возможности инструментария Visual Studio в области продуктивности, делая их...]]></description>
      <content:encoded><![CDATA[<p>Мы продолжаем улучшать возможности инструментария Visual Studio в области продуктивности, делая их более простыми в использовании, вне зависимости от того, какую платформу вы используете, какие приложения создаете. Так же мы хотели бы упростить выбор редакции, которая подходит для вашей разработки. В ноябре прошлого года мы сделали Visual Studio Community 2013 бесплатной для некорпоративного использования. Сегодня мы анонсируем редакции Visual Studio 2015 которые будут доступны после релиза этим летом. Возможности редакции Visual Studio и Visual Studio Ultimate теперь включены в Visual Studio Enterprise с MSDN. В эту редакцию входит вся мощь, с которой вы знакомы по Visual Studio Ultimate вместе с инновациями, которые появились в версии 2015. Теперь, в дополнение к Visual Studio Community и Visual Studio Professional с MSDN, новая редакция Visual Studio Enterprise включает три основных предложения по Visual Studio 2015. <img src="https://picturedata.blob.core.windows.net/pcconv/qq7zme8n8gtou2_6s0ropolt.png" alt="" />Редакции Visual Studio Professional, Team Foundation Server, Team Foundation Server Express и Visual Studio Express, и MSDN Platforms остаются неизменными.</p>
<h4>Получение Visual Studio 2015 и цены</h4>
<p>Пользователи, у которых активна подписка на Visual Studio Premium с MSDN или Visual Studio Ultimate с MSDN получат автоматический апгрейд до Visual Studio Enterprise с MSDN. Цена на Visual Studio Enteprise с MSDN будет значительно снижена по сравнению с текущей ценой Visual Studio Ultimate с MSDN. Посмотрите раздел <a href="https://www.visualstudio.com/ru-ru/products/vs-2015-product-editions">Visual Studio 2015 Produt Editions</a> для более детальной информации по ценам, включая действующие предложения по скидкам. Если вы еще не попробовали Visual Studio 2015, самое время сделать это сейчас. Вы можете <a title="загрузить Visual Studio 2015 CTP 6" href="https://www.visualstudio.com/en-us/downloads/visual-studio-2015-ctp-vs">загрузить Visual Studio 2015 CTP 6</a> и протестировать новые возможности. Не забывайте оставить свой отзыв с помощью наших ресурсов. (<a href="https://visualstudio.uservoice.com/forums/121579-visual-studio/category/35066-ide">UserVoice</a>, <a href="https://go.microsoft.com/fwlink/?LinkId=517102">Send-a-Smile</a>, или <a href="https://connect.microsoft.com/VisualStudio">Connect</a>).</p>]]></content:encoded>
    </item>
    <item>
      <title>Как загрузить локализованные скриншоты для каждого языка в Windows Phone Store</title>
      <link>https://docs.microsoft.com/archive/blogs/dmandreev/23</link>
      <pubDate>Mon, 14 Jul 2014 04:04:12 GMT</pubDate>
      <dc:creator><![CDATA[Dmitry Andreev]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmandreev/2014/07/14/23/</guid>
      <description><![CDATA[В свойствах приложения определяем поддерживаемые культуры:


Это создаст записи в файле...]]></description>
      <content:encoded><![CDATA[<p>В свойствах приложения определяем поддерживаемые культуры:</p>
<p><img src="https://litehtmlconv.azurewebsites.net/api/pics/lgk8o349272trqtn98_y4tcj" alt="" /></p>
<ul>
<li>Это создаст записи в файле WpAppMainfest.xml</li>
</ul>
<p>&nbsp; <span style="font-family: courier new,courier;">&lt;DefaultLanguage xmlns="" code="en-US" /&gt;</span><br /><span style="font-family: courier new,courier;">&nbsp; &lt;Languages xmlns=""&gt;</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; &lt;Language code="en-US" /&gt;</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; &lt;Language code="ru-RU" /&gt;</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; &lt;Language code="ru" /&gt;</span><br /><span style="font-family: courier new,courier;">&nbsp; &lt;/Languages&gt;</span></p>
<p>Далее после загрузки вашего xap в стор, у вас будет возможность манипулировать отдельными наборами свойств для каждой локали:</p>
<p><img src="https://litehtmlconv.azurewebsites.net/api/pics/1aadfdgvtcibg6z0-vqtpm8re" alt="" /></p>
<p><img src="https://litehtmlconv.azurewebsites.net/api/pics/i38q3uw-megcm97mx02ia6ww" alt="" /></p>
<p>&nbsp;</p>
<p>Где после секции текстовых описаний, будет раздел с скриншотами. Переключая локаль, вы можете загрузить локализованные сеты изображений для каждого определенного вами языка. <img src="https://litehtmlconv.azurewebsites.net/api/pics/1fsrhicu4btdwn-cup-10p9zi" alt="" /></p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>How To: Create Unity3d WinRT Plugin.</title>
      <link>https://docs.microsoft.com/archive/blogs/dmandreev/how-to-create-unity3d-winrt-plugin</link>
      <pubDate>Tue, 01 Oct 2013 12:09:00 GMT</pubDate>
      <dc:creator><![CDATA[Dmitry Andreev]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmandreev/2013/10/01/how-to-create-unity3d-winrt-plugin/</guid>
      <description><![CDATA[Documentation from Unity 4.2 contains too small info about WinRT plugins. Let&rsquo;s fix this by...]]></description>
      <content:encoded><![CDATA[<p>Documentation from Unity 4.2 contains <a title="too small info about WinRT plugins" href="https://docs.unity3d.com/Documentation/Manual/windowsstore-plugins.html" target="_blank">too small info about WinRT plugins</a>. Let&rsquo;s fix this by this tutorial.</p>
<p>1)&nbsp;Create empty unity project:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/6886.image001.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/6886.image001.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/6886.image001.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/6886.image001.png" alt="" border="0" /></a><br />2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Create folders in Assets &ndash; Plugins and Metro (under Plugins).<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/1830.image002.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/1830.image002.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/1830.image002.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/1830.image002.png" alt="" border="0" /></a><br />3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; We will try to call plugin function from empty GameObject. Create it:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/7762.image003.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/7762.image003.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/7762.image003.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/7762.image003.png" alt="" border="0" /></a><br />4)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; And create C# script:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/6114.image004.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/6114.image004.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/6114.image004.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/6114.image004.png" alt="" border="0" /></a><br />5)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Then bind it to empty GameObject (by drag&amp;dropping script to Inspector window).<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/5187.image005.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/5187.image005.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/5187.image005.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/5187.image005.png" alt="" border="0" /></a><br />6)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Now check, that everything is ok:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/6523.image006.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/6523.image006.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/6523.image006.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/6523.image006.png" alt="" border="0" /></a><br />7)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Play&nbsp;scene and notice log message from console:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/4762.image007.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/4762.image007.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/4762.image007.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/4762.image007.png" alt="" border="0" /></a><br />8)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Now it&rsquo;s time to create Windows 8 Runtime plugin. Create new Windows Store apps library. I recommend to do it in unity project folder:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/0247.image008.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/0247.image008.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/0247.image008.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/0247.image008.png" alt="" border="0" /></a><br />9)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Configure paths for output:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/8625.image009.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/8625.image009.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/8625.image009.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/8625.image009.png" alt="" border="0" /></a><br />10)&nbsp;&nbsp; And check that everything is ok &ndash; compile project and check Assets/Plugins/Metro folder from Unity:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/1220.image010.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/1220.image010.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/1220.image010.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/1220.image010.png" alt="" border="0" /></a></p>
<p>11)&nbsp;&nbsp; Now add additional project (windows class library) to this solution &ndash; Stub dll that runs under unity editor. <br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/2084.image011.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/2084.image011.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/2084.image011.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/2084.image011.png" alt="" border="0" /></a><br />12)&nbsp;&nbsp; Stub contains only design time functions, but can share most of our plugin code. To reference original plugin.cs, create link from "Add existing File Menu" in this project as link. (Tanks Adam Tuliper&nbsp;for tip).<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/7127.add_as_link.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/7127.add_5F00_as_5F00_link.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/7127.add_as_link.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/7127.add_5F00_as_5F00_link.png" alt="" width="310" height="123" border="0" /></a><br />13)&nbsp;&nbsp; Next step is make some changes of project properties. Make assembly name and default namespace same as WinRTPlugin project and change target framework to version 3.5. <br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/3618.image016.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/3618.image016.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/3618.image016.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/3618.image016.png" alt="" border="0" /></a><br />14)&nbsp;&nbsp; Also point output dir to Assets/Plugins<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/3644.image017.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/3644.image017.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/3644.image017.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/3644.image017.png" alt="" border="0" /></a><br />15)&nbsp;&nbsp; Delete reference to Microsoft.CSharp assembly:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/1513.image018.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/1513.image018.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/1513.image018.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/1513.image018.png" alt="" border="0" /></a><br />16)&nbsp;&nbsp; Close plugin.cs editor tab and doubleclick plugin.cs from Stub project, and surround references from Windows Runtime using NETFX_CORE condition.<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/2627.image019.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/2627.image019.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/2627.image019.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/2627.image019.png" alt="" border="0" /></a><br />17)&nbsp;&nbsp; Now, build Stub project and check that output dll placed to Assets/Plugins.<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/0447.image020.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/0447.image020.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/0447.image020.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/0447.image020.png" alt="" border="0" /></a><br />18)&nbsp;&nbsp; It&rsquo;s time to call our plugin function. Edit your unity script and add plugin instance &amp; function call:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/7384.image021.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/7384.image021.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/7384.image021.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/7384.image021.png" alt="" border="0" /></a><br />19)&nbsp;&nbsp; Open plugin.cs from WinRTPlugin project and add some windows 8 functions:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/4645.image022.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/4645.image022.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/4645.image022.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/4645.image022.png" alt="" border="0" /></a><br />20)&nbsp;&nbsp; Build you project from Unity:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/4382.image023.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/4382.image023.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/4382.image023.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/4382.image023.png" alt="" border="0" /></a><br />21)&nbsp;&nbsp; Open your unity solution from Visual Studio and check that it references WinRTPlugin.dll:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/5657.image024.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/5657.image024.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/5657.image024.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/5657.image024.png" alt="" border="0" /></a><br />22)&nbsp;&nbsp; Run your app and check that everything is ok:<br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/8244.image025.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/8244.image025.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/05/8244.image025.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-05/8244.image025.png" alt="" border="0" /></a></p>
<p>&nbsp;</p>
<p><br />You can download sample code from here <a href="https://sdrv.ms/18LcwIo">https://sdrv.ms/18LcwIo</a><br />&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Обнаружение утечек памяти в приложении Javascript для Windows 8 с помощью инструмента Javascript Memory Analysis из пакета Visual Studio</title>
      <link>https://docs.microsoft.com/archive/blogs/dmandreev/43</link>
      <pubDate>Thu, 11 Jul 2013 23:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Dmitry Andreev]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmandreev/2013/07/11/43/</guid>
      <description><![CDATA[Язык Javascript прекрасно подходит для разработки приложений для Windows 8. Javascript&nbsp;&mdash;...]]></description>
      <content:encoded><![CDATA[<p>Язык <strong>Javascript</strong> прекрасно подходит для разработки приложений для Windows 8. <strong>Javascript</strong>&nbsp;&mdash; нетипизированный динамический язык программирования, обеспечивающий высокую гибкость. Однако без должной внимательности, вы можете допустить утечки памяти в своем коде.</p>
<p>Но вы зря волнуетесь по этому поводу,&nbsp;<strong>Visual Studio</strong>&nbsp;содержит эффективный инструмент под названием <strong>Javascript Memory Analysis</strong>,&nbsp;который помогает обнаружить утечки памяти.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/8204.image_32004984.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/8204.image_5F00_32004984.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/4643.image_thumb_2AE39DBD.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/4643.image_5F00_thumb_5F00_2AE39DBD.png" alt="image" width="722" height="415" border="0" /></a></p>
<h1>Рекомендации по применению инструмента Javascript Memory Analysis</h1>
<p>Этот инструмент запускается из меню&nbsp;<strong>Debug</strong> (Отладка)&nbsp;в&nbsp;<strong>Visual Studio</strong>:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/8787.image_55BE9280.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/8787.image_5F00_55BE9280.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/2818.image_thumb_057C;.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/2818.image_5F00_thumb_5F00_057C3B00.png" alt="image" width="868" height="186" border="0" /></a></p>
<p>После запуска инструмента, запустится и ваше приложение, на экране вы увидите следующее:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/1325.image_2048610C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/1325.image_5F00_2048610C.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/3808.image_thumb_5006098B.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/3808.image_5F00_thumb_5F00_5006098B.png" alt="image" width="948" height="606" border="0" /></a></p>
<p>В первой области окна в режиме реального времени отображается объем памяти, используемой приложением:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/8272.image_18BF8250.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/8272.image_5F00_18BF8250.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/6622.image_thumb_14490189.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/6622.image_5F00_thumb_5F00_14490189.png" alt="image" width="678" height="120" border="0" /></a></p>
<p>Ниже присутствует кнопка <em>Take Heap Snapshot</em> (Создание мгновенного снимка кучи), используемая для создания мгновенного снимка &laquo;кучи&raquo; (элемент управления также показывает размер &laquo;кучи&raquo; и количество активных объектов):</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/0456.image_4CF3AB96.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/0456.image_5F00_4CF3AB96.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/6523.image_thumb_53A945CA.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/6523.image_5F00_thumb_5F00_53A945CA.png" alt="image" width="1056" height="680" border="0" /></a></p>
<p>По щелчку на размере &laquo;кучи&raquo; выводится более подробная информация:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/7128.image_3C119857.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/7128.image_5F00_3C119857.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/5732.image_thumb_2B99275C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/5732.image_5F00_thumb_5F00_2B99275C.png" alt="image" width="864" height="575" border="0" /></a></p>
<p>Это список объектов, отсортированный с учетом объема удерживаемой памяти,&nbsp;<strong>таким образом, объекты, потребляющие больше всего памяти, которую можно высвободить, будут вверху списка.</strong></p>
<p>На примере моего приложения, я вижу, что объект&nbsp;<em>UrzaGatherer</em>&nbsp;удерживает около&nbsp;<strong>60&nbsp;МБ</strong> памяти (так и должно быть, поскольку в нем хранится огромный список&nbsp;<a href="https://blogs.msdn.com/b/eternalcoding/archive/2012/08/20/how-to-cook-a-windows-8-application-with-html5-javascrip-css3-rtm-version.aspx">карт)</a>:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/5224.image_301238D4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/5224.image_5F00_301238D4.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/0434.image_thumb_3895981E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/0434.image_5F00_thumb_5F00_3895981E.png" alt="image" width="1022" height="579" border="0" /></a></p>
<p>Это представление также позволяет вывести на экран:</p>
<ul>
<li>список типов, отсортированный по количеству вхождений;</li>
<li>список корневых объектов (с точки зрения сборщика мусора);</li>
<li>список объектов&nbsp;<strong>DOM</strong>,&nbsp;отсортированный по объему удерживаемой памяти;</li>
<li>список объектов&nbsp;<strong>WinRT</strong>,&nbsp;отсортированный по объему удерживаемой памяти.</li>
</ul>
<p>Эти представления помогут вам обнаружить случаи&nbsp;<strong>нецелесообразного</strong>&nbsp;использования памяти.</p>
<h1>Сравнение моментальных снимков</h1>
<p>После каждого нажатия кнопки&nbsp;<em>Take Heap Snapshot</em> (Создание мгновенного снимка кучи) система генерирует новый дамп &laquo;кучи&raquo; с целью последующего анализа. Кроме того, каждый новый снимок позволяет оценить динамику изменения размера &laquo;кучи&raquo; и количества объектов.</p>
<p>Это&nbsp;<strong>основной</strong> инструмент поиска утечек памяти.</p>
<p>В своем приложении я сделаю первый снимок, перейду на данную страницу, затем вернусь на главную и, наконец, сделаю второй снимок. Таким образом я смогу определить, присутствует ли утечки памяти на интересующей меня странице.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/2313.image_3D0EA996.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/2313.image_5F00_3D0EA996.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/0841.image_thumb_411B8819.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/0841.image_5F00_thumb_5F00_411B8819.png" alt="image" width="664" height="325" border="0" /></a></p>
<p>Сравнив два моментальных снимка, я обнаружил, что&nbsp;размер &laquo;кучи&raquo; увеличился на <strong>6,12&nbsp;МБ</strong>,&nbsp;кроме того, были созданы&nbsp;<strong>53&nbsp;000&nbsp;</strong>объектов, которые не были в дальнейшем удалены.&nbsp;</p>
<p>Щелкнув значение, показывающее изменение размера &laquo;кучи&raquo; (+6,12&nbsp;МБ), вы можете получить более подробную информацию о различиях между двумя моментальными снимками:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/6523.image_16CEE0EF.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/6523.image_5F00_16CEE0EF.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/5633.image_thumb_0892F8B0.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/5633.image_5F00_thumb_5F00_0892F8B0.png" alt="image" width="1024" height="293" border="0" /></a></p>
<p>Представление Dominators (Доминаторы) показывает, что новые объекты не были удалены после того, как мы вернулись на домашнюю страницу. Это представление поможет вам обнаружить ненужные объекты.</p>
<p>В моем случае подозрительной кажется первая строка. Щелкнув ее правой кнопкой мыши, я могу перейти к представлению Root (Корень), чтобы увидеть, какая функция хранит эти объекты:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/8666.image_485F6FE6.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/8666.image_5F00_485F6FE6.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/4137.image_thumb_60F19DE7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/4137.image_5F00_thumb_5F00_60F19DE7.png" alt="image" width="1024" height="415" border="0" /></a></p>
<p>Как видите, объект удерживается функцией&nbsp;<em>ImportFromTappedOut</em>.</p>
<p>Эта глобальная функция в моем коде принимает функцию в качестве параметра:</p>
<pre class="scroll"><code class="js">ImportFromTappedOut = function (deckName, custom) {</code></pre>
<p>Параметр <em>custom&nbsp;</em>эта функция использует для вызова специализированного пользовательского кода. Главная проблема связана с тем, что&nbsp;<em>ImportFromTappedOut</em>&nbsp;&mdash; глобальная функция, и она хранит весь код, к которому обращается функция, в параметре&nbsp;<em>custom</em>.&nbsp;В этом случае моя анонимная функция ссылается на большое количество локальных объектов DOM:</p>
<pre class="scroll"><code class="js">Tools.ImportFromTappedOut("test", function () { var select = document.querySelector("#addToDeck"); <br /> var count = document.querySelector("#addToDeckCount").value; <br /> listView.selection.getItems().then(function (items) { appBar.hide(); <br /> appBar.sticky = false; listView.selection.clear();</code></pre>
<pre class="scroll">&nbsp;</pre>
<pre class="code"><span><em>&hellip;code continue&hellip;</em></span></pre>
<p>Эту проблему мне помог обнаружить рассматриваемый инструмент:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/5633.image_1DA92678.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/5633.image_5F00_1DA92678.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/0743.image_thumb_222237F0.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/0743.image_5F00_thumb_5F00_222237F0.png" alt="image" width="647" height="125" border="0" /></a></p>
<p>Решение простое: достаточно вызвать&nbsp;<em>importFromTappedOut</em>&nbsp;с нулевой функцией, когда я закрываю страницу, чтобы сборщик мусора удалил все сохраненные объекты (в этом случае освободится 1,25&nbsp;МБ).</p>
<p>Я настоятельно рекомендую вам использовать этот инструмент для выявления и предотвращения утечек памяти. Несмотря на свою простоту, он очень эффективен.</p>
<h1>Подробнее о рассматриваемом инструменте</h1>
<p><span style="font-size: 12px;">Следующие статьи также могут быть вам полезны:</span></p>
<ul style="font-size: 12px;">
<li><a href="https://blogs.msdn.com/b/visualstudio/archive/2013/02/04/10388914.aspx">JavaScript memory analysis for Windows Store apps in Visual Studio 2012</a></li>
<li><a href="https://blogs.msdn.com/b/eternalcoding/archive/2012/11/15/optimizing-javascript-windows-8-application-using-the-visual-studio-performance-analysis-tool-profiler.aspx">Optimizing JavaScript Windows 8 application: Using the Visual Studio performance analysis tool (profiler)</a></li>
<li><a href="https://blogs.msdn.com/b/eternalcoding/archive/2012/08/20/how-to-cook-a-windows-8-application-with-html5-javascrip-css3-rtm-version.aspx">How to cook a Windows 8 application with HTML5/Javascript/CSS3</a></li>
<li><a href="https://blogs.msdn.com/b/eternalcoding/archive/2012/03/22/unleash-the-power-of-html-5-canvas-for-gaming-part-1.aspx">Unleash the power of HTML 5 Canvas for gaming</a></li>
<li>[Французский]<a title="https://www.microsoft.com/france/mstechdays/programmes/2013/fiche-session.aspx?ID=f721312a-cc92-4599-8795-cfe07d5c0bb4" href="https://www.microsoft.com/france/mstechdays/programmes/2013/fiche-session.aspx?ID=f721312a-cc92-4599-8795-cfe07d5c0bb4">https://www.microsoft.com/france/mstechdays/programmes/2013/fiche-session.aspx?ID=f721312a-cc92-4599-8795-cfe07d5c0bb4</a></li>
</ul><div style="clear:both;"></div><img src="https://blogs.msdn.com/aggbug.aspx?PostID=10432653" width="1" height="1">]]></content:encoded>
    </item>
    <item>
      <title>[Статья нашего гостя] Советы и рекомендации по IntelliTrace. Основы. Часть 1. Автор: Колин Дембовский (Colin Dembovsky)</title>
      <link>https://docs.microsoft.com/archive/blogs/dmandreev/10</link>
      <pubDate>Tue, 09 Jul 2013 23:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Dmitry Andreev]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmandreev/2013/07/09/10/</guid>
      <description><![CDATA[Рекомендации по применению IntelliTrace
Варианты применения инструмента IntelliTrace:

Во время...]]></description>
      <content:encoded><![CDATA[<p><strong>Рекомендации по применению IntelliTrace</strong></p>
<p>Варианты применения инструмента IntelliTrace:</p>
<ol>
<li><span style="font-size: 12px;">Во время отладки в VS нажатием клавиши F5.</span></li>
<li><span style="font-size: 12px;">В Test Manager (доступен как адаптер диагностических данных&nbsp;&mdash; Data Diagnostic Adapter).</span></li>
<li><span style="font-size: 12px;">При запуске из любого места (использование автономного сборщика данных).</span></li>
</ol>
<p><strong>Описание &laquo;режимов работы&raquo; IntelliTrace</strong></p>
<p>В IntelliTrace реализовано два стандартных режима с широкими возможностями: Events Only (Только события) и Events and Call Information (События и сведения о вызовах). Режим Events Only&nbsp;&mdash; упрощенный, он позволяет регистрировать &laquo;события&raquo;, которые происходят во время выполнения вашей программы. Эти события представляют собой заслуживающие интереса &laquo;происшествия&raquo;, например вызовы ASP.NET или ADO.NET, а&nbsp;также исключения. Группа разработки продукта постаралась записать события, которые помогут понять, как ваш код работает, и проследить длинные цепочки &laquo;причин и следствий&raquo;.</p>
<p>Режим Events and Call Information&nbsp;&mdash; расширенный режим отладки, при котором помимо сведений, относящихся к режиму Events Only, регистрируются также вызовы методов (включая входящие и исходящие аргументы). Для подлежащих сбору данных установлены некоторые ограничения, иначе размер журналов будет просто огромным, даже больше, чем с настройками по умолчанию.</p>
<p><strong>Использование клавиши F5 при работе с IntelliTrace</strong></p>
<p>Этот вариант подходит для использования в процессе разработки кода. Это означает, что можно отлаживать приложение, перемещаясь вперед и назад в сеансе отладки, при этом нет необходимости останавливать приложение или добавлять точки останова. Активировать отладчик можно в настройках IntelliTrace: Tools&nbsp;-&gt; Options (Сервис -&gt; Параметры). Предусмотрено два режима:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/2630.clip_image001_23E65B87.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/2630.clip_5F00_image001_5F00_23E65B87.png"><img title="clip_image001" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/0081.clip_image001_thumb_0069B722.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/0081.clip_5F00_image001_5F00_thumb_5F00_0069B722.png" alt="clip_image001" width="377" height="264" border="0" /></a></p>
<p>После активации (в данном случае я включил режим Events and Call Information) отладчик готов к&nbsp;использованию. Понажимайте кнопки в своем приложении и щелкните ссылку Break All (Приостановить все) в VS в окне IntelliTrace:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/0763.clip_image002_63A01C3F.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/0763.clip_5F00_image002_5F00_63A01C3F.png"><img title="clip_image002" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/3276.clip_image002_thumb_132E14FF.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/3276.clip_5F00_image002_5F00_thumb_5F00_132E14FF.png" alt="clip_image002" width="396" height="224" border="0" /></a></p>
<p>(Я отлаживаю свое приложение Calculator. Нажимаю Break All (Приостановить все) и открывают журнал IntelliTrace.)</p>
<p>Изначально в журнале отображаются все произошедшие события. В нашем случае нажатия кнопок относятся к&nbsp;событиям типа Gesture (Жест), поэтому в журнале мы видим:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/5165.clip_image003_28C84D9C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/5165.clip_5F00_image003_5F00_28C84D9C.png"><img title="clip_image003" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/1460.clip_image003_thumb_30240D49.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/1460.clip_5F00_image003_5F00_thumb_5F00_30240D49.png" alt="clip_image003" width="199" height="320" border="0" /></a></p>
<p>Предположим, что нечто странное произошло, когда я нажал &laquo;=&raquo;, перемножая два числа. Перезапускать приложение нет необходимости, я могу просто нажать кнопку &laquo;=&raquo; после &laquo;*&raquo; (из записи в журнале видно, что я нажал 3&nbsp;х 6&nbsp;=). Я могу нажать это событие и &laquo;перемотать&raquo; до интересующего меня момента.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/5481.clip_image004_7A5EA221.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/5481.clip_5F00_image004_5F00_7A5EA221.png"><img title="clip_image004" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/2577.clip_image004_thumb_1DCB20BA.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/2577.clip_5F00_image004_5F00_thumb_5F00_1DCB20BA.png" alt="clip_image004" width="244" height="208" border="0" /></a></p>
<p>Сейчас я могу нажать Calls View (Представление вызовов) и приступить к просмотру журнала с этой точки.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/4628.clip_image005_7A4E7C54.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/4628.clip_5F00_image005_5F00_7A4E7C54.png"><img title="clip_image005" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/4442.clip_image005_thumb_0F7C81FD.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/4442.clip_5F00_image005_5F00_thumb_5F00_0F7C81FD.png" alt="clip_image005" width="340" height="162" border="0" /></a></p>
<p>Дважды щелкните вызов btnEqual_Click для перехода к этому моменту выполнения. Вы увидите глифы IntelliTrace во внутреннем поле окна исходного кода:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/1373.clip_image006_7DDC7164.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/1373.clip_5F00_image006_5F00_7DDC7164.png"><img title="clip_image006" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/2555.clip_image006_thumb_48EF6C27.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/2555.clip_5F00_image006_5F00_thumb_5F00_48EF6C27.png" alt="clip_image006" width="361" height="162" border="0" /></a></p>
<p>Если навести указатель мыши на значки, система выдаст подсказку. Функции появляются в следующем порядке:</p>
<p>&middot; return to calling method</p>
<p>&middot; step back</p>
<p>&middot; step into</p>
<p>&middot; step over</p>
<p>&middot; return to Live Debugging</p>
<p>(Небольшая подсказка: при нажатии кнопки return to Live Debugging (Возврат к динамической отладке) внизу, вы перейдете к текущей точке отладчика, и для повторного запуска приложения следует опять нажать клавишу&nbsp;F5.)</p>
<p>Если вы нажмете F11, текущий указатель переместится вперед. Нажав эту кнопку дважды, я перешел к точке, где в программе стоит оператор Switch:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/2475.clip_image007_73E75A2C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/2475.clip_5F00_image007_5F00_73E75A2C.png"><img title="clip_image007" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/1616.clip_image007_thumb_5B944011.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/1616.clip_5F00_image007_5F00_thumb_5F00_5B944011.png" alt="clip_image007" width="406" height="202" border="0" /></a></p>
<p>Обратите внимание: мне не придется гадать, какой именно оператор Case был выбран, достаточно посмотреть запись в журнале. Я также поставил метки для обработчиков наведения и убирания курсора мыши для val1 и&nbsp;val2, вы можете увидеть эти значения. Не все значения отслеживаются, но в данном случае это исходящие или входящие примитивы метода, поэтому IntelliTrace успешно регистрирует их значения.</p>
<p>Я опять нажму клавишу F11, чтобы войти в метод Multiply(), а затем еще раз, чтобы перейти к следующему событию:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/8623.clip_image008_712E78AE.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/8623.clip_5F00_image008_5F00_712E78AE.png"><img title="clip_image008" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/7853.clip_image008_thumb_1BBA33BF.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/7853.clip_5F00_image008_5F00_thumb_5F00_1BBA33BF.png" alt="clip_image008" width="444" height="252" border="0" /></a></p>
<p>Я перешел к закрывающейся фигурной скобке метода Multiply. В окне Autos показаны параметры val1 и val2 и&nbsp;их значения (3 и 6, соответственно), а также значение, возвращаемое методом (9).</p>
<p>Вуаля! 3&ndash;4 клика, и мы нашли ошибку в своей программе. И нам даже не пришлось задавать точку останова!</p>
<p><strong>Фильтрация событий</strong></p>
<p>IntelliTrace регистрирует большое количество событий, поэтому, чтобы упростить навигацию по журналу, можно использовать категорию, поток и окно поиска в верхней части окна событий для фильтрации событий.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/3146.clip_image009_5F41BF14.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/3146.clip_5F00_image009_5F00_5F41BF14.png"><img title="clip_image009" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/4024.clip_image009_thumb_74DBF7B1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/4024.clip_5F00_image009_5F00_thumb_5F00_74DBF7B1.png" alt="clip_image009" width="304" height="224" border="0" /></a></p>
<p>Например, в выпадающем списке All Categories (Все категории) я могу выбрать фильтр, чтобы отображались только исключения:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/5482.clip_image010_4635C902.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/5482.clip_5F00_image010_5F00_4635C902.png"><img title="clip_image010" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/7360.clip_image010_thumb_2DE2AEE7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/7360.clip_5F00_image010_5F00_thumb_5F00_2DE2AEE7.png" alt="clip_image010" width="266" height="295" border="0" /></a></p>
<p><strong>Поиск строки</strong></p>
<p>Также рекомендую использовать функцию поиска строки (Search For this line) или метода (Search For This Method). Вы подозреваете, что метод был выполнен во время отладки, но читать весь журнал нет времени? Никаких проблем! Щелкните правой кнопкой мыши строку (или метод) и выберите Search For This Line/Method in IntelliTrace (Поиск для этой строки/метода в IntelliTrace).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/2402.clip_image011_7F3C8037.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/2402.clip_5F00_image011_5F00_7F3C8037.png"><img title="clip_image011" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/8611.clip_image011_thumb_2CFA2330.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/8611.clip_5F00_image011_5F00_thumb_5F00_2CFA2330.png" alt="clip_image011" width="484" height="352" border="0" /></a></p>
<p>После чего вы увидите результаты поиска на панели в верхней части текущего окна кода. Используйте стрелки для перехода к предыдущему или следующему экземпляру этой строки или метода в файле журнала:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/3704.clip_image012_4F8E3BDE.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/3704.clip_5F00_image012_5F00_4F8E3BDE.png"><img title="clip_image012" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/5340.clip_image012_thumb_45E5CDA8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/5340.clip_5F00_image012_5F00_thumb_5F00_45E5CDA8.png" alt="clip_image012" width="327" height="112" border="0" /></a></p>
<p>Я щелкну по значку стрелки сразу после слова Multiply, чтобы перейти к первому вызову этого метода в&nbsp;журнале и начать процесс &laquo;отладки&raquo; с этого места.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/3554.clip_image013_03268270.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/3554.clip_5F00_image013_5F00_03268270.png"><img title="clip_image013" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/3441.clip_image013_thumb_4EA5B027.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/3441.clip_5F00_image013_5F00_thumb_5F00_4EA5B027.png" alt="clip_image013" width="367" height="99" border="0" /></a></p>
<p>В следующей статье я расскажу вам, как запускать IntelliTrace из любого места.</p>
<p>Удачной отладки!</p>
<p>&nbsp;</p><div style="clear:both;"></div><img src="https://blogs.msdn.com/aggbug.aspx?PostID=10432637" width="1" height="1">]]></content:encoded>
    </item>
    <item>
      <title>Разработка приложений с использованием пакета Visual Studio 3D Starter Kit. Часть 3 из 3</title>
      <link>https://docs.microsoft.com/archive/blogs/dmandreev/63</link>
      <pubDate>Wed, 03 Jul 2013 01:12:00 GMT</pubDate>
      <dc:creator><![CDATA[Dmitry Andreev]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmandreev/2013/07/03/63/</guid>
      <description><![CDATA[Это третья, заключительная, статья из серии, посвященной основам работы с пакетом&nbsp;Visual Studio...]]></description>
      <content:encoded><![CDATA[<p>Это третья, заключительная, статья из серии, посвященной основам работы с пакетом&nbsp;<a href="https://aka.ms/vs3dkit">Visual Studio 3D Starter Kit</a>! Если вы прочли и выполнили все рекомендации из двух предыдущих статей (см.&nbsp;<a href="https://blogs.msdn.com/b/developer-tools-rus/archive/2013/06/24/visual-studio-3d-starter-kit-1-3.aspx">здесь</a>&nbsp;и <a href="https://blogs.msdn.com/b/developer-tools-rus/archive/2013/07/01/visual-studio-3d-starter-kit-2-3.aspx">здесь</a>), то получили приложение, которое имитирует игру в кости. Сейчас мы внесем последние изменения в наше приложение для запуска на устройствах, работающих под управлением Windows RT или Windows Phone 8.&nbsp;</p>
<p>Если две предыдущие статьи вы еще не читали, то можете сделать это прямо сейчас. Приступайте к&nbsp;этой статье, когда у вас будет готово приложение.</p>
<p>Если вам легче воспринимать визуальную информацию, то посмотрите видеоролики для части 1 и 2 на нашем канале&nbsp;<a href="https://channel9.msdn.com/posts/VS-3D-Starter-Kit-Dice-Roller">Channel 9</a>! Вам понадобится менее получаса, чтобы с нуля создать приложение, реалистично имитирующее игру в кости!</p>
<p><a href="https://channel9.msdn.com/posts/VS-3D-Starter-Kit-Dice-Roller"><img src="https://media.ch9.ms/ch9/b3eb/05e328a7-8b3d-4e91-9085-e1241e46b3eb/DiceRollerrs_512.jpg" alt="" border="0" /></a></p>
<h2>Заключительные шаги Windows RT</h2>
<p>Современные устройства с Windows RT оборудованы графической картой с поддержкой <a href="https://msdn.microsoft.com/ru-ru/library/windows/desktop/ff476876.aspx">D3D_FEATURE_LEVEL_9_1</a>,&nbsp;а инструменты Visual Studio Graphics генерируют шейдеры для графических карт с поддержкой D3D_FEATURE_LEVEL_10_0 и выше, поэтому для того, чтобы приложение можно было запускать на устройствах с Windows RT, необходимо создать шейдеры поддерживаемой версии.</p>
<p>Откройте сетку Die (Die.fbx) и щелкните куб. В окне Properties (Свойства) найдите свойство Effect (Эффект). Нажмите кнопку &laquo;+&raquo; слева от этого свойства и выберите значение Advanced (Расширенные). Наконец, нажмите кнопку &laquo;&hellip;&raquo;, чтобы открыть исходный код шейдера для эффекта Phong (метод Фонга).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/6758.Part3_Fig1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/6758.Part3_5F00_Fig1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/6758.Part3_Fig1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/391x366/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/6758.Part3_5F00_Fig1.png" alt="" border="0" /></a></p>
<p>В окне конструктора шейдеров Visual Studio Shader Designer вы увидите шейдер, который по умочанию применяется к этой сетке в Visual Studio. Конструктор шейдеров позволяет создавать сложные визуальные эффекты, при этом вам не придется изучать новый язык программирования. Подробнее о конструкторе шейдеров написано в&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/hh315733(v=VS.110).aspx">документации</a>&nbsp;и <a href="https://msdn.microsoft.com/ru-ru/library/jj161095.aspx">обзоре</a>&nbsp;на сайте MSDN.</p>
<p>Мы экспортируем этот шейдер в HLSL для того, чтобы перекомпилировать его для видеокарт типа Direct3D Feature Level 9. Starter Kit попытается автоматически найти поддерживаемый шейдер с тем же именем, если оригинал не поддерживается данным устройством.</p>
<p>Для экспорта этого шейдера переходим к последнему значку на панели инструментов: (Advanced)&nbsp;-&gt; Export -&gt; Export as&hellip; ((Расширенные) -&gt; Экспортировать -&gt; Экспортировать как...), вводим имя <strong>Phong.hlsl</strong> и сохраняем файл в папку Assets (см. рисунок ниже). Необходимо добавить этот файл в&nbsp;проект: щелкните правой кнопкой мыши папку Assets, нажмите Solution Explorer -&gt; Add -&gt; Existing item (Обозреватель решений -&gt; Добавить -&gt; Существующий элемент) и выберите только что экспортированный файл.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0842.Part3_Fig2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0842.Part3_5F00_Fig2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0842.Part3_Fig2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0842.Part3_5F00_Fig2.png" alt="" border="0" /></a></p>
<p>Наконец, мы должны сообщить компилятору HLSL, что этот файл относится к типу Pixel Shader&nbsp;(Шейдер пикселей). Для этого в обозревателе решений Solution Explorer щелкните правой кнопкой мыши файл Phong.hlsl и выберите Properties (Свойства). На странице свойств проверьте, чтобы в&nbsp;раскрывающемся списке Configuration (Конфигурация) был выбран пункт All Configurations (Все конфигурации), а в раскрывающемся списке Platform (Платформа)&nbsp;&mdash; All Platforms (Все платформы). Таким образом, все вносимые нами изменения применяются ко всем версиям нашего приложения.</p>
<p>Затем на странице HLSL Compiler (Компилятор HLSL) задайте свойству Shader Type (Тип шейдера) значение Pixel Shader (/ps) [Шейдер пикселей (/ps)]. Кроме того, должна быть включена оптимизация, т.&nbsp;е. свойству Disable optimizations (Отключить оптимизацию) должно быть задано значение No (Нет). Эти настройки показаны на рисунке ниже:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/7181.Part3_Fig3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/7181.Part3_5F00_Fig3.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/7181.Part3_Fig3.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/7181.Part3_5F00_Fig3.png" alt="" border="0" /></a></p>
<p>На этом этапе мы подготовили приложение для запуска на устройствах под управлением Windows&nbsp;RT. Теперь вы можете установить это приложение на своем устройстве с помощью инструментов удаленной отладки&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/hh441469(v=vs.110).aspx">Visual Studio Remote Debugging Tools</a>.</p>
<p>Прежде чем опубликовать версию приложения для Windows RT, необходимо убедиться в том, что и&nbsp;портретный режим, и режим Snap View работают корректно. В этом случае мы просто удалили следующую строку из метода CreateWindowSizeDependentResource()&nbsp;в классе Game.cpp, чтобы камера не меняла ориентацию при переключении режима представления:</p>
<pre>&nbsp;</pre>
<pre class="scroll"><code class="cplusplus">void Game::CreateWindowSizeDependentResources()<br /> {<br /> GameBase::CreateWindowSizeDependentResources();<br /> <br /> // (фрагмент) инициализировать камеру...<br /> if (aspectRatio &lt; 1.0f)<br /> {<br /> ///<br /> /// портретный режим или режим snap view<br /> ///<br /> <span style="text-decoration: line-through;">m_graphics.GetCamera().SetUpVector(XMFLOAT3(1.0f, 0.0f, 0.0f));</span> <br /> fovAngleY = 120.0f * XM_PI / 180.0f;<br /> }<br /> // (фрагмент) источники света...<br /> }</code></pre>
<pre>&nbsp;</pre>
<p>Приложение в его текущем состоянии можно загрузить с сайта&nbsp;<a href="https://diceroller3d.codeplex.com/SourceControl/changeset/5ebb20f0b93447d14d615508b3d8df7f57d683d7">CodePlex</a>&nbsp;(см. прямую ссылку ниже).</p>
<p><a href="https://download-codeplex.sec.s-msft.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=5ebb20f0b934"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/1541.SupportForRT.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/1541.SupportForRT.png" alt="" border="0" /></a></p>
<h2>Портирование приложения на Windows Phone</h2>
<p>Проект <a href="https://aka.ms/vs3dkit">Starter Kit with support for Windows Phone</a> позволяет беспрепятственно портировать это приложение на Windows Phone 8. Теперь необходимо загрузить пакет Starter Kit, заменить классы Game.cpp и Game.h на те, которые вы создали для этого приложения, добавить все свои активы (в&nbsp;данном случае: Die.fbx, DieTexture.png и Phong.hlsl), а также внести изменения в код XAML для вызова метода RollDie(), когда пользователь касается сенсорного экрана. Краткие пошаговые инструкции:</p>
<ol start="1">
<li>На вашем компьютере должен быть установлен пакет&nbsp;<a href="https://dev.windowsphone.com/en-us/downloadsdk">Windows Phone 8 SDK</a>.</li>
<li>Загрузите пакет <a href="https://aka.ms/vs3dkit">Visual Studio 3D Starter Kit with support for Windows Phone</a>&nbsp;и откройте его в&nbsp;Visual Studio.</li>
<li>В проекте StarterKitPhoneComponent: удалите папку Shared/Animation и все содержимое из папки Shared/Assets.</li>
<li>Замените файлы Game.cpp и Game.h на созданные вами ранее.</li>
<li>Скопируйте все активы вашей игры в папку Shared/Assets проекта StarterKitPhoneComponent: Die.fbx, DieTexture.png и Phong.hlsl.</li>
<li>На странице свойств файла Phong.hlsl проверьте, чтобы в раскрывающемся списке Configuration (Конфигурация) был выбран пункт All Configurations (Все конфигурации), а&nbsp;в&nbsp;раскрывающемся списке Platform (Платформа)&nbsp;&mdash; All Platforms (Все платформы). Затем на странице HLSL Compiler (Компилятор HLSL) задайте свойству Shader Type (Тип шейдера) значение Pixel Shader (/ps) [Шейдер пикселей (/ps)] и установите для свойства Disable optimizations (Отключить оптимизацию) значение No (Нет).</li>
<li>Удалите неиспользуемые методы из класса Direct3DBackground.cpp/.h: ToggleHitEffect() и&nbsp;ChangeMaterialColor().</li>
<li>В классе Direct3DBackground.cpp добавьте следующий код в метод OnPointerReleased():
<p>void&nbsp;Direct3DBackground::OnPointerReleased(DrawingSurfaceManipulationHost^&nbsp;sender,&nbsp;PointerEventArgs^&nbsp;args)</p>
<p>{</p>
<p>&nbsp; m_renderer-&gt;RollDie();</p>
<p>}</p>
</li>
<li>Из MainPage.xaml удалите весь код XAML, относящийся к счетчикам и панели приложения.</li>
<li>Из MainPage.xaml.cs удалите все неиспользуемые поля и методы.</li>
</ol>
<p>Готово! Теперь это приложение можно запустить в эмуляторе Windows Phone или на устройстве с&nbsp;Windows Phone 8. Вы можете отрегулировать положение камеры и поле зрения, чтобы на экране телефона ��убик выглядел крупнее.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0361.DiceRollerPhone.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0361.DiceRollerPhone.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0361.DiceRollerPhone.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/200x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0361.DiceRollerPhone.png" alt="" border="0" /></a></p>
<p>Итоговую версию проекта можно загрузить с сайта&nbsp;<a href="https://diceroller3d.codeplex.com/SourceControl/changeset/78429aedf85e34b4e3a9b41c47ce219ceed9da91">CodePlex</a>&nbsp;(см. прямую ссылку ниже).</p>
<p><a href="https://download-codeplex.sec.s-msft.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=78429aedf85e"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/1854.FinalProject.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/1854.FinalProject.png" alt="" border="0" /></a></p>
<h2>Планы на будущее</h2>
<p>Это приложение готово к размещению в Магазине Windows, но есть много дополнительных шагов, которые помогли бы сделать его лучше. Например:</p>
<ul>
<li>Замена логотипа, иконок плитки и заставки в соответствии с темой приложения.</li>
<li>Создание красивого фона и, возможно, стола, на который пользователь будет бросать кости.</li>
<li>Добавление теней, отражения и других реалистичных визуальных эффектов.</li>
<li>Можно сделать кубик настраиваемым, полупрозрачным, с закругленными краями.</li>
<li>Обеспечение поддержки более чем одного кубика или кубиков с разным количеством граней.</li>
<li>Добавление реалистичных подпрыгиваний и вращений с учетом силы броска, обнаружение столкновений.</li>
<li>Сохранение информации о состоянии кубика, когда работа приложения приостанавливается и возобновляется.</li>
<li>Ведение истории результатов предыдущих бросков.</li>
<li>Обеспечение поддержки датчика, чтобы пользователь мог бросать кости путем встряхивания устройства.</li>
<li>Звуковое сопровождение броска костей.</li>
<li>Возможности приложения Dice Roller можно использовать для создания настольной игры или симулятора казино...</li>
</ul>
<h2>Подведем итоги</h2>
<p>Эта серия статей познакомила вас с процессом создания 3D-приложения для Windows 8, Windows&nbsp;RT и Windows Phone с использованием пакета Visual Studio 3D Starter Kit. Вся логика и&nbsp;активы приложения являются кроссплатформенными. Также вы узнали об инструментах Visual Studio Graphics и поняли, что создание 3D-приложения&nbsp;&mdash; не такая уж сложная задача, вы можете приступать к ней без глубоких знаний в области трехмерного моделирования, математики и HLSL, постепенно изучая новые понятия.</p>
<p>Мы будем рады услышать отзывы об этом пошаговом руководстве, пакете Visual Studio 3D Starter Kit, а также узнать, с какими возможностями Visual Studio, предназначенными для работы с&nbsp;графикой, вы хотели бы познакомиться в будущем. Оставляйте нам свои комментарии!</p><div style="clear:both;"></div><img src="https://blogs.msdn.com/aggbug.aspx?PostID=10431402" width="1" height="1">]]></content:encoded>
    </item>
    <item>
      <title>Разработка приложений с использованием пакета Visual Studio 3D Starter Kit. Часть 2 из 3</title>
      <link>https://docs.microsoft.com/archive/blogs/dmandreev/73</link>
      <pubDate>Mon, 01 Jul 2013 06:16:00 GMT</pubDate>
      <dc:creator><![CDATA[Dmitry Andreev]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmandreev/2013/07/01/73/</guid>
      <description><![CDATA[Не так давно мы приступили к разработке простого приложения для игры в кости с&nbsp;помощью Visual...]]></description>
      <content:encoded><![CDATA[<p>Не так давно мы приступили к разработке простого приложения для игры в кости с&nbsp;помощью Visual Studio 3D Starter Kit. Теперь мы доработаем приложение, добавив анимацию. <a href="https://blogs.msdn.com/b/developer-tools-rus/archive/2013/06/24/visual-studio-3d-starter-kit-1-3.aspx">Ссылка на предыдущую статью</a>.</p>
<h2>Как заставить кубик крутиться</h2>
<p>Чтобы заставить любой объект в графическом приложении двигаться, необходимо:</p>
<ol start="1">
<li>Определить какое-либо состояние (например, с помощью логического флага), чтобы указать, что должна быть запущена анимация. Также на этом этапе можно сохранить сведения об исходном положении и продолжительности анимации, если это необходимо.</li>
<li>В методе Update, который вызывается для каждого кадра перед рендерингом, обрабатывается положение/вращение/масштабирование объекта (с точки зрения 3D-модели, мы говорим о&nbsp;<em>преобразованиях</em>); следует вычислить разницу во времени между началом анимации и выводом на экран текущего кадра. Когда анимация завершается, необходимо надлежащим образом обновить состояние, чтобы остановить анимацию.</li>
<li>В методе Render преобразования должны применяться к каждому объекту надлежащим образом.</li>
</ol>
<p>Мы добавим новый метод RollDie(), который установит состояние и сохранит время запуска. Этот метод будет использоваться для вычисления результата каждого броска кубика, но пока мы просто запустим анимацию&nbsp;&mdash; вращение кубика и показ цифр от 1 до 6.</p>
<p>Чтобы создать эту анимацию, нам понадобится набор переменных для отслеживания преобразований куба, а также времени анимации. Мы создадим одну переменную типа Boolean для отслеживания выполнения анимации, одну переменную типа Float для хранения времени анимации и три вектора для хранения начального, конечного и текущего вращений куба. Векторы типа XMFLOAT3 будут хранить вращения Yaw, Pitch и Roll (см. рисунок ниже).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/8015.Part2_Fig1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/8015.Part2_5F00_Fig1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/8015.Part2_Fig1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/238x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/8015.Part2_5F00_Fig1.png" alt="" border="0" /></a></p>
<p>Давайте создадим эти поля и метод RollDie(). Добавьте следующий код в класс Game.h:</p>
<pre>&nbsp;</pre>
<pre class="scroll"><code class="cplusplus">ref class Game sealed : public GameBase<br /> {<br /> // (фрагмент) объявление других классов...<br /> <br /> Platform::String^ OnHitObject(int x, int y);<br /> void RollDie(); <br /> private:<br /> std::vector&lt;VSD3DStarter::Mesh*&gt; m_meshModels;<br /> bool m_isAnimationRunning;<br /> float m_animationTime;<br /> DirectX::XMFLOAT3 m_initialRotation;<br /> DirectX::XMFLOAT3 m_currentRotation;<br /> DirectX::XMFLOAT3 m_targetRotation;<br /> };</code></pre>
<pre>&nbsp;</pre>
<p>Давайте создадим анимацию, начнем с метода RollDie(). Добавьте следующий код в класс Game.cpp:</p>
<pre><span><span>void</span>&nbsp;<span>Game</span>::RollDie()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;m_initialRotation&nbsp;=&nbsp;m_currentRotation;<br />&nbsp;&nbsp;&nbsp;&nbsp;m_targetRotation&nbsp;=&nbsp;<span>XMFLOAT3</span>(0.0f,&nbsp;XM_PI,&nbsp;0.0f);&nbsp;<span>//&nbsp;always&nbsp;rotate&nbsp;to&nbsp;6<br /><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;m_animationTime&nbsp;=&nbsp;0.0f;<br />&nbsp;&nbsp;&nbsp;&nbsp;m_isAnimationRunning&nbsp;=&nbsp;<span>true</span>;<br />}</span></pre>
<p>RollDie() запустит анимацию путем задания значения True для переменной m_isAnimationRunning. Нам необходимо добавить код в метод Update() для поворота куба в каждом кадре. Добавьте следующий код в метод Update():&nbsp;</p>
<pre class="scroll"><code class="cplusplus">void Game::Update(float timeTotal, float timeDelta)<br /> {<br /> if (m_isAnimationRunning)<br /> {<br /> m_animationTime += timeDelta;<br /> <br /> static const float animationDuration = 0.5f;<br /> float animationProgress = std::min&lt;float&gt;(m_animationTime / animationDuration, 1.0f);<br /> <br /> XMVECTOR initial = XMLoadFloat3(&amp;m_initialRotation);<br /> XMVECTOR target = XMLoadFloat3(&amp;m_targetRotation);<br /> <br /> XMVECTOR current = initial + animationProgress * (target - initial);<br /> XMStoreFloat3(&amp;m_currentRotation, current);<br /> <br /> if (animationProgress &gt;= 1.0f)<br /> m_isAnimationRunning = false;<br /> }<br /> }</code></pre>
<p>Описание кода:</p>
<ol start="1">
<li>Анимация должна запускаться только в том случае, когда установлен флаг m_isAnimationRunning.</li>
<li>Сначала вычисляется значение переменных calculate m_animationTime (время от начала анимации 0&ndash;0,5 секунды) и m_animationProgress (процент завершения анимации 0&ndash;1). Обратите внимание, &laquo;1.0&raquo; означает, что анимация завершена.</li>
<li>Загрузите исходный и целевой векторы вращения в XMVECTORs, это позволяет ускорить расчеты благодаря <a href="https://msdn.microsoft.com/ru-ru/library/26td21ds(v=vs.100).aspx">макроопределениям CPU</a>.</li>
<li>Расчеты линейным способом по формуле:</li>
</ol>
<p><em>текущий = исходный + прогресс * (целевой &ndash; исходный)</em></p>
<ol start="1">
<li>Вычисленное значение сохраняется обратно в m_currentRotation.</li>
<li>Проверка выполнения анимации и ее остановка в случае необходимости.</li>
</ol>
<p>На следующем шаге анимации вычисленное вращение используется в методе Render для поворота куба. Для этого измените следующую строку кода в методе Render():</p>
<pre class="scroll"><code class="cplusplus">void Game::Render()<br /> {<br /> GameBase::Render();<br /> <br /> // (фрагмент) очистить...<br /> <br /> XMMATRIX transform = XMMatrixRotationRollPitchYawFromVector(XMLoadFloat3(&amp;m_currentRotation));<br /> <br /> for (UINT i = 0; i &lt; m_meshModels.size(); i++)<br /> {<br /> m_meshModels[i]-&gt;Render(m_graphics, transform);<br /> }<br /> <br /> // (фрагмент) MSAA...<br /> }</code></pre>
<p>Метод, который мы вызываем, получает объект XMVECTOR, содержащий значения переменных для разворота, уклона и поворота относительно вертикальной оси. Этот метод возвращает матрицу вращения, которая соответствует комбинированному преобразованию. Для наших целей также подходит метод XMMatrixRotationRollPitchYaw, который обрабатывает параметры разворота, уклона и поворота относительно вертикальной оси по отдельности. Кроме того, вы можете вычислить каждый компонент с помощью отдельного метода, а затем самостоятельно перемножить результаты. Полный перечень методов, используемых для создания матриц преобразования, представлен <a href="https://msdn.microsoft.com/ru-ru/library/windows/desktop/ee415594(v=vs.85).aspx">на сайте MSDN</a>.</p>
<p>Все, что нам необходимо сделать,&mdash; вызвать метод RollDie(). Мы будем вызывать его каждый раз, когда пользователь касается или щелкает по экрану. Добавьте следующий код в файл DirectXPage.xaml.cpp (в метод DirectXPage::OnTapped):</p>
<pre class="scroll"><code class="cplusplus">void DirectXPage::OnTapped(Platform::Object^ sender, TappedRoutedEventArgs^ e)<br /> {<br /> m_renderer-&gt;RollDie();<br /> }</code></pre>
<p>Если вы запустите приложение сейчас, то после щелчка или касания экрана в любом месте кубик будет вращаться, показывая цифры от 1 до 6!</p>
<h2>Логика приложения: генератор случайных чисел</h2>
<p>Неинтересно бросать кости, если вы точно знаете, какую цифру увидите. Поэтому мы добавим генератор случайных чисел на основе функции из библиотеки времени выполнения языка C:&nbsp;<a href="https://msdn.microsoft.com/en-us/library/398ax69y(v=vs.110).aspx">rand()</a>. При каждом броске игрок получит новую цифру.</p>
<p>Сначала генератор rand() нужно инициализировать с помощью некоторого начального значения. Если мы не инициализируем генератор или инициализируем его с использованием фиксированного значения, то последовательность генерируемых чисел будет неизменна при каждом запуске приложения, а нам это не подходит. Мы будем инициализировать генератор случайных чисел с&nbsp;использованием текущего времени CPU. Добавьте следующий код в метод Game::Initialize():</p>
<pre class="scroll"><code class="cplusplus">void Game::Initialize()<br /> {<br /> Mesh::LoadFromFile(m_graphics, L"die.cmo", L"", L"", m_meshModels);<br /> <br /> srand ((unsigned int) time(NULL));<br /> }</code></pre>
<p>Также следует подключить библиотеку &lt;time.h&gt; для метода Game.cpp, чтобы функция time() была доступна:</p>
<pre class="scroll"><code class="cplusplus">#include "pch.h"<br /> #include "Game.h"<br /> #include &lt;DirectXMath.h&gt;<br /> #include &lt;DirectXColors.h&gt;<br /> #include &lt;algorithm&gt;<br /> #include &lt;time.h&gt;</code></pre>
<p>После инициализации мы можем воспользоваться функцией rand() в методе RollDie(), чтобы получить цифру, которая выпадет, когда пользователь бросит кости. Мы также должны правильно задать целевые вращения кубика при каждом броске. Для этого измените строку, в которой задается значение переменной m_targetRotation. Окончательный вариант метода RollDie():</p>
<pre class="scroll"><code class="cplusplus">void Game::RollDie()<br /> {<br /> m_initialRotation = m_currentRotation;<br /> <br /> int currentRoll = rand() % 6 + 1;<br /> switch (currentRoll)<br /> {<br /> case 1:<br /> m_targetRotation = XMFLOAT3(0.0f, 0.0f, 0.0f);<br /> break;<br /> case 2:<br /> m_targetRotation = XMFLOAT3(0.0f, XM_PIDIV2, 0.0f);<br /> break;<br /> case 3:<br /> m_targetRotation = XMFLOAT3(XM_PIDIV2, 0.0f, 0.0f);<br /> break;<br /> case 4:<br /> m_targetRotation = XMFLOAT3(-1.0f * XM_PIDIV2, 0.0f, 0.0f);<br /> break;<br /> case 5:<br /> m_targetRotation = XMFLOAT3(0.0f, -1.0f * XM_PIDIV2, 0.0f);<br /> break;<br /> case 6:<br /> m_targetRotation = XMFLOAT3(0.0f, XM_PI, 0.0f);<br /> break;<br /> }<br /> <br /> m_animationTime = 0.0f;<br /> m_isAnimationRunning = true;<br /> }</code></pre>
<p>Запустите приложение. Вот наш анимированный кубик! Бросьте кости, коснувшись экрана в любом месте. Можете перейти в режим Snap View.</p>
<h2>Как&nbsp;заставить кубик прыгать</h2>
<p>Это небольшое приложение можно использовать и в таком виде, но мы можем сделать его еще интереснее. Сейчас мы покажем, как заставить брошенный кубик подпрыгивать, а также добавим дополнительные случайные вращения, чтобы сделать приложение более реалистичным.</p>
<p>Чтобы запрограммировать &laquo;прыжки&raquo;, мы добавим еще одну переменную в нашу анимацию&nbsp;&mdash; вертикальную координату (Y). Значение этой переменной будет изменяться после того, как кости будут брошены (в методе Update()), мы также внесем изменения в метод Render(), чтобы применить трансляцию к кубу. Сначала нужно добавить переменную трансляции в Game.h:</p>
<pre class="scroll"><code class="cplusplus">ref class Game sealed : public GameBase<br /> {<br /> // (фрагмент) объявление других классов...<br /> <br /> private:<br /> std::vector&lt;VSD3DStarter::Mesh*&gt; m_meshModels;<br /> bool m_isAnimationRunning;<br /> float m_animationTime;<br /> DirectX::XMFLOAT3 m_initialRotation;<br /> DirectX::XMFLOAT3 m_currentRotation;<br /> DirectX::XMFLOAT3 m_targetRotation;<br /> float m_currentTranslationY;<br /> };</code></pre>
<p>Чтобы переменная изменялась с течением времени (метод Update()):</p>
<pre class="scroll"><code class="cplusplus">void Game::Update(float timeTotal, float timeDelta)<br /> {<br /> if (m_isAnimationRunning)<br /> {<br /> // (фрагмент)<br /> <br /> XMVECTOR current = initial + animationProgress * (target - initial);<br /> XMStoreFloat3(&amp;m_currentRotation, current);<br /> <br /> const float maxHeight = 2.0f;<br /> m_currentTranslationY = 4.0f * maxHeight * animationProgress * (1 - animationProgress);<br /> <br /> if (animationProgress &gt;= 1.0f)<br /> m_isAnimationRunning = false;<br /> }<br /> }</code></pre>
<p>Те, кто помнит курс математики старших классов, узнали уравнение параболы с полюсами в точках 0 и 1 и вершиной в точке 0,5 (MaxHeight). Наш кубик будет достаточно реалистично подпрыгивать. График этой функции можно увидеть здесь:&nbsp;<a href="https://www.wolframalpha.com/input/?i=plot+y+%3d+4x(1-x)+from+0+to+1&amp;incTime=true">WolframAlpha</a>.</p>
<p>На заключительном этапе мы воспользуемся расчетной трансляцией для преобразования куба в&nbsp;процессе рендеринга. Добавьте следующий код в метод Render:</p>
<pre><span>v</span></pre>
<pre class="scroll"><code class="cplusplus">oid Game::Render()<br /> {<br /> // (фрагмент) очистить...<br /> <br /> m_d3dContext-&gt;ClearDepthStencilView( /* (фрагмент) */ );<br /> <br /> XMMATRIX transform = XMMatrixRotationRollPitchYawFromVector(XMLoadFloat3(&amp;m_currentRotation));<br /> transform *= XMMatrixTranslation(0.0f, m_currentTranslationY, 0.0f);<br /> <br /> for (UINT i = 0; i &lt; m_meshModels.size(); i++)<br /> {<br /> m_meshModels[i]-&gt;Render(m_graphics, transform);<br /> }<br /> <br /> // (фрагмент) MSAA...<br /> }</code></pre>
<p>Запустите приложение и щелкните по экрану. Вы увидите, что кубик после броска реалистично подпрыгивает. Наконец, чтобы анимация выглядела еще более реалистичной, добавим случайные вращения по обеим осям при каждом броске кубика. Для этого внесем изменения в метод RollDie() и добавим случайные повороты в целевое вращение:</p>
<pre class="scroll"><code class="cplusplus">void Game::RollDie()<br /> {<br /> // (фрагмент) инициализация, бросок и переключение(currentRoll)<br /> <br /> XMVECTOR target = XMLoadFloat3(&amp;m_targetRotation);<br /> XMVECTOR current = XMLoadFloat3(&amp;m_currentRotation);<br /> <br /> // учет текущего вращения<br /> target += XMVectorFloor(current / XM_2PI) * XM_2PI;<br /> <br /> // -1, 0 или 1 дополнительный оборот<br /> XMVECTOR randomVector = XMLoadFloat3(&amp;XMFLOAT3(rand() % 3 - 1.0f, rand() % 3 - 1.0f, rand() % 3 - 1.0f));<br /> target += randomVector * XM_2PI;<br /> <br /> XMStoreFloat3(&amp;m_targetRotation, target);<br /> <br /> m_animationTime = 0.0f;<br /> m_isAnimationRunning = true;<br /> }</code></pre>
<p>Этот код вносит два изменения в целевое вращение:</p>
<ol start="1">
<li>Указывается общее количество полных оборотов, совершенных до настоящего момента в&nbsp;рамках целевого вращения, в результате чего каждый поворот будет выполняться относительно предыдущего поворота, а не исходного положения кубика.</li>
<li>Добавляется -1, 0 и 1 полный оборот к целевому относительному вращению. Для этого мы создаем вектор на основе трех значений, выбранных случайно из ряда -1, 0 и 1, и умножаем полученную величину на 2 * PI (полный оборот в радианах).</li>
</ol>
<p>Также обратите внимание на то, что мы используем XMVECTORs еще раз для ускорения расчета, это также позволяет использовать только одну формулу вместо трех (если бы компоненты х, у, z вычислялись по отдельности).</p>
<p>Мы расширили функционал своего приложения. Конечно, с таким приложением работать намного интереснее, чем с классическим генератором случайных чисел. Эту версию приложения можно загрузить с сайта&nbsp;<a href="https://diceroller3d.codeplex.com/SourceControl/changeset/c4192ee94bc1db02347e2da95e44798c2a781837">CodePlex</a>&nbsp;(прямая ссылка представлена на плитке ниже).</p>
<p><a href="https://download-codeplex.sec.s-msft.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=c4192ee94bc1"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/3000.EndOfPart2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/3000.EndOfPart2.png" alt="" border="0" /></a></p>
<p>Осталось всего несколько шагов, и наше приложение будет работать на устройствах с Windows RT и&nbsp;Windows Phone. Эти шаги мы рассмотрим в третьей и последней статье блога из этой серии. Следите за обновлениями!</p><div style="clear:both;"></div><img src="https://blogs.msdn.com/aggbug.aspx?PostID=10430734" width="1" height="1">]]></content:encoded>
    </item>
    <item>
      <title>Разработка приложений с использованием пакета Visual Studio 3D Starter Kit. Часть 1 из 3</title>
      <link>https://docs.microsoft.com/archive/blogs/dmandreev/83</link>
      <pubDate>Mon, 24 Jun 2013 02:27:00 GMT</pubDate>
      <dc:creator><![CDATA[Dmitry Andreev]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmandreev/2013/06/24/83/</guid>
      <description><![CDATA[Несколько недель назад мы анонсировали серию статей, в которых будет показан весь процесс...]]></description>
      <content:encoded><![CDATA[<div class="post-content user-defined-markup">
<p><a href="https://blogs.msdn.com/b/vcblog/archive/2013/02/13/visual-studio-3d-starter-kit-now-for-windows-phone-8.aspx">Несколько недель назад</a> мы анонсировали серию статей, в которых будет показан весь процесс разработки приложения с использованием пакета&nbsp;<a href="https://aka.ms/vs3dkit">Visual Studio 3D Starter Kit</a>. Представляем вашему вниманию первую статью из этой серии. В серии статей мы рассмотрим процесс разработки приложения, пользователь которого сможет касанием или щелчком бросать трехмерные шестигранные кубики для игры в кости. Брошенный кубик будет подпрыгивать и вращаться в&nbsp;воздухе. Это приложение будет также запускаться в режиме <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/hh465371.aspx">Snap View</a> в Windows&nbsp;8, и&nbsp;пользователи смогут бросать кости, не прерывая работу в других приложениях. Мы также продемонстрируем, как сделать это приложение совместимым с устройствами на базе Windows RT, а также портировать его на Windows Phone.</p>
<p>В первой статье мы рассмотрим процесс создания приложения до этапа вывода кубика на экран и&nbsp;наложения текстуры. Мы также изучим возможности инструментов Visual Studio Graphics, которые доступны, начиная с версии Visual Studio Professional и выше. Но даже если у вас только Visual Studio Express 2012 для Windows 8, вы все равно сможете работать с этим пошаговым руководством.</p>
<p>Самые большие сложности у начинающих разработчиков Direct3D возникают из-за необходимости изучения большого количества новых понятий, например они должны научиться кодировать шейдеры HLSL и конвертировать сетки в форматы, подходящие для использования в режиме выполнения. Visual Studio содержит большое количество инструментов, упрощающих этот процесс, они помогут вам сконцентрироваться на логике приложения, вместо того чтобы изучать эти новые понятия. Когда вы будете готовы, вы сможете реализовать дополнительные функции в своем приложении, и при этом не придется начинать все сначала. В статьях из этой серии присутствует ряд ссылок на дополнительную документацию по DirectX, которую мы сами используем. Вы можете изучить эти материалы самостоятельно и узнать подробнее о DirectX и программировании графики.</p>
<p>Итак, настало время перейти от слов к делу!</p>
<h2>Демонстрационное приложение Dice Roller, имитирующие бросание игральных костей</h2>
<p>Кости используются в различных настольных и азартных играх. Создать приложение, имитирующее бросание игральных костей, достаточно просто на любом языке программирования, для генератора случайных чисел чаще всего нужна всего одна строка кода. Но как сделать это приложение интереснее?</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0763.Fig1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0763.Fig1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0763.Fig1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0763.Fig1.png" alt="" border="0" /></a></p>
<p>Ну конечно! Мы можем сделать кубик трехмерным! При этом мы не будем использовать какие-либо дополнительные инструменты, только Visual Studio 2012 Professional. Приступим!</p>
<h2>Начинаем с чистого листа</h2>
<p>Сначала необходимо загрузить и открыть пакет Visual Studio 3D Starter Kit. Ссылка для загрузки: <a href="https://aka.ms/vs3dkit">https://aka.ms/vs3dkit</a>. Мы также подготовили специальную версию пакета Starter Kit (только для Магазина Windows) для этого руководства. Сначала у вас будет совершенно пустой экран, без трехмерных моделей. Таким образом, мы научимся создавать собственные активы. Загрузить эту версию можно с сайта&nbsp;<a href="https://diceroller3d.codeplex.com/SourceControl/changeset/view/e75ccd62e002">CodePlex</a>,&nbsp;(прямая ссылка представлена на плитке ниже).&nbsp;Вы также поймете, как удалить все содержимое из Starter Kit.</p>
<p><a href="https://download-codeplex.sec.s-msft.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=e75ccd62e002"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/7563.EmptyStarterKit.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/7563.EmptyStarterKit.png" alt="" border="0" /></a></p>
<p><strong>Примечание для пользователей Visual Studio Express</strong>. Активы, используемые в этом проекте, можно загрузить, нажав плитку ниже. Просто добавляйте их в свой проект на соответствующих этапах.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/40/47/30/Dice%20Roller%20Assets.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-40-47-30/Dice-Roller-Assets.zip"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/2158.DiceRollerAssets.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/2158.DiceRollerAssets.png" alt="" border="0" /></a></p>
<p>После запуска этого приложения вы увидите заставку Starter Kit с чайником, а затем&nbsp;&mdash; пустой серый экран. Не волнуйтесь, мы скоро его заполним&hellip;</p>
<h2>Создание и отображение сетки</h2>
<p>Сначала мы создадим единственную сетку, которую мы будем использовать в этом приложении,&mdash; трехмерный куб для костей. Для этого в окне обозревателя решений Visual Studio Solution Explorer правой кнопкой мыши щелкните папку Shared/Assets (Общие/Активы) в проекте StarterKit и выберите Add -&gt; New item&hellip; -&gt; Graphics -&gt; 3D Scene (.fbx) (Добавить -&gt; Новый элемент&hellip; -&gt; Графика&nbsp;-&gt; 3D-сцена (.fbx)). Давайте назовем сцену Die.fbx.&nbsp;На следующем рисунке показано окно редактора сетки Visual Studio Mesh Editor:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/31048.Fig2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/31048.Fig2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/31048.Fig2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/31048.Fig2.png" alt="" border="0" /></a></p>
<p>Чтобы добавить куб, откройте панель элементов и дважды щелкните Cube. Вы можете также добавить некоторые другие простые формы, например цилиндры и чайники, и даже выполнить некоторые операции по редактированию (поворот, масштабирование и трансляция 3D-модели).</p>
<p>Чтобы вывести куб на экран, в нашу игру необходимо добавить код для загрузки и рендеринга сетки. В Starter Kit присутствует класс Game (Game.cpp/Game.h), который содержит логику рендеринга для нашей игры, именно сюда этот код должен быть добавлен.</p>
<p>Для начала загрузим сетку из файла при инициализации приложения. Добавьте следующий код в метод Game::Initialize():&nbsp;</p>
<pre class="scroll"><code class="csharp">void Game::Initialize()<br /> {<br /> Mesh::LoadFromFile(m_graphics, L"die.cmo", L"", L"", m_meshModels); <br /> }</code></pre>
<p>Этот код использует класс Mesh из проекта Starter Kit для загрузки модели Die из файла в вектор m_meshModels.</p>
<ul>
<li>Первый параметр, m_graphics, содержит экземпляр класса Graphics, в который сгруппированы все полезные объекты DirectX.</li>
<li>Второй параметр&nbsp;&mdash; это имя файла. Файл имеет расширение .cmo, поскольку в ходе построения все активы преобразуются в более простой формат, оптимальный для режима выполнения. Откомпилированные сетки хранятся в файлах в формате CMO (Compiled Mesh Object), для шейдеров используется <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb509633(v=vs.85).aspx">стандартный компилятор FX</a>,&nbsp;который создает файлы в&nbsp;формате CSO (Compiled Shader Object), изображения (PNG, JPG и т.&nbsp;д.) будут преобразованы в оптимизированный для среды выполнения формат&nbsp;<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb943990(v=vs.85).aspx">DDS (DirectDraw Surface)</a>.</li>
<li>Третий и четвертый параметры содержат относительные пути к шейдерам (файлам CSO) и&nbsp;текстурам (файлам DDS), которые используются в этой сетке. Чаще всего подходят значения по умолчанию.</li>
<li>Последний параметр&nbsp;&mdash; это ссылка на вектор std::vector класса Meshes, где должны храниться загруженные сетки.</li>
</ul>
<p>Далее необходимо выполнить рендеринг куба в каждом кадре. Добавьте следующий код в метод Game::Render():</p>
<pre class="scroll"><code class="csharp">void Game::Render()<br /> {<br /> GameBase::Render();<br /> <br /> // clear<br /> m_d3dContext-&gt;OMSetRenderTargets(<br /> 1,<br /> m_d3dRenderTargetView.GetAddressOf(),<br /> m_d3dDepthStencilView.Get()<br /> );<br /> <br /> m_d3dContext-&gt;ClearRenderTargetView(<br /> m_d3dRenderTargetView.Get(),<br /> DirectX::Colors::DarkSlateGray<br /> );<br /> <br /> m_d3dContext-&gt;ClearDepthStencilView(<br /> m_d3dDepthStencilView.Get(),<br /> D3D11_CLEAR_DEPTH,<br /> 1.0f,<br /> 0<br /> );<br /> <br /> XMMATRIX transform = XMMatrixIdentity(); <br /> for (UINT i = 0; i &lt; m_meshModels.size(); i++)<br /> {<br /> m_meshModels[i]-&gt;Render(m_graphics, transform);<br /> } <br /> <br /> //<br /> // only enable MSAA if the device has enough power<br /> //<br /> if (m_d3dFeatureLevel &gt;= D3D_FEATURE_LEVEL_10_0)<br /> {<br /> // (... MSAA code ...)<br /> }<br /> }</code></pre>
<p>Этот код вызывает метод Render для каждой сетки, чтобы вывести сетку на экран. Матрица преобразования содержит преобразования (масштабирование, транслирование, вращение и т.&nbsp;д.), которые мы будет применять к каждой сетке. В нашем случае применяется матрица Identity, которая выполняет рендеринг объекта без каких-либо визуальных изменений.</p>
<p>Если вы запустите приложение прямо сейчас, то увидите куб посередине экрана:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/2605.Fig3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/2605.Fig3.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/2605.Fig3.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/2605.Fig3.png" alt="" border="0" /></a></p>
<p>Вам не кажется, что кубик маловат? Давайте приблизим камеру. Добавьте следующую строку в&nbsp;метод Game::CreateWindowSizeDependentResources():&nbsp;</p>
<pre class="scroll"><code class="csharp">m_graphics.GetCamera().SetPosition(XMFLOAT3(0.0f, 2.0f, -6.0f));</code></pre>
<p>Этот метод вызывается каждый раз, когда изменяются размеры окна (например, при изменении разрешения или в режиме Snap View), поэтому здесь удобно задавать и изменять свойства камеры. Строка, в которую мы внесли изменения, устанавливает положение камеры, кроме того, можно отрегулировать поле зрения (fovAngleY в коде проекта StarterKit), тогда объекты визуально будут больше или меньше, а положение камеры не изменится.</p>
<h2>Добавление текстуры</h2>
<p>В этом примере мы предоставим вам текстуру для граней кубика. Она очень простая, но в&nbsp;дальнейшем вы можете создать собственную текстуру с помощью других инструментов.</p>
<p>На рисунке ниже показана предлагаемая текстура. Текстуру&nbsp;<a href="https://www.codeplex.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=669474014b1e&amp;itemId=Shared%2fAssets%2fDieTexture.png">можно загрузить отсюда</a>.</p>
<p><a href="https://www.codeplex.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=669474014b1e&amp;itemId=Shared%2fAssets%2fDieTexture.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/1423.Fig4.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/1423.Fig4.png" alt="" border="0" /></a></p>
<p>Сначала необходимо скопировать файл в папку Assets. Вернитесь в Visual Studio, щелкните правой кнопкой мыши папку Assets, нажмите Add -&gt; Existing item (Добавить -&gt; Существующий элемент) и&nbsp;выберите изображение.</p>
<p>Наконец, нужно применить текстуру к кубу. Откройте сетку Die (Die.fbx) и щелкните куб. В окне инструмента Properties (сочетание клавиш: Alt+Enter) найдите свойство Texture1. Нажмите кнопку &laquo;&hellip;&raquo;, чтобы выбрать изображение и применить его к кубу.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/8524.Fig5.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/8524.Fig5.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/8524.Fig5.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/8524.Fig5.png" alt="" border="0" /></a></p>
<p>Если вы запустите приложение снова, вы увидите куб с цифрами в соответствующей позиции.</p>
<p>Приложение в его текущем состоянии можно загрузить с сайта&nbsp;<a href="https://diceroller3d.codeplex.com/SourceControl/changeset/669474014b1e7f3510a4c1854f53a8e446193690">CodePlex</a>&nbsp;(прямая ссылка представлена на плитке ниже).</p>
<p><a href="https://download-codeplex.sec.s-msft.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=669474014b1e"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/5228.EndOfPart1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/5228.EndOfPart1.png" alt="" border="0" /></a></p>
<p>В нашей следующей статье мы расскажем, как добавить код анимации и сделать так, чтобы кубик можно было бросать! До встречи!</p>
<p>&nbsp;</p>
<div>&nbsp;</div>
</div>
<div class="post-attachment-viewer">
<div class="post-attachment"><span class="value"><a class="internal-link download-attachment" href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/40/47/30/Dice%20Roller%20Assets.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-40-47-30/Dice-Roller-Assets.zip"><span class="avatar"><img src="https://blogs.msdn.com/utility/filethumbnails/zip.gif" alt="" border="0" /></span>Dice Roller Assets.zip</a></span></div>
</div><div style="clear:both;"></div><img src="https://blogs.msdn.com/aggbug.aspx?PostID=10428083" width="1" height="1">]]></content:encoded>
    </item>
    <item>
      <title>Разработка приложений, учитывающих географическое положение, с использованием функций геолокации и карт Bing Maps</title>
      <link>https://docs.microsoft.com/archive/blogs/dmandreev/93</link>
      <pubDate>Wed, 05 Jun 2013 05:10:00 GMT</pubDate>
      <dc:creator><![CDATA[Dmitry Andreev]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmandreev/2013/06/05/93/</guid>
      <description><![CDATA[Если в бизнес-логике вашего приложения учитывается местоположение пользователя, вы можете...]]></description>
      <content:encoded><![CDATA[<p>Если в бизнес-логике вашего приложения учитывается местоположение пользователя, вы можете предоставлять пользователям приложения актуальный прогноз погоды, рассылать купоны, информацию о спортивных мероприятиях или концертах. Вы можете использовать <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/br229921.aspx">геолокационные</a> возможности Windows&nbsp;8, а также пакет Bing Maps SDK для разработки&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/hh465148.aspx">приложений для Магазина Windows, учитывающих географическое положение</a>.</p>
<p>Сейчас я расскажу вам, как ваше приложение может воспользоваться возможностями <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/br225603.aspx">службы расположения</a> для предоставления пользователям информации с учетом их местоположения, которое определяется по IP-адресу, параметрам сети Wi-Fi или данным GPS. После определения местоположения вы можете предоставить эту информацию пользователю с помощью Bing Maps SDK.</p>
<h2>Получение сведений о расположении</h2>
<p>Пространство имен <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.aspx">Windows.Devices.Geolocation</a>&nbsp;используется для получения сведений о вашем местоположении. На выбор метода определения местоположения пользователя (GPS, Wi-Fi или IP-адрес) влияют два основных фактора:</p>
<ol start="1">
<li>Уровень требуемой точности. Оптимальный уровень точности для вашего приложения.</li>
<li>Доступность данных о местоположении. Не во все устройства встроен модуль GPS, кроме того, сеть Wi-Fi может быть недоступна, когда запрашиваются сведения о местоположении.</li>
</ol>
<h3><a>Требуемая точность</a></h3>
<p>Отправляя запрос местоположения, ваше приложение должно указать&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geolocator.desiredaccuracy.aspx">требуемую точность</a>,&nbsp;чтобы данные в пределах заданного диапазона могли быть возвращены как можно быстрее. Каждый из типов характеризуется степенью точности определения местоположения:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Gps">GPS</a>&nbsp;&mdash; модуль GPS обеспечивает максимальную точность, погрешность обычно составляет не более 10&nbsp;метров.&nbsp;Однако если модуль GPS необходимо &laquo;разбудить&raquo;, чтобы получить данные со спутников и провести их триангуляцию, то приложение выдаст сведения о&nbsp;расположении не ранее, чем через 1&ndash;2 минуты. Как только модуль GPS установит связь со&nbsp;спутниками, он будет быстрее определять местоположение. Разумеется, чем дольше GPS используется, тем больше энергии потребляет. Чтобы получить данные от модуля GPS, необходимо свойству <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geolocator.desiredaccuracy.aspx">Geolocator.DesiredAccuracy</a>&nbsp;задать значение High.</li>
<li><a href="https://en.wikipedia.org/wiki/Wi-Fi">Wi-Fi</a>&nbsp;&mdash; соединение Wi-Fi позволяет определять местоположение с точностью до 300&ndash;500&nbsp;метров. При наличии подключения по Wi-Fi, данные о местоположении можно получить быстрее, чем при использовании модуля GPS, которому сначала требуется установить связь со спутниками. Установите для свойства DesiredAccuracy значение Default, если хотите получать сведения о расположении с учетом параметров соединения Wi-Fi.</li>
<li><a href="https://en.wikipedia.org/wiki/IP_address">IP</a>&nbsp;&mdash; IP-адрес позволяет определять местоположение с точностью до 1&nbsp;км. При наличии сетевого подключения данные о местоположении можно получить быстрее, чем при использовании модуля GPS, которому сначала требуется установить связь со спутниками. Установите также для свойства DesiredAccuracy значение Default, если хотите получать сведения о расположении с учетом IP-адреса. Служба расположений старается вычислить местоположение максимально точно; достигнутая точность указывается в свойстве <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geocoordinate.accuracy.aspx">Geocoordinate.Accuracy</a>.</li>
</ul>
<p>К вопросу определения требуемой точности следует подходить со всей тщательностью. От этого зависит производительность вашего приложения и энергопотребление устройства. Например, если ваше приложение рассылает пользователям прогноз погоды, вам обычно не нужна точность на уровне GPS. Также не забудьте указать точность своих данных с помощью радиуса ошибки, рассчитанного с учетом точности возвращаемых данных. Код C# для задания требуемой точности:</p>
<p><span>C#</span></p>
<pre class="scroll"><code class="csharp">Geolocator geolocator = new Geolocator();<br />geolocator.DesiredAccuracy = Windows.Devices.Geolocation.PositionAccuracy.High;<br /> </code></pre>
<p><span>Вне зависимости от требуемой точности, вызов для определения местоположения будет следующим:</span></p>
<p><span>C#</span></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="csharp">Geoposition pos = await geolocator.GetGeopositionAsync().AsTask(token);</code></pre>
</div>
</blockquote>
<p>Следующий код JavaScript который создает экземпляр класса Geolocator, задает требуемую точность, а затем получает сведения о текущем местоположении. Обратите внимание на то, что переменная promise представляет собой объект&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/br211867.aspx">WinJS.Promise</a>, вам понадобиться метод&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/hh701079.aspx">done</a>&nbsp;для получения данных с использованием вызова&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/br225537.aspx">getGeopositionAsync</a>.</p>
<p><span>JavaScript</span></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="js"> var geolocator = Windows.Devices.Geolocation.Geolocator();<br /> geolocator.desiredAccuracy =<br /> Windows.Devices.Geolocation.PositionAccuracy.high;<br /> <br /> // Get the geoposition, capturing the request in a 'promise' object.<br /> var promise = geolocator.getGeopositionAsync();</code></pre>
</div>
</blockquote>
<p>&nbsp;</p>
<p>Не забывайте о том, что когда вы задаете желаемую точность на уровне High, вы не можете быть уверены в том, что устройство пользователя сможет такую точность обеспечить. На ПК может отсутствовать модуль GPS или он может быть отключен, устройство может быть не подключено к&nbsp;сети Wi-Fi и т.&nbsp;д. Вы всегда должны быть готовы корректно обработать данные с низкой точностью. Как именно вы будете это делать, зависит от функциональных возможностей вашего приложения. Достаточно ли полученные данные точны, чтобы приложение могло продолжить свою работу? Можете ли вы запросить данные с точностью на уровне GPS? Для получения дополнительной информации см.&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/hh465148.aspx" target="_blank">Guidelines for location-aware apps</a>.</p>
<h3>Приложение Bing Maps</h3>
<p><a href="https://apps.microsoft.com/webpdp/app/97a2179c-38be-45a3-933e-0d2dbf14a142">Bing Maps</a>&nbsp;&mdash; хороший пример приложения, которое адаптируется к точности полученных данных о&nbsp;местоположении. На настольном ПК, который обычно не оборудован модулем GPS или Wi-Fi, оно определяет местоположение с учетом IP-адреса, при этом на экран выводится регион, в котором находится пользователь. На ноутбуке со встроенным модулем беспроводной связи приложение использует Wi-Fi, чтобы получить более точные сведения о местоположении и вывести на экран более детализированную информацию. Если пользователь хочет получить еще более точные сведения, то система отображает радиус ошибки. На устройствах, оборудованных модулем GPS, приложение Bing Maps получает максимально точные данные и выводит на экран соответствующие сведения о местоположении.</p>
<h3>Приложение Bing Weather</h3>
<p>Как уже упоминалось, приложениям, подобным&nbsp;<a href="https://apps.microsoft.com/webpdp/app/421ba874-f903-4965-9b82-d60f3ba3cae0">Bing Weather</a>,&nbsp;достаточно данных о регионе. Поэтому в приложении можно указать, что ему подходят данные с низкой точностью, и быстро получить сведения о местоположении. С точки зрения пользователя, быстродействие приложения повышается. Другие примеры приложений, которым, возможно, потребуются только данные о&nbsp;регионе: инструменты поиска радиостанций, сервисы рассылки информации о предложениях местных магазинов или местные новостные каналы.</p>
<h2>Отображение сведений о местоположении с помощью Bing Maps SDK</h2>
<p>Получив сведения о местоположении с помощью вызова&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geolocator.getgeopositionasync.aspx">GetGeopositionAsync</a>, вы можете отобразить эту точку на карте.</p>
<ul>
<li>Для начала&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geoposition.aspx">Geoposition</a>&nbsp;необходимо преобразовать в&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/hh846500.aspx">Location</a>,&nbsp;чтобы приложение Bing Maps могло работать с этой информацией. Сделать это позволяет следующий код:</li>
</ul>
<p><span>C#</span></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="csharp">Location location = new Location(pos.Coordinate.Latitude, pos.Coordinate.Longitude);</code></pre>
</div>
</blockquote>
<p><span>JavaScript:</span></p>
<blockquote>
<pre class="scroll"><code class="js">promise.done(<br /> function (pos) {<br /> // Get the coordinates of the current location.<br /> var coord = pos.coordinate,<br /> location = new Microsoft.Maps.Location(coord.latitude, coord.longitude);<br /> <br /> },<br /> function (err) {<br /> // Handle the error.<br /> });</code></pre>
</blockquote>
<p>&nbsp;</p>
<ul>
<ul>
<li>Затем местоположение выводится на экран в приложении Bing Maps. Пакет Bing Maps SDK можно загрузить <a href="https://visualstudiogallery.msdn.microsoft.com/bb764f67-6b2c-4e14-b2d3-17477ae1eaca">отсюда</a>. Вам также понадобится ключ для Bing Maps. Чтобы его получить, зарегистрируйтесь на портале Bing Maps и следуйте инструкциям: <a href="https://msdn.microsoft.com/ru-ru/library/ff428642.aspx">Getting a Bing Maps Key</a>. В&nbsp;процессе регистрации ознакомьтесь с ограничениями для ключа каждого типа и выберите подходящий ключ для своего приложения.&nbsp;<br /> Добавьте элемент управления Bing Maps в свой конструктор и укажите ключ в учетных данных.</li>
</ul>
</ul>
<p>&nbsp;</p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="html">&lt;Page<br /> xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"<br /> xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"<br /> xmlns:local="using:SimpleMapping"<br /> xmlns:d="https://schemas.microsoft.com/expression/blend/2008"<br /> xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"<br /> xmlns:Maps="using:Bing.Maps"<br /> x:Class="SimpleMapping.MainPage"<br /> mc:Ignorable="d"&gt;<br /> <br /> &lt;Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"&gt;<br /> &lt;Maps:Map x:Name="Map" Margin="0,120,0,0" Credentials="Insert Your Bing Maps Key Here"/&gt;<br /> &lt;/Grid&gt;<br /> &lt;/Page&gt;</code></pre>
</div>
</blockquote>
<ul>
<ul>
<li>Следующий фрагмент вы можете включить в код страницы в своем приложении, где отображается карта. Здесь настраивается масштаб карты и отображается местоположение. Подробнее о масштабе описано в статье&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/xaml/jj850315.aspx">How to display your location on a Bing Map</a>.</li>
</ul>
</ul>
<p>&nbsp;</p>
<p><span>C#</span></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="csharp">double zoomLevel = 13.0f;<br /> <br />Map.SetView(location, zoomLevel);</code></pre>
</div>
</blockquote>
<p><br /><span>Добавить элемент управления Bing Maps в ваше приложение с использованием JavaScript и HTML немного сложнее. Добавьте следующий тег &lt;script&gt; в код HTML своего приложения:</span></p>
<div>&nbsp;</div>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="html">&lt;script type="text/javascript" <br /> src="ms-appx:///Bing.Maps.JavaScript//js/veapicore.js"&gt;<br /> /script&gt;</code></pre>
</div>
</blockquote>
<p>Затем нужно создать тег &lt;div&gt; с картой и задать атрибут ID, чтобы вы могли получить к нему доступ.</p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="html">&lt;div id=&rsquo;map-div&rsquo;&gt;&lt;/div&gt;</code></pre>
</div>
</blockquote>
<p>Наконец, вы должны инициализировать элемент управления карты для своей HTML-страницы. Для этого используется следующий код JavaScript:</p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="js">// Load the Microsoft.Maps.Map module and then call getMap when the <br /> // module has loaded.<br /> function initMap() {<br /> Microsoft.Maps.loadModule('Microsoft.Maps.Map', <br /> { <br /> callback: getMap, <br /> culture: "en", <br /> homeRegion: "US" <br /> });<br /> }<br /> <br /> // Get the div to contain the map from the interface of the app.<br /> function getMap() {<br /> <br /> // Create a new instance of the Map class, passing in the app ID.<br /> var map = new Microsoft.Maps.Map(<br /> document.getElementById(mapDivId), <br /> { credentials: &ldquo;Insert your credentials here&rdquo; });<br /> <br /> // Set the initial zoom level and type of map.<br /> map.setView({<br /> mapTypeId: Microsoft.Maps.MapTypeId.road,<br /> zoom: 3<br /> });<br /> }</code></pre>
</div>
</blockquote>
<ul>
<li>Кроме того, любое приложение, использующее сведения о расположении, должно учитывать установленные пользователем разрешения, которые могут измениться в любой момент. Приложение Weather использует данные о местоположении, чтобы вывести на экран актуальный прогноз погоды. Но пользователь всегда может зайти в настройки и&nbsp;отключить функцию определения местоположения, и ваше приложение должно учитывать такую возможность. В этом случае приложение Weather должно вывести на экран соответствующее предупреждение, например: &laquo;Ваше местоположение не может быть определено. Необходимо разрешить приложению Weather определять ваше местоположение&raquo;. Рекомендации по поводу работы с пользовательскими настройками при определении местоположения см. в документе&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/Hh465148(v=win.10).aspx">Guidelines for location-aware apps</a> (Руководство по разработке приложений, учитывающих географическое положение). &nbsp;</li>
</ul>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0882.bing-weather_2FEEBCEF.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0882.bing_2D00_weather_5F00_2FEEBCEF.jpg"><img title="Bing Weather app" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/7356.bing-weather_thumb_084840C5.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/7356.bing_2D00_weather_5F00_thumb_5F00_084840C5.jpg" alt="Bing Weather app using location to get weather for the current location" width="600" height="450" border="0" /></a></p>
<p>&nbsp;</p>
<p>Функции определения географического положения и использования Bing Maps SDK подробнее рассматриваются в <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/xaml/jj850315.aspx">видео, руководствах</a> и&nbsp;<a href="https://code.msdn.microsoft.com/windowsapps/Simple-geolocation-with-7b385c3c">примере кода</a>. Там вы найдете пошаговые инструкции для асинхронного получения сведений о расположении с последующей визуализацией этой информации с помощью Bing Maps SDK. Вы узнаете, как активировать функцию определения местоположения, асинхронно получить соответствующие сведения, вывести требуемый участок карты и настроить значок местоположения с учетом точности полученных данных. Дополнительная информация также представлена на странице&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/hh846481.aspx">Bing Maps for Windows Store Apps</a> (Bing Maps и&nbsp;приложения для Магазина Windows).</p>
<h2>Упаковка</h2>
<p>Функция определения местоположения может быть полезна для вашего приложения, например, с&nbsp;точки зрения экономии времени. Вы сможете предоставлять пользователям более актуальную информацию, если будете знать, где они находятся. Это может быть список местных радиостанций, информация о предложениях от местных магазинов, ситуации на дорогах или погоде. В любом случае данные о местоположении сделают ваше приложение более полезным. В целях экономии времени пользователя, эти функции должны быть автоматизированы. Это поможет вашему приложению стать популярнее.</p>
<p>Автор: Росс Хейзе (Ross Heise), старший разработчик контента, Windows Developer Content</p>
<p>Выражаю особую благодарность Джону Кею (Jon Kay) и Эрику Шмидту (Eric Schmidt) за помощь в&nbsp;подготовке этой статьи.</p><div style="clear:both;"></div><img src="https://blogs.msdn.com/aggbug.aspx?PostID=10423836" width="1" height="1">]]></content:encoded>
    </item>
    <item>
      <title>Как сделать ваше приложение быстрым: профильная оптимизация C++</title>
      <link>https://docs.microsoft.com/archive/blogs/dmandreev/103</link>
      <pubDate>Fri, 31 May 2013 01:39:00 GMT</pubDate>
      <dc:creator><![CDATA[Dmitry Andreev]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/dmandreev/2013/05/31/103/</guid>
      <description><![CDATA[Профильная оптимизация&nbsp;это очень интересный способ оптимизации кода приложения всреде...]]></description>
      <content:encoded><![CDATA[<p><a href="https://msdn.microsoft.com/ru-ru/library/vstudio/e7k32f4k.aspx">Профильная оптимизация</a><span>&nbsp;это очень интересный способ оптимизации кода приложения в</span><em>среде выполнения&nbsp;</em><span>(в команде разработчиков Visual C этот метод называют POGO или PGO, от английского Profile Guided Optimization). Впервые профильная оптимизация была применена в конце 90-х исследовательскими группами в Visual C и Microsoft. Тогда она была рассчитана для архитектуры Itanium. Затем PGO была включена в состав Visual Studio C/C++ 2005. На сегодня это основной процесс оптимизации, значительно повышающий производительность приложений Microsoft и других разработчиков.</span><br /><span>В этом посте будет рассказано, как создавать более быстрые и высокопроизводительные нативные приложения. Для начала, познакомимся ближе с PGO, а затем рассмотрим на примере (симуляция NBody), как с помощью нескольких простых шагов можно применить этот процесс оптимизации в ваших приложениях. Для работы используйте исходный код из</span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/40/74/38/NBody.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-40-74-38/NBody.zip">примера</a><span>. Для сборки проекта вам понадобится&nbsp;</span><a href="https://blogs.msdn.com/controlpanel/blogs/posteditor.aspx/DirectX%20SDK">DirectX SDK</a><span>.</span><br /><a name="habracut"></a><br /><br /></p>
<h4>Как сделать нативное приложение более быстрым</h4>
<p><br /><span>Традиционные компиляторы работают с оптимизацией на основе статических исходных файлов. Они анализируют текст исходного файла, но не принимают в расчет данные, вводимые пользователями, о которых просто невозможно знать из кода. Рассмотрим этот псевдокод:</span><br /><img src="https://habrastorage.org/storage2/e3b/3e7/a1b/e3b3e7a1b0a2ba54134961d2d9fe8693.png" alt="" /><br /><br /><span>При работе с функцией whichBranchIsTaken компилятор не знает, как часто параметр &laquo;a&raquo; будет меньше параметра &laquo;b&raquo;, и сколько раз будет применено условие &laquo;if&raquo; (т. е. компилятор не может предсказывать ветвления). При работе с функциями девиртуализации и switchCaseExpansion компилятор знает недостаточно о значениях *p и i, что делает невозможным оптимизацию девиртуализации и расширений параметров. Эти проблемы проявятся еще ярче, если мы подставим данный фрагмент кода в разные модули (например, разные объектные файлы), поскольку функции традиционной компиляции не могут быть оптимизированы для работы в пределах исходных модулей.</span><br /><span>Базовая модель компилятора и компоновщика не так уж и плоха, но в ней недостает двух основных возможностей для оптимизации. Во-первых, в ней не используется информация, которую можно было бы получить на основе анализа всех исходных файлов (традиционные компиляторы оптимизируют только отдельные объектные файлы). Во-вторых, в ней не проводится оптимизация на базе ожидаемой или профильной реакции приложения. Первый недостаток может быть исправлен с помощью переключателя компилятора (</span><a href="https://msdn.microsoft.com/en-us/library/0zza0de8.aspx">/GL</a><span>) или переключателя компоновщика (</span><a href="https://msdn.microsoft.com/en-us/library/xbf3tbeh.aspx">/LTCG</a><span>), выполняющего полную оптимизацию программы и необходимого для профильной оптимизации приложения. После того, как оптимизация полной программы включена, вы можете применять профильную оптимизацию. Остановимся на ней подробнее.</span><br /><span>PGO &ndash; это процесс оптимизации компилятора в среде выполнения, применяющий данные профиля, собранные в ходе выполнения важных или требующих высокой производительности пользовательских сценариев, с целью оптимизации приложения. Профильная оптимизация обладает рядом преимуществ по сравнению с традиционной статической оптимизацией, поскольку она принимает в расчет, как будет себя вести приложение в рабочей среде. Благодаря этому оптимизатор может осуществлять оптимизацию по скорости (для частых пользовательских сценариев) или оптимизацию по размеру (для редких сценариев). В результате код становится более лаконичным, что, в конечном счете, повышает производительность приложения.</span><br /><br /><img src="https://habrastorage.org/storage2/1d4/def/43a/1d4def43a3670f6755be780c907054f0.png" alt="" /><br /><br /><span>В настоящее время PGO может применяться только на классических приложениях для настольных компьютеров и поддерживается на платформах x86 и х64. PGO представляет собой процесс, состоящий из трех этапов, как это показано на рисунке выше.</span><br /><br /></p>
<ul>
<li>Первый этап обычно называют&nbsp;<strong>фазой инструментирования</strong>. В ходе этой фазы идет сборка приложения с заданным набором флагов компиляции. В процессе сборки внутренний компилятор добавляет в созданный код пробные инструкции (зонды), которые используются для записи данных обучения, необходимых на следующем этапе. Всего добавляется три типа зондов (входа в функцию, перехода и значений). Зонд входа в функцию измеряет, как часто запрашивалась та или иная функция. Зонд перехода позволяет узнать, сколько раз была достигнута та или иная ветвь кода. Таким образом в ходе фазы обучения компилятор получает информацию о том, как часто &laquo;a &gt; b&raquo; в фрагменте кода whichBranchisTaken в заданном сценарии обучения. Зонд значений позволяет получить данные для построения гистограммы значений. Например, зонд значений, добавленный в фрагмент кода switchCaseExpansion, позволит получить данные для построения гистограммы значений для переменной индекса switch case i. Получив в ходе обучения информацию о том, какие значения будет принимать переменная &laquo;i&raquo;, компилятор сможет провести оптимизацию для наиболее частых значений, а также таких функций как switchCaseExpansion. Таким образом, по окончании фазы у нас будет инструментированная версия приложения (с зондами) и пустой файл базы данных (.pgd), в которую будет заноситься информация, полученная в ходе следующей фазы.</li>
<li><strong>Фаза обучения&nbsp;</strong>. В ходе этой фазы пользователь запускает инструментированную версию приложения и проигрывает стандартные пользовательские сценарии, требующие высокой производительности. На выходе мы имеем файлы .pgc, содержащие информацию, связанную с различными пользовательскими сценариями. В процессе обучения информация проходит через зонды, добавленные в ходе первой фазы. На выходе мы получаем pgc-файлы appname!# (где appname соответствует названию приложения, а # &mdash; единице плюс числу pgc-файлов appname!# в выходном каталоге построения).</li>
<li><strong>Последняя фаза PGO &mdash; оптимизация</strong>. В ходе этой фазы создается оптимизированная версия приложения. Помимо этого, информация из pgc-файлов, полученная в ходе фазы обучения, вносится в фоновом режиме в базу данных (файл .pgd), созданную в ходе инструментирования. Внутренний компилятор затем использует эту базу данных для последующей оптимизации кода и построения еще более совершенной версии приложения.</li>
</ul>
<p><br /><br /><span>Пользователи PGO зачастую ошибочно считают, что все три фазы (инструментирование, обучение и оптимизация) должны проводиться каждый раз при построении проекта. На самом деле, первые две фазы могут быть исключены при построении последующих версий, а код при этом может претерпевать значительные изменения по сравнению с версией, полученной после фазы обучения приложения. В больших коллективах один разработчик может отвечать за проведение PGO и поддержку базы данных обучения (.pgd) в репозитории исходного кода. Другие разработчики могут синхронизировать свои репозитарии кода с этой базой и использовать файлы обучения для построения PGO-оптимизированных версий приложений. После определенного количества перекомпиляций приложение будет окончательно оптимизировано.</span><br /><br /></p>
<h4>Применение профильной оптимизации</h4>
<p><br /><span>Теперь, когда мы знаем немного больше о профильной оптимизации, рассмотрим ее применение на конкретном примере. Профильную оптимизацию приложения можно осуществлять с помощью Visual Studio или командной строки разработчика. Ниже рассмотрен пример работы в Visual Studio с приложением под условным названием &laquo;Nbody Simulation&raquo;. Если вы хотите узнать больше о PGO в командной строке, обратитесь к&nbsp;</span><a href="https://msdn.microsoft.com/ru-ru/library/aa289170(v=vs.71).aspx">этим статьям</a><span>. Для начала работы загрузите решение в Visual Studio и выберите конфигурацию построения для работы (т.е. &laquo;Release&raquo;).</span><br /><br /><img src="https://habrastorage.org/storage2/9da/0ad/0cf/9da0ad0cffcd5f70dc448c539414eeed.png" alt="" /><br /><br /><span>Как было упомянуто выше, PGO состоит из трех этапов: инструментирования, обучения и оптимизации. Для создания инструментированной версии приложения, нажмите правой кнопкой мыши по названию проекта (&laquo;NBodyGravityCPU&raquo;) и выберите раздел &laquo;Instrument&raquo; в меню &laquo;Profile Guided Optimization&raquo;.</span><br /><br /><img src="https://habrastorage.org/storage2/75c/6c1/333/75c6c13339783c818f2291ae3d469a6f.png" alt="" /><br /><br /><span>В Visual Studio будет построена инструментированная версия приложения. После этого можно переходить к фазе обучения. Запустите инструментированную версию приложения. Для этого зайдите в меню &laquo;Profile Guided Optimization&raquo; и выберите &laquo;Run Instrumented/Optimized Application&raquo;. В нашем случае приложение выполняется с максимально большим телом кода (15360), т. к. будет реализован стабильный пользовательский сценарий, требующий высокой производительности. После того как два основных показателя производительности приложения &mdash; FPS (кадров в секунду) и GFlop &ndash; примут устойчивые значения, вы можете закрыть приложение. На этом фаза обучения будет завершена, а полученные данные будут сохранены в файле .pgc. По умолчанию файл .pgc будет включен в вашу конфигурацию построения, т.е. каталог &laquo;Release&raquo;. Например, в результате этого обучения создается файл NBodyGravityCPU!1.pgc.</span><br /><br /><img src="https://habrastorage.org/storage2/93c/bd8/dae/93cbd8dae442b8d9fa2857429615d389.png" alt="" /><br /><br /><span>NBody Simulation представляет собой очень простое приложение, созданное исключительно для иллюстрации процесса PGO. В действительности может существовать множество вариантов сценариев обучения приложений. В частности, можно производить обучение в несколько этапов, разделенных по времени. Для записи таких сценариев обучения лучше всего использовать команду&nbsp;</span><a href="https://msdn.microsoft.com/ru-ru/library/9hwkw6e8.aspx">pgosweep</a><span>&nbsp;в командной строке разработчика после того, как инструментированная версия уже создана (напр., в Visual Studio).</span><br /><br /><img src="https://habrastorage.org/storage2/373/812/4e7/3738124e725ac44b322bb78d30e1c406.png" alt="" /><br /><br /><span>В ходе последней фазы PGO создается оптимизированная версия приложения. В меню &laquo;Profile Guided Optimization&raquo; выберите &laquo;Optimize&raquo;. Будет создана оптимизированная версия приложения. В выходном журнале PGO-построения вы увидите обобщенную информацию о проведенной операции.</span><br /><span>Как было сказано выше, информация из файлов .pgc, полученная в ходе фазы обучения, включается в базу данных .pgd, которая затем используется матрицей оптимизации внутреннего компилятора. В большинстве случаев (за исключением небольших быстрых приложений) критерий оптимизации скорость/размер определяется соотношением динамических инструкций для определенной функции. Функции с большим числом инструкций (т. н. &laquo;горячие&raquo;) оптимизируются на скорость, а с малым количеством инструкций (т. н. &laquo;холодные&raquo;) &ndash; на размер.</span><br /><span>Это практически все, что вам необходимо для того чтобы начать профильную оптимизацию в ваших приложениях. Попробуйте применить PGO для своих приложений и оцените результаты! И обязательно загляните в блог&nbsp;</span><a href="https://blogs.msdn.com/b/developer-tools-rus/">Инструменты для разработчика</a><span>, возможно вы найдете там еще какие либо интересные решения!&nbsp;</span><br /><span>Автор поста &mdash; Анкит Астхана (</span><a href="https://blogs.msdn.com/487959/ProfileUrlRedirect.ashx">Ankit Asthana</a><span>) &mdash; руководитель программы по внутреннему компилятору Microsoft Visual С++.</span></p><div style="clear:both;"></div><img src="https://blogs.msdn.com/aggbug.aspx?PostID=10422603" width="1" height="1">]]></content:encoded>
    </item>
  </channel>
</rss>