<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
	
.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
<<importTiddlers>>
|''Type:''|file|
|''URL:''|http://ogoshi.tiddlyspot.com/|
|''Workspace:''|(default)|

This tiddler was automatically created to record the details of this server
 XNAは.NET Frameworkの上で動作します。ここでは、何かやろうとするとき、.NET Frameworkの機能で実現できるものと、関連するXNAの補助機能について取り上げます。

!時刻はどう取得する?

 XNAのGameクラスのUpdateメソッドやDrawメソッドの引数で渡されるGameTimeクラスの情報が利用できますが、現在時刻はSystem.DateTime.Nowプロパティでも取得できます。
 時間間隔を正確に測るのであれば、System.Diagnostics.Stopwatchクラスも便利です。

!数学関数はどこにある?

 三角関数などの一般的な数学関数のメソッドは、System.Math静的クラスにあります。

*Sin、Cos、Tan、Abs、Floor、Ceiling、Pow、Exp、Logなど

 また、Math静的クラスを補うメソッドと定数が、XNAのMicrosoft.Xna.Framework.MathHelper静的クラスにあります。

!疑似乱数を作るには?

 System.Randomクラスを使います。
 XNAクリエーターズクラブゲームパッケージ(.ccgame形式)ファイルは、ファイルを開いてUnpackするWindows環境に、XNA Game Studioがインストールされている必要があります。そのバージョンはXNAクリエーターズクラブゲームパッケージ(.ccgame形式)ファイルが対象としているバージョンのXNA Game Studioが必要です。
※実際のXNAクリエーターズクラブゲームパッケージ(.ccgame形式)に対する処理は、XnaPackユーティリティが行っています。

!!XNA Game Studio 3.1のXNAクリエーターズクラブゲームパッケージ(.ccgame形式)ファイルを各XNA Game Studioバージョンをインストールした開発環境でUnpackしたときの動作

!!!開発環境がXNA Game Studio 2.0の場合に表示されるメッセージボックスの内容

|!XNA Game Studio Package Utility|
|Error 2131: Unpacking the game "''ファイル名''" is unsupported for this toolset. Please upgrade your toolset before retrying to unpack this game.|

!!!開発環境がXNA Game Studio 3.0の場合に表示されるメッセージボックスの内容
|!XNA Game Studio Package Utility|
|Error 2160: The packaged game requires a runtime that is not recognized by this version of XnaPack. A newer version of XnaPack may be required to unpack this game, or the package may be invalid.|
 C#でマルチプラットフォーム(たとえばWindowsと[[Xbox 360]]と[[Windows Phone 7]])のコードを書き分けるには、次のようにします。
{{{
 #if WINDOWS
	// Windows用コード
 #elif XBOX
	// Xbox 360用コード
 #elif WINDOWS_PHONE
	// Windows Phone用コード
 #else
	#error プラットフォームが明示されていないか、このゲームではサポートされません。
 #endif
}}}
 このように、XNA用のプロジェクトには条件付きコンパイルシンボルがあらかじめ定義されています。
 多くの部分は共通のコードで書けますが、機能の差などによって書き分ける必要がある場合に使います。

!条件コンパイルシンボル
|!Windowsプラットフォーム|!Xbox 360プラットフォーム|!Windows Phoneプラットフォーム([[XNA Game Studio 4.0]]以降)|
|WINDOWS|XBOX または XBOX360|WINDOWS_PHONE|

:CTP:Community Technical Preview
 [[XNA Game Studio 3.0]]以降、ClickOnce機能を使ってゲームの配布パッケージを作ることができるようになっています。

 配布パッケージは、自動的にインターネットから.Net Framework 3.5とXNA Framework 3.0のダウンロードしてインストールできるようになっています。Windows用の[[XNA Game Studio]]対応ゲームの配布が容易になっています。
 ただし、以下の点では注意が必要です。

*「Game for Windows Live」ランタイムはインストールされないので、XNAのネットワーク機能やGamerServices名前空間の機能を使う場合には、ユーザーにゲームに対応するバージョンの[[XNA Game Studio]]をインストールしてもらう必要があります。

[[目次]]
[[このページの操作について]]
config.options.chkDisableWikiLinks=true;
config.options.chkAllowLinksFromShadowTiddlers=false;
config.options.chkDisableNonExistingWikiLinks=true;
config.options.txtDisableWikiLinksList="DisableWikiLinksList";
config.options.txtDisableWikiLinksTag="excludeWikiWords";
/***
|Name|DisableWikiLinksPlugin|
|Source|http://www.TiddlyTools.com/#DisableWikiLinksPlugin|
|Version|1.6.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Tiddler.prototype.autoLinkWikiWords, 'wikiLink' formatter|
|Options|##Configuration|
|Description|selectively disable TiddlyWiki's automatic ~WikiWord linking behavior|
This plugin allows you to disable TiddlyWiki's automatic ~WikiWord linking behavior, so that WikiWords embedded in tiddler content will be rendered as regular text, instead of being automatically converted to tiddler links.  To create a tiddler link when automatic linking is disabled, you must enclose the link text within {{{[[...]]}}}.
!!!!!Usage
<<<
You can block automatic WikiWord linking behavior for any specific tiddler by ''tagging it with<<tag excludeWikiWords>>'' (see configuration below) or, check a plugin option to disable automatic WikiWord links to non-existing tiddler titles, while still linking WikiWords that correspond to existing tiddlers titles or shadow tiddler titles.  You can also block specific selected WikiWords from being automatically linked by listing them in [[DisableWikiLinksList]] (see configuration below), separated by whitespace.  This tiddler is optional and, when present, causes the listed words to always be excluded, even if automatic linking of other WikiWords is being permitted.  

Note: WikiWords contained in default ''shadow'' tiddlers will be automatically linked unless you select an additional checkbox option lets you disable these automatic links as well, though this is not recommended, since it can make it more difficult to access some TiddlyWiki standard default content (such as AdvancedOptions or SideBarTabs)
<<<
!!!!!Configuration
<<<
<<option chkDisableWikiLinks>> Disable ALL automatic WikiWord tiddler links
<<option chkAllowLinksFromShadowTiddlers>> ... except for WikiWords //contained in// shadow tiddlers
<<option chkDisableNonExistingWikiLinks>> Disable automatic WikiWord links for non-existing tiddlers
Disable automatic WikiWord links for words listed in: <<option txtDisableWikiLinksList>>
Disable automatic WikiWord links for tiddlers tagged with: <<option txtDisableWikiLinksTag>>
<<<
!!!!!Revisions
<<<
2008.07.22 [1.6.0] hijack tiddler changed() method to filter disabled wiki words from internal links[] array (so they won't appear in the missing tiddlers list)
2007.06.09 [1.5.0] added configurable txtDisableWikiLinksTag (default value: "excludeWikiWords") to allows selective disabling of automatic WikiWord links for any tiddler tagged with that value.
2006.12.31 [1.4.0] in formatter, test for chkDisableNonExistingWikiLinks
2006.12.09 [1.3.0] in formatter, test for excluded wiki words specified in DisableWikiLinksList
2006.12.09 [1.2.2] fix logic in autoLinkWikiWords() (was allowing links TO shadow tiddlers, even when chkDisableWikiLinks is TRUE).  
2006.12.09 [1.2.1] revised logic for handling links in shadow content
2006.12.08 [1.2.0] added hijack of Tiddler.prototype.autoLinkWikiWords so regular (non-bracketed) WikiWords won't be added to the missing list
2006.05.24 [1.1.0] added option to NOT bypass automatic wikiword links when displaying default shadow content (default is to auto-link shadow content)
2006.02.05 [1.0.1] wrapped wikifier hijack in init function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals
2005.12.09 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.DisableWikiLinksPlugin= {major: 1, minor: 6, revision: 0, date: new Date(2008,7,22)};

if (config.options.chkDisableNonExistingWikiLinks==undefined) config.options.chkDisableNonExistingWikiLinks= false;
if (config.options.chkDisableWikiLinks==undefined) config.options.chkDisableWikiLinks=false;
if (config.options.txtDisableWikiLinksList==undefined) config.options.txtDisableWikiLinksList="DisableWikiLinksList";
if (config.options.chkAllowLinksFromShadowTiddlers==undefined) config.options.chkAllowLinksFromShadowTiddlers=true;
if (config.options.txtDisableWikiLinksTag==undefined) config.options.txtDisableWikiLinksTag="excludeWikiWords";

// find the formatter for wikiLink and replace handler with 'pass-thru' rendering
initDisableWikiLinksFormatter();
function initDisableWikiLinksFormatter() {
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="wikiLink"; i++);
	config.formatters[i].coreHandler=config.formatters[i].handler;
	config.formatters[i].handler=function(w) {
		// supress any leading "~" (if present)
		var skip=(w.matchText.substr(0,1)==config.textPrimitives.unWikiLink)?1:0;
		var title=w.matchText.substr(skip);
		var exists=store.tiddlerExists(title);
		var inShadow=w.tiddler && store.isShadowTiddler(w.tiddler.title);
		// check for excluded Tiddler
		if (w.tiddler && w.tiddler.isTagged(config.options.txtDisableWikiLinksTag))
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }
		// check for specific excluded wiki words
		var t=store.getTiddlerText(config.options.txtDisableWikiLinksList);
		if (t && t.length && t.indexOf(w.matchText)!=-1)
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }
		// if not disabling links from shadows (default setting)
		if (config.options.chkAllowLinksFromShadowTiddlers && inShadow)
			return this.coreHandler(w);
		// check for non-existing non-shadow tiddler
		if (config.options.chkDisableNonExistingWikiLinks && !exists)
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }
		// if not enabled, just do standard WikiWord link formatting
		if (!config.options.chkDisableWikiLinks)
			return this.coreHandler(w);
		// just return text without linking
		w.outputText(w.output,w.matchStart+skip,w.nextMatch)
	}
}

Tiddler.prototype.coreAutoLinkWikiWords = Tiddler.prototype.autoLinkWikiWords;
Tiddler.prototype.autoLinkWikiWords = function()
{
	// if all automatic links are not disabled, just return results from core function
	if (!config.options.chkDisableWikiLinks)
		return this.coreAutoLinkWikiWords.apply(this,arguments);
	return false;
}

Tiddler.prototype.disableWikiLinks_changed = Tiddler.prototype.changed;
Tiddler.prototype.changed = function()
{
	this.disableWikiLinks_changed.apply(this,arguments);
	// remove excluded wiki words from links array
	var t=store.getTiddlerText(config.options.txtDisableWikiLinksList,"").readBracketedList();
	if (t.length) for (var i=0; i<t.length; i++)
		if (this.links.contains(t[i]))
			this.links.splice(this.links.indexOf(t[i]),1);
};
//}}}
 Microsoft DreamSparkでは、学生の方々にMicrosoftの開発ツールが無償提供されます。XNA開発にも役立つものが含まれます。

 XNA開発で必要最低限の開発環境は、誰でも無償で利用できます。しかし、学生の方々はDreamSparkを利用すれば、有償の開発ツール([[Visual Studio]] 2008 ProfessionalエディションやExpression Studio 3など)が無償で利用できます。詳細な利用条件などについては、関連サイトをよくご確認ください。

*http://www.microsoft.com/japan/academic/dreamspark/default.mspx
*https://www.dreamspark.com/default.aspx
 XNA Game Studio 3.1において、次のようなコード(effectはEffectクラスのインスタンス)では、ガベージが発生してしまいます。
(ただし、将来のバージョンで、この問題が続くかは不明です。)

{{cs{
foreach (var pass in effect.CurrentTechnique.Passes) {
}
}}}

※パフォーマンスを重視する場合、ガベージコレクションの動作を最小にするため、ガベージの発生は抑えたいものです。

 この問題を回避する方法を2つ挙げます。

!解決法1 : for文にする
{{cs{
for (int i = 0;i < effect.CurrentTechnique.Count; i++) {
	var pass = effect.CurrentTechnique.Passes[i];
}
}}}

!解決法2 : GetEnumeratorメソッド関連の代替処理を用意する

 サンプルコードのようにコードを追加して使います。

{{cs{
foreach (var pass in effect.CurrentTechnique.Passes()) {
}
}}}

!!!サンプルコード
{{cs{
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace GarbageFreeEffectPassEnumerator {

	public struct EffectPassEnumerator : IEnumerator<EffectPass> {
		EffectPassCollection passes;
		int index;
		public EffectPassEnumerator(EffectPassCollection passes) {
			this.passes = passes; index = -1;
		}
		public EffectPassEnumerator GetEnumerator() { return this; }
		public EffectPass Current { get { return passes[index]; } }
		public void Dispose() { }
		object System.Collections.IEnumerator.Current { get { return passes[index]; } }
		public bool MoveNext() {
			if (index >= passes.Count - 1) return false;
			index++; return true;
		}
		public void Reset() { index = -1; }
	}

	public static partial class Helper {
		public static EffectPassEnumerator Passes(this EffectTechnique technique) {
			return new EffectPassEnumerator(technique.Passes);
		}
		public static EffectPassEnumerator ForEach(this EffectPassCollection passes) {
			return new EffectPassEnumerator(passes);
		}
	}

	public class EffectPassGame : Microsoft.Xna.Framework.Game {
		GraphicsDeviceManager graphics;
		BasicEffect effect;
		VertexPositionColor[] vertices = {
			new VertexPositionColor(new Vector3(-1, -1, 0), Color.Blue),
			new VertexPositionColor(new Vector3(-1, +1, 0), Color.Green),
			new VertexPositionColor(new Vector3(+1, -1, 0), Color.Red),
		};
		VertexDeclaration declaration;

		public EffectPassGame() {
			graphics = new GraphicsDeviceManager(this);
			Content.RootDirectory = "Content";
		}

		protected override void LoadContent() {
			effect = new BasicEffect(GraphicsDevice, null);
			effect.VertexColorEnabled = true;
			declaration = new VertexDeclaration(GraphicsDevice, VertexPositionColor.VertexElements);
		}

		protected override void Update(GameTime gameTime) {
			if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
				this.Exit();

			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime) {
			GraphicsDevice.Clear(Color.CornflowerBlue);
			effect.Begin();
			GraphicsDevice.VertexDeclaration = declaration;

			&#47;&#47; foreach (var pass in effect.CurrentTechnique.Passes) {
			foreach (var pass in effect.CurrentTechnique.Passes()) {
				pass.Begin();
				GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0, 1);
				pass.End();
			}

			effect.End();
			base.Draw(gameTime);
		}
	}
}
}}}
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.8.4|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|select and extract tiddlers from your ~TiddlyWiki documents and save them to a separate file|
ExportTiddlersPlugin lets you select and extract tiddlers from your ~TiddlyWiki documents using interactive control panel lets you specify a destination, and then select which tiddlers to export. Tiddler data can be output as complete, stand-alone TiddlyWiki documents, or just the selected tiddlers ('~PureStore' format -- smaller files!) that can be imported directly into another ~TiddlyWiki, or as an ~RSS-compatible XML file that can be published for RSS syndication.
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Inline control panel (live):
><<exportTiddlers inline>>
!!!!!Revisions
<<<
2008.09.29 [2.8.4] in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
|please see [[ExportTiddlersPluginInfo]] for additional revision details|
2005.10.09 [0.0.0] development started
<<<
!!!!!Code
***/
//{{{
// version
version.extensions.ExportTiddlersPlugin= {major: 2, minor: 8, revision: 4, date: new Date(2008,9,29)};

// default shadow definition
config.shadowTiddlers.ExportTiddlers='<<exportTiddlers inline>>';

// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
	config.tasks.exportTask = {
		text:'export',
		tooltip:'Export selected tiddlers to another file',
		content:'<<exportTiddlers inline>>'
	}
	config.backstageTasks.splice(config.backstageTasks.indexOf('importTask')+1,0,'exportTask');
}

// $(...) function: 'shorthand' convenience syntax for document.getElementById()
if (typeof($)=='undefined') { // avoid redefinition
function $() {
	var elements=new Array();
	for (var i=0; i<arguments.length; i++) {
		var element=arguments[i];
		if (typeof element=='string') element=document.getElementById(element);
		if (arguments.length==1) return element;
		elements.push(element);
	}
	return elements;
}
}

config.macros.exportTiddlers = {
	label: 'export tiddlers',
	prompt: 'Copy selected tiddlers to an export document',
	okmsg: '%0 tiddlers written to %1',
	failmsg: 'An error occurred while creating %1',
	mergeprompt: '%0\nalready contains tiddler definitions.\n'
		+'\nPress OK to add new/revised tiddlers to current file contents.'
		+'\nPress Cancel to completely replace file contents',
	mergestatus: 'Merged %0 new/revised tiddlers with %1 previously saved tiddlers',
	statusmsg: '%0 tiddler%1 - %2 selected for export',
	newdefault: 'export.html',
	datetimefmt: '0MM/0DD/YYYY 0hh:0mm:0ss',  // for 'filter date/time' edit fields
	type_TW: 'tw', type_PS: 'ps', type_TX: 'tx', type_NF: 'nf', // file type tokens
	type_map: { // map filetype param alternatives/abbreviations to token values
		tiddlywiki:'tw', tw:'tw', wiki: 'tw',
		purestore: 'ps', ps:'ps', store:'ps',
		plaintext: 'tx', tx:'tx', text: 'tx',
		newsfeed:  'nf', nf:'nf', xml:  'nf', rss:'nf'
	},
	handler: function(place,macroName,params) {
		if (params[0]!='inline')
			{ createTiddlyButton(place,this.label,this.prompt,this.togglePanel); return; }
		var panel=this.createPanel(place);
		panel.style.position='static';
		panel.style.display='block';
	},
	createPanel: function(place) {
		var panel=$('exportPanel');
		if (panel) { panel.parentNode.removeChild(panel); }
		setStylesheet(this.css,'exportTiddlers');
		panel=createTiddlyElement(place,'span','exportPanel',null,null)
		panel.innerHTML=this.html;
		this.initFilter();
		this.refreshList(0);
		var fn=$('exportFilename');
		if (window.location.protocol=='file:' && !fn.value.length) {
			// get new target path/filename
			var newPath=getLocalPath(window.location.href);
			var slashpos=newPath.lastIndexOf('/'); if (slashpos==-1) slashpos=newPath.lastIndexOf('\\'); 
			if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
			fn.value=newPath+this.newdefault;
		}
		return panel;
	},
	togglePanel: function(e) {
		if (!e) var e = window.event;
		var parent=resolveTarget(e).parentNode;
		var panel = $('exportPanel');
		if (panel==undefined || panel.parentNode!=parent)
			panel=config.macros.exportTiddlers.createPanel(parent);
		var isOpen = panel.style.display=='block';
		if(config.options.chkAnimate)
			anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,'none'));
		else
			panel.style.display = isOpen ? 'none' : 'block' ;
		if (panel.style.display!='none') { // update list and set focus when panel is made visible
			config.macros.exportTiddlers.refreshList(0);
			var fn=$('exportFilename'); fn.focus(); fn.select();
		}
		e.cancelBubble = true;
		if (e.stopPropagation) e.stopPropagation();
		return(false);
	},
	css: '\
		#exportPanel {\
			display: none; position:absolute; z-index:12; width:35em; right:105%; top:6em;\
			background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
			border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
			padding: 0.5em; margin:0em; -moz-border-radius:1em;-webkit-border-radius:1em;\
		}\
		#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
		#exportPanel table { \
			width:100%; border:0px; padding:0px; margin:0px;\
			font-size:8pt; line-height:110%; background:transparent;\
		}\
		#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
		#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
		#exportPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\
		#exportPanel input  { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%; }\
		#exportPanel textarea  { width:98%;padding:0px;margin:0px;overflow:auto;font-size:8pt; }\
		#exportPanel .box { \
			border:1px solid black; padding:3px; margin-bottom:5px; \
			background:#f8f8f8; -moz-border-radius:5px;-webkit-border-radius:5px; }\
		#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\
		#exportPanel .rad { width:auto;border:0 }\
		#exportPanel .chk { width:auto;border:0 }\
		#exportPanel .btn { width:auto; }\
		#exportPanel .btn1 { width:98%; }\
		#exportPanel .btn2 { width:48%; }\
		#exportPanel .btn3 { width:32%; }\
		#exportPanel .btn4 { width:24%; }\
		#exportPanel .btn5 { width:19%; }\
	',
	html: '\
		<!-- target path/file  -->\
		<div>\
		export to path/filename:<br>\
		<input type="text" id="exportFilename" size=40 style="width:93%"><input \
			type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%" \
			onclick="var fn=config.macros.exportTiddlers.askForFilename(this); if (fn.length) this.previousSibling.value=fn; ">\
		</div>\
		<!-- output format -->\
		<div>\
		output file format:\
		<select id="exportFormat" size=1>\
			<option value="TW">TiddlyWiki HTML document (includes core code)</option>\
			<option value="PS">TiddlyWiki "PureStore" HTML file (tiddler data only)</option>\
			<option value="TX">TiddlyWiki plain text TXT file (tiddler source listing)</option>\
			<option value="NF">RSS NewsFeed XML file</option>\
		</select>\
		</div>\
		<!-- notes -->\
		<div>\
		notes:<br>\
		<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea> \
		</div>\
		<!-- list of tiddlers -->\
		<table><tr align="left"><td>\
			select:\
			<a href="JavaScript:;" id="exportSelectAll"\
				onclick="config.macros.exportTiddlers.process(this)" title="select all tiddlers">\
				&nbsp;all&nbsp;</a>\
			<a href="JavaScript:;" id="exportSelectChanges"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers changed since last save">\
				&nbsp;changes&nbsp;</a> \
			<a href="JavaScript:;" id="exportSelectOpened"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers currently being displayed">\
				&nbsp;opened&nbsp;</a> \
			<a href="JavaScript:;" id="exportSelectRelated"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers related to the currently selected tiddlers">\
				&nbsp;related&nbsp;</a> \
			<a href="JavaScript:;" id="exportToggleFilter"\
				onclick="config.macros.exportTiddlers.process(this)" title="show/hide selection filter">\
				&nbsp;filter&nbsp;</a>  \
		</td><td align="right">\
			<a href="JavaScript:;" id="exportListSmaller"\
				onclick="config.macros.exportTiddlers.process(this)" title="reduce list size">\
				&nbsp;&#150;&nbsp;</a>\
			<a href="JavaScript:;" id="exportListLarger"\
				onclick="config.macros.exportTiddlers.process(this)" title="increase list size">\
				&nbsp;+&nbsp;</a>\
		</td></tr></table>\
		<select id="exportList" multiple size="10" style="margin-bottom:5px;"\
			onchange="config.macros.exportTiddlers.refreshList(this.selectedIndex)">\
		</select><br>\
		</div><!--box-->\
		<!-- selection filter -->\
		<div id="exportFilterPanel" style="display:none">\
		<table><tr align="left"><td>\
			selection filter\
		</td><td align="right">\
			<a href="JavaScript:;" id="exportHideFilter"\
				onclick="config.macros.exportTiddlers.process(this)" title="hide selection filter">hide</a>\
		</td></tr></table>\
		<div class="box">\
		<input type="checkbox" class="chk" id="exportFilterStart" value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> starting date/time<br>\
		<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
			<select size=1 id="exportFilterStartBy" \
				onchange="config.macros.exportTiddlers.showFilterFields(this);">\
				<option value="0">today</option>\
				<option value="1">yesterday</option>\
				<option value="7">a week ago</option>\
				<option value="30">a month ago</option>\
				<option value="file">file date</option>\
				<option value="other">other (mm/dd/yyyy hh:mm)</option>\
			</select>\
		</td><td width="50%">\
			<input type="text" id="exportStartDate" onfocus="this.select()"\
				onchange="$(\'exportFilterStartBy\').value=\'other\';">\
		</td></tr></table>\
		<input type="checkbox" class="chk" id="exportFilterEnd" value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> ending date/time<br>\
		<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
			<select size=1 id="exportFilterEndBy" \
				onchange="config.macros.exportTiddlers.showFilterFields(this);">\
				<option value="0">today</option>\
				<option value="1">yesterday</option>\
				<option value="7">a week ago</option>\
				<option value="30">a month ago</option>\
				<option value="file">file date</option>\
				<option value="other">other (mm/dd/yyyy hh:mm)</option>\
			</select>\
		</td><td width="50%">\
			<input type="text" id="exportEndDate" onfocus="this.select()"\
				onchange="$(\'exportFilterEndBy\').value=\'other\';">\
		</td></tr></table>\
		<input type="checkbox" class="chk" id=exportFilterTags value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> match tags<br>\
		<input type="text" id="exportTags" onfocus="this.select()">\
		<input type="checkbox" class="chk" id=exportFilterText value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> match titles/tiddler text<br>\
		<input type="text" id="exportText" onfocus="this.select()">\
		</div> <!--box-->\
		</div> <!--panel-->\
		<!-- action buttons -->\
		<div style="text-align:center">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportFilter" value="apply filter">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportStart" value="export tiddlers">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportDelete" value="delete tiddlers">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportClose" value="close">\
		</div><!--center-->\
	',
	process: function(which) { // process panel control interactions
		// DEBUG alert(which.id);
		var theList=$('exportList'); if (!theList) return;
		var count = 0;
		var total = store.getTiddlers('title').length;
		switch (which.id) {
			case 'exportFilter':
				count=this.filterExportList();
				var panel=$('exportFilterPanel');
				if (count==-1) { panel.style.display='block'; break; }
				$('exportStart').disabled=(count==0);
				$('exportDelete').disabled=(count==0);
				this.displayStatus(count,total);
				if (count==0) { alert('No tiddlers were selected'); panel.style.display='block'; }
				break;
			case 'exportStart':
				this.go();
				break;
			case 'exportDelete':
				this.deleteTiddlers();
				break;
			case 'exportHideFilter':
			case 'exportToggleFilter':
				var panel=$('exportFilterPanel')
				panel.style.display=(panel.style.display=='block')?'none':'block';
				break;
			case 'exportSelectChanges':
				var lastmod=new Date(document.lastModified);
				for (var t = 0; t < theList.options.length; t++) {
					if (theList.options[t].value=='') continue;
					var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;
					theList.options[t].selected=(tiddler.modified>lastmod);
					count += (tiddler.modified>lastmod)?1:0;
				}
				$('exportStart').disabled=(count==0);
				$('exportDelete').disabled=(count==0);
				this.displayStatus(count,total);
				if (count==0) alert('There are no unsaved changes');
				break;
			case 'exportSelectAll':
				for (var t = 0; t < theList.options.length; t++) {
					if (theList.options[t].value=='') continue;
					theList.options[t].selected=true;
					count += 1;
				}
				$('exportStart').disabled=(count==0);
				$('exportDelete').disabled=(count==0);
				this.displayStatus(count,count);
				break;
			case 'exportSelectOpened':
				for (var t = 0; t < theList.options.length; t++) theList.options[t].selected=false;
				var tiddlerDisplay = $('tiddlerDisplay'); // for TW2.1-
				if (!tiddlerDisplay) tiddlerDisplay = $('storyDisplay'); // for TW2.2+
				for (var t=0;t<tiddlerDisplay.childNodes.length;t++) {
					var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);
					for (var i = 0; i < theList.options.length; i++) {
						if (theList.options[i].value!=tiddler) continue;
						theList.options[i].selected=true; count++; break;
					}
				}
				$('exportStart').disabled=(count==0);
				$('exportDelete').disabled=(count==0);
				this.displayStatus(count,total);
				if (count==0) alert('There are no tiddlers currently opened');
				break;
			case 'exportSelectRelated':
				// recursively build list of related tiddlers
				function getRelatedTiddlers(tid,tids) {
					var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
					tids.push(t.title);
					if (!t.linksUpdated) t.changed();
					for (var i=0; i<t.links.length; i++)
						if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
					return tids;
				}
				// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
				var tids=[];
				for (var i=0; i<theList.options.length; i++)
					if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
				// select related tiddlers (includes original selected tiddlers)
				for (var i=0; i<theList.options.length; i++)
					theList.options[i].selected=tids.contains(theList.options[i].value);
				this.displayStatus(tids.length,total);
				break;
			case 'exportListSmaller':	// decrease current listbox size
				var min=5;
				theList.size-=(theList.size>min)?1:0;
				break;
			case 'exportListLarger':	// increase current listbox size
				var max=(theList.options.length>25)?theList.options.length:25;
				theList.size+=(theList.size<max)?1:0;
				break;
			case 'exportClose':
				$('exportPanel').style.display='none';
				break;
		}
	},
	displayStatus: function(count,total) {
		var txt=this.statusmsg.format([total,total!=1?'s':'',!count?'none':count==total?'all':count]);
		clearMessage();	displayMessage(txt);
		return txt;
	},
	refreshList: function(selectedIndex) {
		var theList = $('exportList'); if (!theList) return;
		// get the sort order
		var sort;
		if (!selectedIndex)   selectedIndex=0;
		if (selectedIndex==0) sort='modified';
		if (selectedIndex==1) sort='title';
		if (selectedIndex==2) sort='modified';
		if (selectedIndex==3) sort='modifier';
		if (selectedIndex==4) sort='tags';

		// unselect headings and count number of tiddlers actually selected
		var count=0;
		for (var t=5; t < theList.options.length; t++) {
			if (!theList.options[t].selected) continue;
			if (theList.options[t].value!='')
				count++;
			else { // if heading is selected, deselect it, and then select and count all in section
				theList.options[t].selected=false;
				for ( t++; t<theList.options.length && theList.options[t].value!=''; t++) {
					theList.options[t].selected=true;
					count++;
				}
			}
		}

		// disable 'export' and 'delete' buttons if no tiddlers selected
		$('exportStart').disabled=(count==0);
		$('exportDelete').disabled=(count==0);

		// show selection count
		var tiddlers = store.getTiddlers('title');
		if (theList.options.length) this.displayStatus(count,tiddlers.length);

		// if a [command] item, reload list... otherwise, no further refresh needed
		if (selectedIndex>4) return;

		// clear current list contents
		while (theList.length > 0) { theList.options[0] = null; }
		// add heading and control items to list
		var i=0;
		var indent=String.fromCharCode(160)+String.fromCharCode(160);
		theList.options[i++]=
			new Option(tiddlers.length+' tiddlers in document', '',false,false);
		theList.options[i++]=
			new Option(((sort=='title'   )?'>':indent)+' [by title]', '',false,false);
		theList.options[i++]=
			new Option(((sort=='modified')?'>':indent)+' [by date]', '',false,false);
		theList.options[i++]=
			new Option(((sort=='modifier')?'>':indent)+' [by author]', '',false,false);
		theList.options[i++]=
			new Option(((sort=='tags'    )?'>':indent)+' [by tags]', '',false,false);

		// output the tiddler list
		switch(sort) {
			case 'title':
				for(var t = 0; t < tiddlers.length; t++)
					theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
				break;
			case 'modifier':
			case 'modified':
				var tiddlers = store.getTiddlers(sort);
				// sort descending for newest date first
				tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });
				var lastSection = '';
				for(var t = 0; t < tiddlers.length; t++) {
					var tiddler = tiddlers[t];
					var theSection = '';
					if (sort=='modified') theSection=tiddler.modified.toLocaleDateString();
					if (sort=='modifier') theSection=tiddler.modifier;
					if (theSection != lastSection) {
						theList.options[i++] = new Option(theSection,'',false,false);
						lastSection = theSection;
					}
					theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
				}
				break;
			case 'tags':
				var theTitles = {}; // all tiddler titles, hash indexed by tag value
				var theTags = new Array();
				for(var t=0; t<tiddlers.length; t++) {
					var title=tiddlers[t].title;
					var tags=tiddlers[t].tags;
					if (!tags || !tags.length) {
						if (theTitles['untagged']==undefined) { theTags.push('untagged'); theTitles['untagged']=new Array(); }
						theTitles['untagged'].push(title);
					}
					else for(var s=0; s<tags.length; s++) {
						if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
						theTitles[tags[s]].push(title);
					}
				}
				theTags.sort();
				for(var tagindex=0; tagindex<theTags.length; tagindex++) {
					var theTag=theTags[tagindex];
					theList.options[i++]=new Option(theTag,'',false,false);
					for(var t=0; t<theTitles[theTag].length; t++)
						theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
				}
				break;
			}
		theList.selectedIndex=selectedIndex; // select current control item
		$('exportStart').disabled=true;
		$('exportDelete').disabled=true;
		this.displayStatus(0,tiddlers.length);
	},
	askForFilename: function(here) {
		var msg=here.title; // use tooltip as dialog box message
		var path=getLocalPath(document.location.href);
		var slashpos=path.lastIndexOf('/'); if (slashpos==-1) slashpos=path.lastIndexOf('\\'); 
		if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
		var filetype=$('exportFormat').value.toLowerCase();
		var defext='html';
		if (filetype==this.type_TX) defext='txt';
		if (filetype==this.type_NF) defext='xml';
		var file=this.newdefault.replace(/html$/,defext);
		var result='';
		if(window.Components) { // moz
			try {
				netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
				var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
				var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
				picker.init(window, msg, nsIFilePicker.modeSave);
				var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
				thispath.initWithPath(path);
				picker.displayDirectory=thispath;
				picker.defaultExtension=defext;
				picker.defaultString=file;
				picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
				if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
			}
			catch(e) { alert('error during local file access: '+e.toString()) }
		}
		else { // IE
			try { // XPSP2 IE only
				var s = new ActiveXObject('UserAccounts.CommonDialog');
				s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|XML files|*.xml|';
				s.FilterIndex=defext=='txt'?2:'html'?3:'xml'?4:1;
				s.InitialDir=path;
				s.FileName=file;
				if (s.showOpen()) var result=s.FileName;
			}
			catch(e) {  // fallback
				var result=prompt(msg,path+file);
			}
		}
		return result;
	},
	initFilter: function() {
		// start date
		$('exportFilterStart').checked=false;
		$('exportStartDate').value='';
		// end date
		$('exportFilterEnd').checked=false;
		$('exportEndDate').value='';
		// tags
		$('exportFilterTags').checked=false;
		$('exportTags').value='';
		// text
		$('exportFilterText').checked=false;
		$('exportText').value='';
		// show/hide filter input fields
		this.showFilterFields();
	},
	showFilterFields: function(which) {
		var show=$('exportFilterStart').checked;
		$('exportFilterStartBy').style.display=show?'block':'none';
		$('exportStartDate').style.display=show?'block':'none';
		var val=$('exportFilterStartBy').value;
		$('exportStartDate').value
			=this.getFilterDate(val,'exportStartDate').formatString(this.datetimefmt);
		if (which && (which.id=='exportFilterStartBy') && (val=='other'))
			$('exportStartDate').focus();

		var show=$('exportFilterEnd').checked;
		$('exportFilterEndBy').style.display=show?'block':'none';
		$('exportEndDate').style.display=show?'block':'none';
		var val=$('exportFilterEndBy').value;
		$('exportEndDate').value
			=this.getFilterDate(val,'exportEndDate').formatString(this.datetimefmt);
		 if (which && (which.id=='exportFilterEndBy') && (val=='other'))
			$('exportEndDate').focus();

		var show=$('exportFilterTags').checked;
		$('exportTags').style.display=show?'block':'none';

		var show=$('exportFilterText').checked;
		$('exportText').style.display=show?'block':'none';
	},
	getFilterDate: function(val,id) {
		var result=0;
		switch (val) {
			case 'file':
				result=new Date(document.lastModified);
				break;
			case 'other':
				result=new Date($(id).value);
				break;
			default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31
				var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;
				var oneday=86400000;
				if (id=='exportStartDate')
					result=new Date((Math.floor(now/oneday)-val)*oneday+tz);
				else
					result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);
				break;
		}
		return result;
	},
	filterExportList: function() {
		var theList  = $('exportList'); if (!theList) return -1;
		var filterStart=$('exportFilterStart').checked;
		var val=$('exportFilterStartBy').value;
		var startDate=config.macros.exportTiddlers.getFilterDate(val,'exportStartDate');
		var filterEnd=$('exportFilterEnd').checked;
		var val=$('exportFilterEndBy').value;
		var endDate=config.macros.exportTiddlers.getFilterDate(val,'exportEndDate');
		var filterTags=$('exportFilterTags').checked;
		var tags=$('exportTags').value;
		var filterText=$('exportFilterText').checked;
		var text=$('exportText').value;
		if (!(filterStart||filterEnd||filterTags||filterText)) {
			alert('Please set the selection filter');
			$('exportFilterPanel').style.display='block';
			return -1;
		}
		if (filterStart&&filterEnd&&(startDate>endDate)) {
			var msg='starting date/time:\n'
			msg+=startDate.toLocaleString()+'\n';
			msg+='is later than ending date/time:\n'
			msg+=endDate.toLocaleString()
			alert(msg);
			return -1;
		}
		// if filter by tags, get list of matching tiddlers
		// use getMatchingTiddlers() (if MatchTagsPlugin is installed) for full boolean expressions
		// otherwise use getTaggedTiddlers() for simple tag matching
		if (filterTags) {
			var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
			var t=fn.apply(store,[tags]);
			var tagged=[];
			for (var i=0; i<t.length; i++) tagged.push(t[i].title);
		}
		// scan list and select tiddlers that match all applicable criteria
		var total=0;
		var count=0;
		for (var i=0; i<theList.options.length; i++) {
			// get item, skip non-tiddler list items (section headings)
			var opt=theList.options[i]; if (opt.value=='') continue;
			// get tiddler, skip missing tiddlers (this should NOT happen)
			var tiddler=store.getTiddler(opt.value); if (!tiddler) continue; 
			var sel=true;
			if ( (filterStart && tiddler.modified<startDate)
			|| (filterEnd && tiddler.modified>endDate)
			|| (filterTags && !tagged.contains(tiddler.title))
			|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
				sel=false;
			opt.selected=sel;
			count+=sel?1:0;
			total++;
		}
		return count;
	},
	deleteTiddlers: function() {
		var list=$('exportList'); if (!list) return;
		var tids=[];
		for (i=0;i<list.length;i++)
			if (list.options[i].selected && list.options[i].value.length)
				tids.push(list.options[i].value);
		if (!confirm('Are you sure you want to delete these tiddlers:\n\n'+tids.join(', '))) return;
		store.suspendNotifications();
		for (t=0;t<tids.length;t++) {
			var tid=store.getTiddler(tids[t]); if (!tid) continue;
			var msg="'"+tid.title+"' is tagged with 'systemConfig'.\n\n";
			msg+='Removing this tiddler may cause unexpected results.  Are you sure?'
			if (tid.tags.contains('systemConfig') && !confirm(msg)) continue;
			store.removeTiddler(tid.title);
			story.closeTiddler(tid.title);
		}
		store.resumeNotifications();
		alert(tids.length+' tiddlers deleted');
		this.refreshList(0); // reload listbox
		store.notifyAll(); // update page display
	},
	go: function() {
		if (window.location.protocol!='file:') // make sure we are local
			{ displayMessage(config.messages.notFileUrlError); return; }
		// get selected tidders, target filename, target type, and notes
		var list=$('exportList'); if (!list) return;
		var tids=[]; for (var i=0; i<list.options.length; i++) {
			var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
			var tid=store.getTiddler(opt.value); if (!tid) continue;
			tids.push(tid);
		}
		if (!tids.length) return; // no tiddlers selected
		var target = $('exportFilename').value.trim();
		if (!target.length) {
			displayMessage('A local target path/filename is required',target);
			return;
		}
		var filetype = $('exportFormat').value.toLowerCase();
		var notes=$('exportNotes').value.replace(/\n/g,'<br>');
		var total={val:0};
		var out=this.assembleFile(target,filetype,tids,notes,total);
		var link='file:///'+target.replace(/\\/g,'/');
		var samefile=link==decodeURIComponent(window.location.href);
		var p=getLocalPath(document.location.href);
		if (samefile) {
			if (config.options.chkSaveBackups) { var t=loadOriginal(p);if(t)saveBackup(p,t); }
			if (config.options.chkGenerateAnRssFeed && saveRss instanceof Function) saveRss(p);
		}
		var ok=saveFile(target,out);
		displayMessage((ok?this.okmsg:this.failmsg).format([total.val,target]),link);
	},
	plainTextHeader:
		 '// Source'+':\n//\t%0\n'
		+'// Title:\n//\t%1\n'
		+'// Subtitle:\n//\t%2\n'
		+'// Created:\n//\t%3 by %4\n'
		+'// Application:\n//\tTiddlyWiki %5 / %6 %7\n',
	plainTextTiddler:
		'\n// ----- %0 (by %1 on %2) -----\n\n%3',
	plainTextFooter:
		'',
	newsFeedHeader:
		 '<'+'?xml version="1.0"?'+'>\n'
		+'<rss version="2.0">\n'
		+'<channel>\n'
		+'<title>%1</title>\n'
		+'<link>%0</link>\n'
		+'<description>%2</description>\n'
		+'<language>en-us</language>\n'
		+'<copyright>Copyright '+(new Date().getFullYear())+' %4</copyright>\n'
		+'<pubDate>%3</pubDate>\n'
		+'<lastBuildDate>%3</lastBuildDate>\n'
		+'<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n'
		+'<generator>TiddlyWiki %5 / %6 %7</generator>\n',
	newsFeedTiddler:
		'\n%0\n',
	newsFeedFooter:
		'</channel></rss>',
	pureStoreHeader:
		 '<html><body>'
		+'<style type="text/css">'
		+'	#storeArea {display:block;margin:1em;}'
		+'	#storeArea div {padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}'
		+'	#pureStoreHeading {width:100%;text-align:left;background-color:#eeeeee;padding:1em;}'
		+'</style>'
		+'<div id="pureStoreHeading">'
		+'	TiddlyWiki "PureStore" export file<br>'
		+'	Source'+': <b>%0</b><br>'
		+'	Title: <b>%1</b><br>'
		+'	Subtitle: <b>%2</b><br>'
		+'	Created: <b>%3</b> by <b>%4</b><br>'
		+'	TiddlyWiki %5 / %6 %7<br>'
		+'	Notes:<hr><pre>%8</pre>'
		+'</div>'
		+'<div id="storeArea">',
	pureStoreTiddler:
		'%0\n%1',
	pureStoreFooter:
		'</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>',
	assembleFile: function(target,filetype,tids,notes,total) {
		var revised='';
		var now = new Date().toLocaleString();
		var src=convertUnicodeToUTF8(document.location.href);
		var title = convertUnicodeToUTF8(wikifyPlain('SiteTitle').htmlEncode());
		var subtitle = convertUnicodeToUTF8(wikifyPlain('SiteSubtitle').htmlEncode());
		var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
		var twver = version.major+'.'+version.minor+'.'+version.revision;
		var v=version.extensions.ExportTiddlersPlugin; var pver = v.major+'.'+v.minor+'.'+v.revision;
		var headerargs=[src,title,subtitle,now,user,twver,'ExportTiddlersPlugin',pver,notes];
		switch (filetype) {
			case this.type_TX: // plain text
				var header=this.plainTextHeader.format(headerargs);
				var footer=this.plainTextFooter;
				break;
			case this.type_NF: // news feed (XML)
				headerargs[0]=store.getTiddlerText('SiteUrl','');
				var header=this.newsFeedHeader.format(headerargs);
				var footer=this.newsFeedFooter;
				break;
			case this.type_PS: // PureStore (no code)
				var header=this.pureStoreHeader.format(headerargs);
				var footer=this.pureStoreFooter;
				break;
			case this.type_TW: // full TiddlyWiki
			default:
				var currPath=getLocalPath(window.location.href);
				var original=loadFile(currPath);
				if (!original) { displayMessage(config.messages.cantSaveError); return; }
				var posDiv = locateStoreArea(original);
				if (!posDiv) { displayMessage(config.messages.invalidFileError.format([currPath])); return; }
				var header = original.substr(0,posDiv[0]+startSaveArea.length)+'\n';
				var footer = '\n'+original.substr(posDiv[1]);
				break;
		}
		var out=this.getData(target,filetype,tids);
		var revised = header+convertUnicodeToUTF8(out.join('\n'))+footer;
		// if full TW, insert page title and language attr, and reset all MARKUP blocks...
		if (filetype==this.type_TW) {
			var newSiteTitle=convertUnicodeToUTF8(getPageTitle()).htmlEncode();
			revised=revised.replaceChunk('<title'+'>','</title'+'>',' ' + newSiteTitle + ' ');
			revised=updateLanguageAttribute(revised);
			var titles=[]; for (var i=0; i<tids.length; i++) titles.push(tids[i].title);
			revised=updateMarkupBlock(revised,'PRE-HEAD',
				titles.contains('MarkupPreHead')? 'MarkupPreHead' :null);
			revised=updateMarkupBlock(revised,'POST-HEAD',
				titles.contains('MarkupPostHead')?'MarkupPostHead':null);
			revised=updateMarkupBlock(revised,'PRE-BODY',
				titles.contains('MarkupPreBody')? 'MarkupPreBody' :null);
			revised=updateMarkupBlock(revised,'POST-SCRIPT',
				titles.contains('MarkupPostBody')?'MarkupPostBody':null);
		}
		total.val=out.length;
		return revised;
	},
	formatItem: function(s,f,t,u) {
		if (f==this.type_TW)
			var r=s.getSaver().externalizeTiddler(s,t);
		if (f==this.type_PS)
			var r=config.macros.exportTiddlers.pureStoreTiddler.format([t.title,s.getSaver().externalizeTiddler(s,t)]);
		if (f==this.type_NF)
			var r=this.newsFeedTiddler.format([t.saveToRss(u)]);
		if (f==this.type_TX)
			var r=this.plainTextTiddler.format([t.title,t.modifier,t.modified.toLocaleString(),t.text]);
		return r||'';
	},
	getData: function(target,filetype,tids) {
		// output selected tiddlers and gather list of titles (for use with merge)
		var out=[]; var titles=[];
		var url=store.getTiddlerText('SiteUrl','');
		for (var i=0; i<tids.length; i++) {
			out.push(this.formatItem(store,filetype,tids[i],url));
			titles.push(tids[i].title);
		}
		// if TW or PureStore format, ask to merge with existing tiddlers (if any)
		if (filetype==this.type_TW || filetype==this.type_PS) {
			var text=loadFile(target);
			if (text && text.length) {
				var remoteStore=new TiddlyWiki();
				if (remoteStore.importTiddlyWiki(convertUTF8ToUnicode(text))
					&& confirm(this.mergeprompt.format([target]))) {
					var existing=remoteStore.getTiddlers('title');
					for (var i=0; i<existing.length; i++)
						if (!titles.contains(existing[i].title))
							out.push(this.formatItem(remoteStore,filetype,existing[i],url));
					displayMessage(this.mergestatus.format([tids.length,out.length-tids.length]));
				}
			}
		}
		return out;
	}
}
//}}}
GameTimeクラスはゲームの時間を表し、[[Gameクラス]]のUpdateメソッドやDrawメソッドの引数として使われています。

|!型|!名前|!機能|
|TimeSpan|ElapsedGameTimeプロパティ|前回からの経過ゲーム時間|
|TimeSpan|TotalGameTimeプロパティ|開始からの経過ゲーム時間|
|bool|IsRunningSlowlyプロパティ|Game.TargetElapsedTimeよりゲームループが長引いているときにtrueを得ます。ゲームループが遅くなっているので、何らかしら遅れを取り戻すべき状態です。|

※[[XNA Game Studio 4.0]]では、[[XNA Game Studio 3.1]]までのElapsedRealTimeプロパティ、TotalRealTimeプロパティは、混乱の原因となりそれほど便利ではないため、取り除かれました。

*参考: http://blogs.msdn.com/shawnhar/archive/2010/04/13/elapsedrealtime-and-totalrealtime-in-xna-game-studio-4-0.aspx
 [[XNA Game Studio 4.0]]のGameクラスについてです。

!XNAのゲームプロジェクト

!![[Windows]]と[[Xbox 360]]の場合
 実行可能ファイル形式(.exe)と、依存しているコンテンツと関連のファイルが出力されます。
 また、配布または[[XNAクリエーターズクラブ]]へのゲームの提出のために、プロジェクトのコンテキストメニューから「XNA クリエーターズ クラブ ゲームとしてパッケージ化」(Package as XNA Creators Club Game)を選択することで、XNAクリエーターズクラブゲームパッケージ(.ccgame形式)として、1つのファイルにまとめることもできます。([[XNA Game Studioパッケージユーティリティ]])

!![[Windows Phone 7]]の場合
 一方、[[Windows Phone 7]]では、DLL形式(.dll)と、依存しているコンテンツと関連のファイルが出力されます。これらは、配置用の[[xap形式]](.xap)のパッケージとして1つのファイルにまとめられます。[[xap形式]]は、zip形式を使っています。[[xap形式]]ファイルの内容は、zip形式のファイルとして確認が可能です。
 これは[[Silverlight]]と共通の仕組みです。

!ゲームのエントリポイント

 テンプレートからプロジェクトを作ると、「Program.cs」には、次のようなコードが得られます。

{{{
using System;

namespace SampleGame {
#if WINDOWS || XBOX
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main(string[] args)
        {
            using (Game1 game = new Game1())
            {
                game.Run();
            }
        }
    }
#endif
}
}}}

!![[Windows]]と[[Xbox 360]]の場合
 既定では「Program.cs」にあるエントリポイントであるMainメソッドからプログラムが開始します。

!![[Windows Phone 7]]の場合
 条件コンパイルによって、「Program.cs」は特に意味をなさないようになっています。その代わりとして、ビルド時に自動でpublicなGame派生クラスを見つけ、そのGame派生クラスが実行されるようにビルドされます。複数のpublicなGame派生クラスがあると、ビルドでエラーメッセージが出力されます。
※これは、「XNA Game Studio」の一般的用法から逸脱した話題です。
----

 ここでは「[[XNA Game Studio]]で基本になっている[[Gameクラス]]を使わないプログラムは可能かどうか」について、見てみましょう。

 [[Windows]]では、Windows FormsやWPFなどのウィンドウアプリケーションに対して、[[Gameクラス]]を使わないで、[[XNA Game Studio]]のGraphicsDeviceクラスだけを利用したアプリケーションも可能です。
 それでは、[[Xbox 360]]でも可能でしょうか。次のプログラムは、[[Xbox 360]]上で、[[Gameクラス]]を使わないで、グラフィックスが扱えることを示すプログラムです。
 新しいゲームプロジェクト「Xbox 360 ゲーム (3.1)」から「Game1.cs」と「Progam.cs」を取り除いて、後述のサンプルコードを使います。

!!注意
*Gameクラス不使用プログラムが、[[Xbox LIVEインディーズゲーム]]などで現行および将来に渡り許容されるか否かや、全ての機能が正常に動作するか否かを示すものではありません。
*[[Windows]]で動作させるには、別途ウィンドウを作成して、GraphicsDeviceコンストラクタにウィンドウハンドルを渡す必要があります。また、一般的なウィンドウアプリケーションとして、ウィンドウへ描画するには、プログラムの構造を変更する必要があります。

!!サンプルコード
{{{
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace OutOfGame {
	class OutOfGame : IDisposable {
		readonly GraphicsDevice GraphicsDevice;
		bool exit;
		float blue;

		public static void Main() {
			using (var outOfGame = new OutOfGame()) {
				outOfGame.Run();
			}
		}

		public OutOfGame() {
			GraphicsDevice = new GraphicsDevice(
				GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, IntPtr.Zero,
				new PresentationParameters
				{
					BackBufferWidth = 1280,
					BackBufferHeight = 720,
				});
		}
		public void Run() {
			while (!exit) {
				Update();
				Draw();
			}
		}
		public void Dispose() {
			if (GraphicsDevice != null)
				GraphicsDevice.Dispose();
		}
		public void Update() {
			if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
				this.Exit();
		}
		public void Draw() {
			blue = DateTime.Now.Millisecond * 0.002f;
			if (blue >= 1) blue = 2 - blue;
			GraphicsDevice.Clear(new Color(0.0f, 0.0f, 0.75f + blue * 0.25f, 1.0f));
			GraphicsDevice.Present();
		}
		public void Exit() {
			exit = true;
		}
	}
}
}}}
/***
|Name|ImageSizePlugin|
|Source|http://www.TiddlyTools.com/#ImageSizePlugin|
|Version|1.1.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin,formatter|
|Requires||
|Overrides|'image' formatter|
|Description|extends image syntax to add optional CSS width/height values|
!!!!!Usage
<<<
Extends standard TiddlyWiki image syntax, ''{{{[img[...]]}}}'', so you can specify CSS width/height values.

The extended syntax is:
>''{{{[img(x,y)[...]]}}}''
>where x and y are the desired width and height of the image, specified using CSS units of measurement (e.g., px, em, cm, in, or %).  Use ''auto'' for either the width or height to scale image proportionally (i.e., maintain aspect ratio).  You may also calculate a CSS value on-the-fly by using //evaluated javascript//, enclosed between """{{""" and """}}""", e.g, {{{({{widthFunction()}},{{heightFunction()}})}}}.

Note: this plugin also includes enhancements to support:
*[[AttachFilePluginFormatters]] (embed image files as text-encoded tiddlers)
* [[ImagePathPlugin]] (fallback locations for missing images)
Please refer to those plugins for details...
<<<
!!!!!Examples
<<<
{{{
[<img(34%,auto)[images/meow.gif]]
[<img(21%,auto)[images/meow.gif]]
[<img(13%,auto)[images/meow.gif]]
[<img(8%,auto)[images/meow.gif]]
[<img(5%,auto)[images/meow.gif]]
[<img(3%,auto)[images/meow.gif]]
[<img(2%,auto)[images/meow.gif]]
[img(1%,auto)[images/meow.gif]]
}}}
[<img(34%,auto)[images/meow.gif]]
[<img(21%,auto)[images/meow.gif]]
[<img(13%,auto)[images/meow.gif]]
[<img(8%,auto)[images/meow.gif]]
[<img(5%,auto)[images/meow.gif]]
[<img(3%,auto)[images/meow.gif]]
[<img(2%,auto)[images/meow.gif]]
[img(1%,auto)[images/meow.gif]]
{{clear block{}}}
<<<
!!!!!Revisions
<<<
2008.01.19 [1.1.0] added support for evaluated width/height values!!
2008.01.18 [1.0.1] code cleanup plus improved regexp for matching "(width,height)" by eliminating hard-coded recognition of [px,em,cm,in,%] CSS units.  Syntax now accepts ANY values for width/height, and leaves it to the browser's CSS processing to handle any invalid values.
2008.01.17 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImageSizePlugin= {major: 1, minor: 1, revision: 0, date: new Date(2008,1,19)};

// replace standard handler for image formatter
// note: includes modifications for [[AttachFilePluginFormatters]] AND [[ImagePathPlugin]]
var f=config.formatters.findByField("name","image");
config.formatters[f].match="\\[[<>]?[Ii][Mm][Gg](?:\\([^,]*,[^\\)]*\\))?\\[";
config.formatters[f].lookaheadRegExp=/\[([<]?)(>?)[Ii][Mm][Gg](\([^,]*,[^\)]*\))?\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg;
config.formatters[f].handler=function(w) {
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var floatLeft=lookaheadMatch[1];
		var floatRight=lookaheadMatch[2];
		var XY=lookaheadMatch[3];
		var tooltip=lookaheadMatch[4];
		var src=lookaheadMatch[5];
		var link=lookaheadMatch[6];
		// Simple bracketted link
		var e = w.output;
		if(link) { // LINKED IMAGE
			if (config.formatterHelpers.isExternalLink(link)) {
				if (config.macros.attach && config.macros.attach.isAttachment(link)) {
					// see [[AttachFilePluginFormatters]]
					e = createExternalLink(w.output,link);
					e.href=config.macros.attach.getAttachment(link);
					e.title = config.macros.attach.linkTooltip + link;
				} else
					e = createExternalLink(w.output,link);
			} else 
				e = createTiddlyLink(w.output,link,false,null,w.isStatic);
			addClass(e,"imageLink");
		}
		var img = createTiddlyElement(e,"img");
		if(floatLeft) img.align="left"; else if(floatRight) img.align="right"; // FLOAT LEFT/RIGHT
		if(XY) { // CUSTOM SIZE with optional EVAL'ED width/height ({{...}},{{...}})
			var parts=XY.replace(/[\(\)]/g,'').split(","); var x=parts[0]; var y=parts[1];
			if (x.substr(0,2)=="{{") {
				try{img.style.width=eval(x.substr(2,x.length-4));}
				catch(e){displayMessage(e.description||e.toString())}
			} else img.style.width=x;

			if (y.substr(0,2)=="{{") {
				try{img.style.height=eval(y.substr(2,y.length-4));}
				catch(e){displayMessage(e.description||e.toString())}
			} else img.style.height=y;
		}
		if(tooltip) img.title = tooltip; // TOOLTIP
		// GET IMAGE SOURCE (get attachment or resolve fallback path as needed)
		if (config.macros.attach && config.macros.attach.isAttachment(src))
			src=config.macros.attach.getAttachment(src); // see [[AttachFilePluginFormatters]]
		else if (config.formatterHelpers.resolvePath) { // see [[ImagePathPlugin]]
			// Note: IE and Safari use onError to call resolvePath() only if initial lookup fails
			// (avoids security messages for initial filesystem access)... otherwise, attempt to
			// resolve the original path/file before initial rendering
			if (config.browser.isIE || config.browser.isSafari) {
				img.onerror=(function(){
					this.src=config.formatterHelpers.resolvePath(this.src,false);
					return false;
				});
			} else
				src=config.formatterHelpers.resolvePath(lookaheadMatch[5],true);
		}
		img.src=src; // RENDER IMAGE
		w.nextMatch = this.lookaheadRegExp.lastIndex;
	}
}
//}}}
/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.4.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|config.macros.importTiddlers.handler|
|Description|interactive controls for import/export with filtering.|
This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents.  An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles.  Automatically add tags to imported tiddlers so they are easy to find later on.  Generates a detailed report of import 'history' in ImportedTiddlers.
!!!!!Documentation
<<<
see [[ImportTiddlersPluginInfo]] for details
<<<
!!!!!interactive control panel:
<<<
<<importTiddlers inline>>
{{clear{
^^(see also: [[ImportTiddlers]] shadow tiddler)^^}}}
<<<
!!!!!Installation Notes
<<<
* As of 6/27/2007, 'patch' functions that provide backward-compatibility with TW2.1.x and earlier have been split into a separate [[ImportTiddlersPluginPatch]] tiddler to reduce installation overhead for //this// plugin.  You only need to install the additional plugin tiddler when using ImportTiddlersPlugin in documents using TW2.1.x or earlier.
* As of 3/21/2007, the interactive {{{<<importTiddlers>>}}} and non-interactive {{{<<loadTiddlers>>}}} macro definitions and related code have been split into separate [[ImportTiddlersPlugin]] and [[LoadTiddlersPlugin]] to permit selective installation of either the interactive and/or non-interactive macro functions.
* Quick Installation Tip: If you are using an unmodified version of TiddlyWiki (core release version <<version>>), you can get a new, empty TiddlyWiki with the Import Tiddlers plugin pre-installed (''[[download from here|TW+ImportExport.html]]''), and then simply import all your content from your old document into this new, empty document.
<<<
!!!!!Revisions
<<<
2008.09.30 [4.4.0] added fallback definition of merge() for use with TW2.0.x and TW1.2.x
2008.08.12 [4.3.3] rewrite backstage and shadow tiddler definitions for easier customization
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImportTiddlersPlugin= {major: 4, minor: 4, revision: 0, date: new Date(2008,8,30)};

// IE needs explicit global scoping for functions/vars called from browser events
window.onClickImportButton=onClickImportButton;
window.refreshImportList=refreshImportList;

// default cookie/option values
if (!config.options.chkImportReport) config.options.chkImportReport=true;

// default shadow definition
config.shadowTiddlers.ImportTiddlers='<<importTiddlers inline>>';

// use shadow tiddler content in backstage panel
if (config.tasks) config.tasks.importTask.content='<<tiddler ImportTiddlers>>' // TW2.2 or above

// $(...) function: 'shorthand' convenience syntax for document.getElementById()
if (typeof($)=='undefined') { // avoid redefinition
window.$ = function() {
	var elements=new Array();
	for (var i=0; i<arguments.length; i++) {
		var element=arguments[i];
		if (typeof element=='string') element=document.getElementById(element);
		if (arguments.length==1) return element;
		elements.push(element);
	}
	return elements;
}
}
//}}}
//{{{
// backward-compatiblity for TW2.0.x and TW1.2.x
if (config.macros.importTiddlers==undefined)
	config.macros.importTiddlers={};
if (typeof merge=='undefined') {
	function merge(dst,src,preserveExisting) {
		for(var i in src)
			{ if(!preserveExisting || dst[i] === undefined) dst[i] = src[i]; }
		return dst;
	}
}
if (config.browser.isGecko===undefined)
	config.browser.isGecko=(config.userAgent.indexOf('gecko')!=-1);
//}}}
//{{{
merge(config.macros.importTiddlers,{
	label: 'import tiddlers',
	prompt: 'Copy tiddlers from another document',
	openMsg: 'Opening %0',
	openErrMsg: 'Could not open %0 - error=%1',
	readMsg: 'Read %0 bytes from %1',
	foundMsg: 'Found %0 tiddlers in %1',
	filterMsg: "Filtered %0 tiddlers matching '%1'",
	summaryMsg: '%0 tiddler%1 in the list',
	summaryFilteredMsg: '%0 of %1 tiddler%2 in the list',
	plural: 's are',
	single: ' is',
	countMsg: '%0 tiddlers selected for import',
	processedMsg: 'Processed %0 tiddlers',
	importedMsg: 'Imported %0 of %1 tiddlers from %2',
	loadText: 'please load a document...',
	closeText: 'close',
	doneText: 'done',
	startText: 'import',
	stopText: 'stop',
	local: true,		// default to import from local file
	src: '',		// path/filename or URL of document to import (retrieved from SiteUrl)
	proxy: '',		// URL for remote proxy script (retrieved from SiteProxy)
	useProxy: false,	// use specific proxy script in front of remote URL
	inbound: null,		// hash-indexed array of tiddlers from other document
	newTags: '',		// text of tags added to imported tiddlers
	addTags: true,		// add new tags to imported tiddlers
	listsize: 10,		// # of lines to show in imported tiddler list
	importTags: true,	// include tags from remote source document when importing a tiddler
	keepTags: true,		// retain existing tags when replacing a tiddler
	sync: false,		// add 'server' fields to imported tiddlers (for sync function)
	lastFilter: '',		// most recent filter (URL hash) applied
	lastAction: null,	// most recent collision button performed
	index: 0,		// current processing index in import list
	sort: ''		// sort order for imported tiddler listbox
});
//}}}
//{{{
// replace core macro handler
if (config.macros.importTiddlers.coreHandler==undefined)
	config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler; // save built-in handler
config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	if (!params[0] || params[0].toLowerCase()=='core') { // default to built in
		if (config.macros.importTiddlers.coreHandler)
			config.macros.importTiddlers.coreHandler.apply(this,arguments);
		else 
			createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);
	} else if (params[0]=='link') { // show link to floating panel
		createTiddlyButton(place,params[1]||this.label,params[2]||this.prompt,onClickImportMenu);
	} else if (params[0]=='inline') {// show panel as INLINE tiddler content
		createImportPanel(place);
		$('importPanel').style.position='static';
		$('importPanel').style.display='block';
	} else if (config.macros.loadTiddlers)
		config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers
}
//}}}
//{{{
// Handle link click to create/show/hide control panel
function onClickImportMenu(e)
{
	if (!e) var e = window.event;
	var parent=resolveTarget(e).parentNode;
	var panel = $('importPanel');
	if (panel==undefined || panel.parentNode!=parent)
		panel=createImportPanel(parent);
	var isOpen = panel.style.display=='block';
	if(config.options.chkAnimate)
		anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,'none'));
	else
		panel.style.display = isOpen ? 'none' : 'block' ;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}
//{{{
// Create control panel: HTML, CSS
function createImportPanel(place) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var panel=$('importPanel');
	if (panel) { panel.parentNode.removeChild(panel); }
	setStylesheet(cmi.css,'importTiddlers');
	panel=createTiddlyElement(place,'span','importPanel',null,null)
	panel.innerHTML=cmi.html;
	refreshImportList();
	var siteURL=store.getTiddlerText('SiteUrl'); if (!siteURL) siteURL='';
	$('importSourceURL').value=siteURL;
	cmi.src=siteURL;
	var siteProxy=store.getTiddlerText('SiteProxy'); if (!siteProxy) siteProxy='SiteProxy';
	$('importSiteProxy').value=siteProxy;
	cmi.proxy=siteProxy;
	if (config.browser.isGecko) { // FF3 FIXUP
		$('fileImportSource').style.display='none';
		$('importLocalPanelFix').style.display='block';
	}
	return panel;
}
//}}}
//{{{
config.macros.importTiddlers.css = '\
#importPanel {\
	display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\
	background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
	padding: 0.5em; margin:0em; -moz-border-radius:1em;-webkit-border-radius:1em;\
}\
#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\
#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel select { width:100%;margin:0px;font-size:8pt;line-height:110%;}\
#importPanel input  { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\
#importPanel .box { border:1px solid #000; background-color:#eee; padding:3px 5px; margin-bottom:5px; -moz-border-radius:5px;-webkit-border-radius:5px;}\
#importPanel .topline { border-top:1px solid #999; padding-top:2px; margin-top:2px; }\
#importPanel .rad { width:auto; }\
#importPanel .chk { width:auto; margin:1px;border:0; }\
#importPanel .btn { width:auto; }\
#importPanel .btn1 { width:98%; }\
#importPanel .btn2 { width:48%; }\
#importPanel .btn3 { width:32%; }\
#importPanel .btn4 { width:23%; }\
#importPanel .btn5 { width:19%; }\
#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }\
#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\
#backstagePanel #importPanel { left:10%; right:auto; }\
';
//}}}
//{{{
config.macros.importTiddlers.html = '\
<!-- source and report -->\
<table><tr><td align=left>\
	import from\
	<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED\
		onclick="onClickImportButton(this,event)" title="show file controls"> local file\
	<input type="radio" class="rad" name="importFrom" id="importFromWeb"  value="http"\
		onclick="onClickImportButton(this,event)" title="show web controls"> web server\
</td><td align=right>\
	<input type=checkbox class="chk" id="chkImportReport" checked\
		onClick="config.options[\'chkImportReport\']=this.checked;"> create report\
</td></tr></table>\
\
<div class="box" id="importSourcePanel" style="margin:.5em">\
<div id="importLocalPanel" style="display:block;margin-bottom:2px;"><!-- import from local file  -->\
enter or browse for source path/filename<br>\
<input type="file" id="fileImportSource" size=57 style="width:100%"\
	onKeyUp="config.macros.importTiddlers.src=this.value"\
	onChange="config.macros.importTiddlers.src=this.value;$(\'importLoad\').onclick()">\
<div id="importLocalPanelFix" style="display:none"><!-- FF3 FIXUP -->\
	<input type="text" id="fileImportSourceFix" style="width:90%"\
		title="Enter a path/file to import"\
		onKeyUp="config.macros.importTiddlers.src=this.value"\
		onChange="config.macros.importTiddlers.src=this.value; $(\'importLoad\').onclick()">\
	<input type="button" id="fileImportSourceFixButton" style="width:7%" value="..."\
		title="Select a path/file to import"\
		onClick="var r=config.macros.importTiddlers.askForFilename(this); if (!r||!r.length) return;\
			$(\'fileImportSourceFix\').value=r;\
			config.macros.importTiddlers.src=r;\
			$(\'importLoad\').onclick()">\
</div><!--end FF3 FIXUP-->\
</div><!--end local-->\
<div id="importHTTPPanel" style="display:none;margin-bottom:2px;"><!-- import from http server -->\
<table><tr><td align=left>\
	enter a URL or <a href="javascript:;" id="importSelectFeed"\
		onclick="onClickImportButton(this,event)" title="select a pre-defined \'systemServer\' URL">\
		select a server</a><br>\
</td><td align=right>\
	<input type="checkbox" class="chk" id="importUsePassword"\
		onClick="config.macros.importTiddlers.usePassword=this.checked;\
			config.macros.importTiddlers.showPanel(\'importIDPWPanel\',this.checked,true);">password\
	<input type="checkbox" class="chk" id="importUseProxy"\
		onClick="config.macros.importTiddlers.useProxy=this.checked;\
			config.macros.importTiddlers.showPanel(\'importSiteProxy\',this.checked,true);">proxy\
</td></tr></table>\
<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\
	onKeyUp="config.macros.importTiddlers.proxy=this.value"\
	onChange="config.macros.importTiddlers.proxy=this.value;">\
<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\
	onKeyUp="config.macros.importTiddlers.src=this.value"\
	onChange="config.macros.importTiddlers.src=this.value;">\
<div id="importIDPWPanel" style="text-align:center;margin-top:2px;display:none";>\
username: <input type=text id="txtImportID" style="width:25%" \
	onChange="config.options.txtRemoteUsername=this.value;">\
 password: <input type=password id="txtImportPW" style="width:25%" \
	onChange="config.options.txtRemotePassword=this.value;">\
</div><!--end idpw-->\
</div><!--end http-->\
</div><!--end source-->\
\
<div class="box" id="importSelectPanel" style="display:none;margin:.5em;">\
<table><tr><td align=left>\
select:\
<a href="javascript:;" id="importSelectAll"\
	onclick="onClickImportButton(this);return false;" title="SELECT all tiddlers">\
	all</a>\
&nbsp;<a href="javascript:;" id="importSelectNew"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers not already in destination document">\
	added</a>\
&nbsp;<a href="javascript:;" id="importSelectChanges"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been updated in source document">\
	changes</a>\
&nbsp;<a href="javascript:;" id="importSelectDifferences"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been added or are different from existing tiddlers">\
	differences</a>\
</td><td align=right>\
<a href="javascript:;" id="importListSmaller"\
	onclick="onClickImportButton(this);return false;" title="SHRINK list size">\
	&nbsp;&#150;&nbsp;</a>\
<a href="javascript:;" id="importListLarger"\
	onclick="onClickImportButton(this);return false;" title="GROW list size">\
	&nbsp;+&nbsp;</a>\
<a href="javascript:;" id="importListMaximize"\
	onclick="onClickImportButton(this);return false;" title="MAXIMIZE/RESTORE list size">\
	&nbsp;=&nbsp;</a>\
</td></tr></table>\
<select id="importList" size=8 multiple\
	onchange="setTimeout(\'refreshImportList(\'+this.selectedIndex+\')\',1)">\
	<!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\
</select>\
<div style="text-align:center">\
	<a href="javascript:;"\
		title="click for help using filters..."\
		onclick="alert(\'A filter consists of one or more space-separated combinations of:\\n\\ntiddler titles\\ntag:[[tagvalue]]\\ntag:[[tag expression]] (requires MatchTagsPlugin)\\nstory:[[TiddlerName]]\\nsearch:[[searchtext]]\\n\\nUse a blank filter for all tiddlers.\')"\
	>filter</a>\
	<input type="text" id="importLastFilter" style="margin-bottom:1px; width:65%"\
		title="Enter a combination of one or more filters. Use a blank filter for all tiddlers."\
		onfocus="this.select()" value=""\
		onKeyUp="config.macros.importTiddlers.lastFilter=this.value"\
		onChange="config.macros.importTiddlers.lastFilter=this.value;">\
	<input type="button" id="importApplyFilter" style="width:20%" value="apply"\
		title="filter list of tiddlers to include only those that match certain criteria"\
		onclick="onClickImportButton(this)">\
	</div>\
</div><!--end select-->\
\
<div class="box" id="importOptionsPanel" style="text-align:center;margin:.5em;display:none;">\
	apply tags: <input type=checkbox class="chk" id="chkImportTags" checked\
		onClick="config.macros.importTiddlers.importTags=this.checked;">from source&nbsp;\
	<input type=checkbox class="chk" id="chkKeepTags" checked\
		onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing&nbsp;\
	<input type=checkbox class="chk" id="chkAddTags" \
		onClick="config.macros.importTiddlers.addTags=this.checked;\
			config.macros.importTiddlers.showPanel(\'txtNewTags\',this.checked,true);\
			if (this.checked) $(\'txtNewTags\').focus();">add tags<br>\
	<input type=text id="txtNewTags" style="margin-top:4px;display:none;" size=15\ onfocus="this.select()" \
		title="enter tags to be added to imported tiddlers" \
		onKeyUp="config.macros.importTiddlers.newTags=this.value;\
		$(\'chkAddTags\').checked=this.value.length>0;" autocomplete=off>\
	<nobr><input type=checkbox class="chk" id="chkSync" \
		onClick="config.macros.importTiddlers.sync=this.checked;">\
		link imported tiddlers to source document (for sync later)</nobr>\
</div><!--end options-->\
\
<div id="importButtonPanel" style="text-align:center">\
	<input type=button id="importLoad"	class="importButton btn3" value="open"\
		title="load listbox with tiddlers from source document"\
		onclick="onClickImportButton(this)">\
	<input type=button id="importOptions"	class="importButton btn3" value="options..."\
		title="set options for tags, sync, etc."\
		onclick="onClickImportButton(this)">\
	<input type=button id="importStart"	class="importButton btn3" value="import"\
		title="start/stop import of selected source tiddlers into current document"\
		onclick="onClickImportButton(this)">\
	<input type=button id="importClose"	class="importButton btn3" value="done"\
		title="clear listbox or hide control panel"\
		onclick="onClickImportButton(this)">\
</div>\
\
<div class="none" id="importCollisionPanel" style="display:none;margin:.5em 0 .5em .5em;">\
	<table><tr><td style="width:65%" align="left">\
		<table><tr><td align=left>\
			tiddler already exists:\
		</td><td align=right>\
			<input type=checkbox class="chk" id="importApplyToAll" \
			onclick="$(\'importRename\').disabled=this.checked;"\
			checked>apply to all\
		</td></tr></table>\
		<input type=text id="importNewTitle" size=15 autocomplete=off">\
	</td><td style="width:34%" align="center">\
		<input type=button id="importMerge"\
			class="importButton" style="width:47%" value="merge"\
			title="append the incoming tiddler to the existing tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><input type=button id="importSkip"\
			class="importButton" style="width:47%" value="skip"\
			title="do not import this tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><br><input type=button id="importRename"\
			class="importButton" style="width:47%" value="rename"\
			title="rename the incoming tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><input type=button id="importReplace"\
			class="importButton" style="width:47%" value="replace"\
			title="discard the existing tiddler"\
			onclick="onClickImportButton(this)">\
	</td></tr></table>\
</div><!--end collision-->\
';
//}}}
//{{{
// process control interactions
function onClickImportButton(which,event)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	var list = $('importList');
	if (!list) return;
	var thePanel = $('importPanel');
	var theCollisionPanel = $('importCollisionPanel');
	var theNewTitle = $('importNewTitle');
	var count=0;
	switch (which.id)
		{
		case 'importFromFile':	// show local panel
		case 'importFromWeb':	// show HTTP panel
			cmi.local=(which.id=='importFromFile');
			cmi.showPanel('importLocalPanel',cmi.local);
			cmi.showPanel('importHTTPPanel',!cmi.local);
			break;
		case 'importOptions':	// show/hide options panel
			cmi.showPanel('importOptionsPanel',$('importOptionsPanel').style.display=='none');
			break;
		case 'fileImportSource':
		case 'importLoad':		// load import source into hidden frame
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			if (cmi.src=='') break;
			// Load document, read it's DOM and fill the list
			cmi.loadRemoteFile(cmi.src,cmi.filterTiddlerList);
			break;
		case 'importSelectFeed':	// select a pre-defined systemServer feed URL
			var p=Popup.create(which); if (!p) return;
			var tids=store.getTaggedTiddlers('systemServer');
			if (!tids.length)
				createTiddlyText(createTiddlyElement(p,'li'),'no pre-defined server feeds');
			for (var t=0; t<tids.length; t++) {
				var u=store.getTiddlerSlice(tids[t].title,'URL');
				var d=store.getTiddlerSlice(tids[t].title,'Description');
				if (!d||!d.length) d=store.getTiddlerSlice(tids[t].title,'description');
				if (!d||!d.length) d=u;
				createTiddlyButton(createTiddlyElement(p,'li'),tids[t].title,d,
					function(){
						var u=this.getAttribute('url');
						$('importSourceURL').value=u;
						config.macros.importTiddlers.src=u;
						$('importLoad').onclick();
					},
					null,null,null,{url:u});
			}
			Popup.show(p,false);
			event.cancelBubble = true;
			if (event.stopPropagation) event.stopPropagation();
			return(false);
			// create popup with feed list
			// onselect, insert feed URL into input field.
			break;
		case 'importSelectAll':		// select all tiddler list items (i.e., not headings)
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				if (list.options[t].value=='') continue;
				list.options[t].selected=true;
				count++;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			$('importStart').disabled=!count;
			break;
		case 'importSelectNew':		// select tiddlers not in current document
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=='') continue;
				list.options[t].selected=!store.tiddlerExists(list.options[t].value);
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			$('importStart').disabled=!count;
			break;
		case 'importSelectChanges':		// select tiddlers that are updated from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value==''||!store.tiddlerExists(list.options[t].value)) continue;
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified>0); // updated tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			$('importStart').disabled=!count;
			break;
		case 'importSelectDifferences':		// select tiddlers that are new or different from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=='') continue;
				if (!store.tiddlerExists(list.options[t].value)) { list.options[t].selected=true; count++; continue; }
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified!=0); // changed tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			$('importStart').disabled=!count;
			break;
		case 'importApplyFilter':	// filter list to include only matching tiddlers
			importReport();		// if an import was in progress, generate a report
			clearMessage();
			if (!cmi.all) // no tiddlers loaded = '0 selected'
				{ displayMessage(cmi.countMsg.format([0])); return false; }
			var hash=$('importLastFilter').value;
			cmi.inbound=cmi.filterByHash('#'+hash,cmi.all);
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importStart':		// initiate the import processing
			importReport();		// if an import was in progress, generate a report
			$('importApplyToAll').checked=false;
			$('importStart').value=cmi.stopText;
			if (cmi.index>0) cmi.index=-1; // stop processing
			else cmi.index=importTiddlers(0); // or begin processing
			importStopped();
			break;
		case 'importClose':		// unload imported tiddlers or hide the import control panel
			// if imported tiddlers not loaded, close the import control panel
			if (!cmi.inbound) { thePanel.style.display='none'; break; }
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importSkip':	// don't import the tiddler
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported = cmi.inbound[j];
			theImported.status='skipped after asking';			// mark item as skipped
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index+1);	// resume with NEXT item
			importStopped();
			break;
		case 'importRename':		// change name of imported tiddler
			cmi.lastAction=which;
			var theItem		= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported		= cmi.inbound[j];
			theImported.status	= 'renamed from '+theImported.title;	// mark item as renamed
			theImported.set(theNewTitle.value,null,null,null,null);		// change the tiddler title
			theItem.value		= theNewTitle.value;			// change the listbox item text
			theItem.text		= theNewTitle.value;			// change the listbox item text
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importMerge':	// join existing and imported tiddler content
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported	= cmi.inbound[j];
			var theExisting	= store.getTiddler(theItem.value);
			var theText	= theExisting.text+'\n----\n^^merged from: ';
			theText		+='[['+cmi.src+'#'+theItem.value+'|'+cmi.src+'#'+theItem.value+']]^^\n';
			theText		+='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\n'+theImported.text;
			var theDate	= new Date();
			var theTags	= theExisting.getTags()+' '+theImported.getTags();
			theImported.set(null,theText,null,theDate,theTags);
			theImported.status   = 'merged with '+theExisting.title;	// mark item as merged
			theImported.status  += ' - '+theExisting.modified.formatString('MM/DD/YYYY 0hh:0mm:0ss');
			theImported.status  += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with this item
			importStopped();
			break;
		case 'importReplace':		// substitute imported tiddler for existing tiddler
			cmi.lastAction=which;
			var theItem		  = list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported     = cmi.inbound[j];
			var theExisting	  = store.getTiddler(theItem.value);
			theImported.status  = 'replaces '+theExisting.title;		// mark item for replace
			theImported.status += ' - '+theExisting.modified.formatString('MM/DD/YYYY 0hh:0mm:0ss');
			theImported.status += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importListSmaller':		// decrease current listbox size, minimum=5
			if (list.options.length==1) break;
			list.size-=(list.size>5)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListLarger':		// increase current listbox size, maximum=number of items in list
			if (list.options.length==1) break;
			list.size+=(list.size<list.options.length)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListMaximize':	// toggle listbox size between current and maximum
			if (list.options.length==1) break;
			list.size=(list.size==list.options.length)?cmi.listsize:list.options.length;
			break;
		}
}
//}}}
//{{{
config.macros.importTiddlers.showPanel=function(place,show,skipAnim) {
	if (typeof place == 'string') var place=$(place);
	if (!place||!place.style) return;
	if(!skipAnim && anim && config.options.chkAnimate) anim.startAnimating(new Slider(place,show,false,'none'));
	else place.style.display=show?'block':'none';
}
//}}}
//{{{
function refreshImportList(selectedIndex)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	var list  = $('importList');
	if (!list) return;
	// if nothing to show, reset list content and size
	if (!cmi.inbound) 
	{
		while (list.length > 0) { list.options[0] = null; }
		list.options[0]=new Option(cmi.loadText,'',false,false);
		list.size=cmi.listsize;

		// toggle buttons and panels
		$('importLoad').disabled=false;
		$('importLoad').style.display='inline';
		$('importStart').disabled=true;
		$('importOptions').disabled=true;
		$('importOptions').style.display='none';
		$('fileImportSource').disabled=false;
		$('importFromFile').disabled=false;
		$('importFromWeb').disabled=false;
		$('importStart').value=cmi.startText;
		$('importClose').value=cmi.doneText;
		$('importSelectPanel').style.display='none';
		$('importOptionsPanel').style.display='none';
		return;
	}
	// there are inbound tiddlers loaded...
	// toggle buttons and panels
	$('importLoad').disabled=true;
	$('importLoad').style.display='none';
	$('importOptions').style.display='inline';
	$('importOptions').disabled=false;
	$('fileImportSource').disabled=true;
	$('importFromFile').disabled=true;
	$('importFromWeb').disabled=true;
	$('importClose').value=cmi.closeText;
	if ($('importSelectPanel').style.display=='none')
		cmi.showPanel('importSelectPanel',true);

	// get the sort order
	if (!selectedIndex)   selectedIndex=0;
	if (selectedIndex==0) cmi.sort='title';		// heading
	if (selectedIndex==1) cmi.sort='title';
	if (selectedIndex==2) cmi.sort='modified';
	if (selectedIndex==3) cmi.sort='tags';
	if (selectedIndex>3) {
		// display selected tiddler count
		for (var t=0,count=0; t < list.options.length; t++) {
			if (!list.options[t].selected) continue;
			if (list.options[t].value!='')
				count+=1;
			else { // if heading is selected, deselect it, and then select and count all in section
				list.options[t].selected=false;
				for ( t++; t<list.options.length && list.options[t].value!=''; t++) {
					list.options[t].selected=true;
					count++;
				}
			}
		}
		clearMessage(); displayMessage(cmi.countMsg.format([count]));
	}
	$('importStart').disabled=!count;
	if (selectedIndex>3) return; // no refresh needed

	// get the alphasorted list of tiddlers
	var tiddlers=cmi.inbound;
	tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
	// clear current list contents
	while (list.length > 0) { list.options[0] = null; }
	// add heading and control items to list
	var i=0;
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	if (cmi.all.length==tiddlers.length)
		var summary=cmi.summaryMsg.format([tiddlers.length,(tiddlers.length!=1)?cmi.plural:cmi.single]);
	else
		var summary=cmi.summaryFilteredMsg.format([tiddlers.length,cmi.all.length,(cmi.all.length!=1)?cmi.plural:cmi.single]);
	list.options[i++]=new Option(summary,'',false,false);
	list.options[i++]=new Option(((cmi.sort=='title'   )?'>':indent)+' [by title]','',false,false);
	list.options[i++]=new Option(((cmi.sort=='modified')?'>':indent)+' [by date]','',false,false);
	list.options[i++]=new Option(((cmi.sort=='tags')?'>':indent)+' [by tags]','',false,false);
	// output the tiddler list
	switch(cmi.sort) {
		case 'title':
			for(var t = 0; t < tiddlers.length; t++)
				list.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			break;
		case 'modified':
			// sort descending for newest date first
			tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });
			var lastSection = '';
			for(var t = 0; t < tiddlers.length; t++) {
				var tiddler = tiddlers[t];
				var theSection = tiddler.modified.toLocaleDateString();
				if (theSection != lastSection) {
					list.options[i++] = new Option(theSection,'',false,false);
					lastSection = theSection;
				}
				list.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
			}
			break;
		case 'tags':
			var theTitles = {}; // all tiddler titles, hash indexed by tag value
			var theTags = new Array();
			for(var t=0; t<tiddlers.length; t++) {
				var title=tiddlers[t].title;
				var tags=tiddlers[t].tags;
				if (!tags || !tags.length) {
					if (theTitles['untagged']==undefined) { theTags.push('untagged'); theTitles['untagged']=new Array(); }
					theTitles['untagged'].push(title);
				}
				else for(var s=0; s<tags.length; s++) {
					if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
					theTitles[tags[s]].push(title);
				}
			}
			theTags.sort();
			for(var tagindex=0; tagindex<theTags.length; tagindex++) {
				var theTag=theTags[tagindex];
				list.options[i++]=new Option(theTag,'',false,false);
				for(var t=0; t<theTitles[theTag].length; t++)
					list.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
			}
			break;
		}
	list.selectedIndex=selectedIndex;		  // select current control item
	if (list.size<cmi.listsize) list.size=cmi.listsize;
	if (list.size>list.options.length) list.size=list.options.length;
}
//}}}
//{{{
// re-entrant processing for handling import with interactive collision prompting
function importTiddlers(startIndex)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	if (!cmi.inbound) return -1;

	var list = $('importList');
	if (!list) return;
	var t;
	// if starting new import, reset import status flags
	if (startIndex==0)
		for (var t=0;t<cmi.inbound.length;t++)
			cmi.inbound[t].status='';
	for (var i=startIndex; i<list.options.length; i++)
		{
		// if list item is not selected or is a heading (i.e., has no value), skip it
		if ((!list.options[i].selected) || ((t=list.options[i].value)==''))
			continue;
		for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==t) break;
		var inbound = cmi.inbound[j];
		var theExisting = store.getTiddler(inbound.title);
		// avoid redundant import for tiddlers that are listed multiple times (when 'by tags')
		if (inbound.status=='added')
			continue;
		// don't import the 'ImportedTiddlers' history from the other document...
		if (inbound.title=='ImportedTiddlers')
			continue;
		// if tiddler exists and import not marked for replace or merge, stop importing
		if (theExisting && (inbound.status.substr(0,7)!='replace') && (inbound.status.substr(0,5)!='merge'))
			return i;
		// assemble tags (remote + existing + added)
		var newTags = '';
		if (cmi.importTags)
			newTags+=inbound.getTags()	// import remote tags
		if (cmi.keepTags && theExisting)
			newTags+=' '+theExisting.getTags(); // keep existing tags
		if (cmi.addTags && cmi.newTags.trim().length)
			newTags+=' '+cmi.newTags; // add new tags
		inbound.set(null,null,null,null,newTags.trim());
		// set the status to 'added' (if not already set by the 'ask the user' UI)
		inbound.status=(inbound.status=='')?'added':inbound.status;
		// set sync fields
		if (cmi.sync) {
			if (!inbound.fields) inbound.fields={}; // for TW2.1.x backward-compatibility
			inbound.fields['server.page.revision']=inbound.modified.convertToYYYYMMDDHHMM();
			inbound.fields['server.type']='file';
			inbound.fields['server.host']=(cmi.local?'file://':'')+cmi.src;
		}
		// do the import!
		store.suspendNotifications();
		store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags, inbound.fields, true, inbound.created);
                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value (needed for TW2.1.x and earlier)
		store.resumeNotifications();
		}
	return(-1);	// signals that we really finished the entire list
}
function importStopped()
{
	var cmi=config.macros.importTiddlers; // abbreviation
	var list = $('importList');
	var theNewTitle = $('importNewTitle');
	if (!list) return;
	if (cmi.index==-1){ 
		$('importStart').value=cmi.startText;
		importReport();		// import finished... generate the report
	} else {
		// import collision...
		// show the collision panel and set the title edit field
		$('importStart').value=cmi.stopText;
		cmi.showPanel('importCollisionPanel',true);
		theNewTitle.value=list.options[cmi.index].value;
		if ($('importApplyToAll').checked
			&& cmi.lastAction
			&& cmi.lastAction.id!='importRename') {
			onClickImportButton(cmi.lastAction);
		}
	}
}
//}}}
//{{{
function importReport()
{
	var cmi=config.macros.importTiddlers; // abbreviation
	if (!cmi.inbound) return;

	// if import was not completed, the collision panel will still be open... close it now.
	var panel=$('importCollisionPanel'); if (panel) panel.style.display='none';

	// get the alphasorted list of tiddlers
	var tiddlers = cmi.inbound;
	// gather the statistics
	var count=0; var total=0;
	for (var t=0; t<tiddlers.length; t++) {
		if (!tiddlers[t].status || !tiddlers[t].status.trim().length) continue;
		if (tiddlers[t].status.substr(0,7)!='skipped') count++;
		total++;
	}
	// generate a report
	if (total) displayMessage(cmi.processedMsg.format([total]));
	if (count && config.options.chkImportReport) {
		// get/create the report tiddler
		var theReport = store.getTiddler('ImportedTiddlers');
		if (!theReport) { theReport=new Tiddler(); theReport.title='ImportedTiddlers'; theReport.text=''; }
		// format the report content
		var now = new Date();
		var newText = 'On '+now.toLocaleString()+', '+config.options.txtUserName
		newText +=' imported '+count+' tiddler'+(count==1?'':'s')+' from\n[['+cmi.src+'|'+cmi.src+']]:\n';
		if (cmi.addTags && cmi.newTags.trim().length)
			newText += 'imported tiddlers were tagged with: "'+cmi.newTags+'"\n';
		newText += '<<<\n';
		for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status)
			newText += '#[['+tiddlers[t].title+']] - '+tiddlers[t].status+'\n';
		newText += '<<<\n';
		// update the ImportedTiddlers content and show the tiddler
		theReport.text	 = newText+((theReport.text!='')?'\n----\n':'')+theReport.text;
		theReport.modifier = config.options.txtUserName;
		theReport.modified = new Date();
                store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags, theReport.fields);
		story.displayTiddler(null,theReport.title,1,null,null,false);
		story.refreshTiddler(theReport.title,1,true);
	}
	// reset status flags
	for (var t=0; t<cmi.inbound.length; t++) cmi.inbound[t].status='';
	// mark document as dirty and let display update as needed
	if (count) { store.setDirty(true); store.notifyAll(); }
	// always show final message when tiddlers were actually loaded
	if (count) displayMessage(cmi.importedMsg.format([count,tiddlers.length,cmi.src.replace(/%20/g,' ')]));
}
//}}}
//{{{
// // File and XMLHttpRequest I/O
config.macros.importTiddlers.askForFilename=function(here) {
	var msg=here.title; // use tooltip as dialog box message
	var path=getLocalPath(document.location.href);
	var slashpos=path.lastIndexOf('/'); if (slashpos==-1) slashpos=path.lastIndexOf('\\'); 
	if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
	var file='';
	var result='';
	if(window.Components) { // moz
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, nsIFilePicker.modeOpen);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='html';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
		}
		catch(e) { alert('error during local file access: '+e.toString()) }
	}
	else { // IE
		try { // XPSP2 IE only
			var s = new ActiveXObject('UserAccounts.CommonDialog');
			s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
			s.FilterIndex=3; // default to HTML files;
			s.InitialDir=path;
			s.FileName=file;
			if (s.showOpen()) var result=s.FileName;
		}
		catch(e) {  // fallback
			var result=prompt(msg,path+file);
		}
	}
	return result;
}

config.macros.importTiddlers.loadRemoteFile = function(src,callback) {
	if (src==undefined || !src.length) return null; // filename is required
	var original=src; // URL as specified
	var hashpos=src.indexOf('#'); if (hashpos!=-1) src=src.substr(0,hashpos); // URL with #... suffix removed (needed for IE)
	clearMessage();
	displayMessage(this.openMsg.format([src.replace(/%20/g,' ')]));
	if (src.substr(0,5)!='http:' && src.substr(0,5)!='file:') { // if not a URL, read from local filesystem
		var txt=loadFile(src);
		if (!txt) { // file didn't load, might be relative path.. try fixup
			var pathPrefix=document.location.href;  // get current document path and trim off filename
			var slashpos=pathPrefix.lastIndexOf('/'); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf('\\'); 
			if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
			src=pathPrefix+src;
			if (pathPrefix.substr(0,5)!='http:') src=getLocalPath(src);
			var txt=loadFile(src);
		}
		if (!txt) { // file still didn't load, report error
			displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g,' '),'(filesystem error)']));
		} else {
			displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g,' ')]));
			if (callback) callback(true,original,convertUTF8ToUnicode(txt),src,null);
		}
	} else {
		var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
		var xhr=doHttp('GET',src,null,null,name,pass,callback,original,null)
		if (!xhr) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,'(XMLHTTPRequest error)']));
	}
}

config.macros.importTiddlers.readTiddlersFromHTML=function(html)
{
	var remoteStore=new TiddlyWiki();
	remoteStore.importTiddlyWiki(html);
	return remoteStore.getTiddlers('title');	
}

config.macros.importTiddlers.filterTiddlerList=function(success,params,txt,src,xhr) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var src=src.replace(/%20/g,' ');
	if (!success) { displayMessage(cmi.openErrMsg.format([src,xhr.status])); return; }
	cmi.all = cmi.readTiddlersFromHTML(txt);
	var count=cmi.all?cmi.all.length:0;
	var querypos=src.lastIndexOf('?'); if (querypos!=-1) src=src.substr(0,querypos);
	displayMessage(cmi.foundMsg.format([count,src]));
	cmi.inbound=cmi.filterByHash(params,cmi.all); // use full URL including hash (if any)
	$('importLastFilter').value=cmi.lastFilter;
	window.refreshImportList(0);
}

config.macros.importTiddlers.filterByHash=function(src,tiddlers)
{
	var hashpos=src.lastIndexOf('#'); if (hashpos==-1) return tiddlers;
	var hash=src.substr(hashpos+1); if (!hash.length) return tiddlers;
	var tids=[];
	var params=hash.parseParams('anon',null,true,false,false);
	for (var p=1; p<params.length; p++) {
		switch (params[p].name) {
			case 'anon':
			case 'open':
				tids.pushUnique(params[p].value);
				break;
			case 'tag':
				if (store.getMatchingTiddlers) { // for boolean expressions - see MatchTagsPlugin
					var r=store.getMatchingTiddlers(params[p].value,null,tiddlers);
					for (var t=0; t<r.length; t++) tids.pushUnique(r[t].title);
				} else for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].isTagged(params[p].value))
						tids.pushUnique(tiddlers[t].title);
				break;
			case 'story':
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].title==params[p].value) {
						tiddlers[t].changed();
						for (var s=0; s<tiddlers[t].links.length; s++)
							tids.pushUnique(tiddlers[t].links[s]);
						break;
					}
				break;
			case 'search':
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].text.indexOf(params[p].value)!=-1)
						tids.pushUnique(tiddlers[t].title);
				break;
		}
	}
	var matches=[];
	for (var t=0; t<tiddlers.length; t++)
		if (tids.contains(tiddlers[t].title))
			matches.push(tiddlers[t]);
	displayMessage(config.macros.importTiddlers.filterMsg.format([matches.length,hash]));
	config.macros.importTiddlers.lastFilter=hash;
	return matches;
}
//}}}
/***
|''Name:''|JapaneseTranslationPlugin |
|''Description:''|Translation of TiddlyWiki into Japanese |
|''Author:''|OGOSHI Masayuki &lt;ogoshima@gmail.com&gt; |
|''Source:''|http://ogoshi.tiddlyspot.com/#JapaneseTranslationPlugin |
|''Version:''|0.3.7.1-ja|
|''Date:''|Sep 04, 2008|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.1 Japan |http://creativecommons.org/licenses/by-sa/2.1/jp/]] |
|''~CoreVersion:''|2.4|

TiddlyWiki を日本語化するプラグイン。TiddlyWiki Version 2.4 上で動作を確認しました。
ライセンスは英語版のCCライセンスに準じる日本語版の CC-by-SA 2.1 ライセンスとします。

英語版のクレジットは以下のとおり。
|''Name:''|EnglishTranslationPlugin|
|''Description:''|Translation of TiddlyWiki into English|
|''Author:''|MartinBudden (mjbudden (at) gmail (dot) com)|
|''Source:''|www.example.com |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/association/locales/core/en/locale.en.js |
|''Version:''|0.3.7|
|''Date:''|Jul 6, 2007|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]] |
|''~CoreVersion:''|2.4|
***/

//{{{
//--
//-- Translateable strings
//--

// Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone

config.locale = "ja"; // W3C language tag

if (config.options.txtUserName == 'YourName') // do not translate this line, but do translate the next line
	merge(config.options,{txtUserName: "氏名"});

merge(config.tasks,{
	save: {text: "保存", tooltip: "このTiddlyWikiを保存します", action: saveChanges},
	sync: {text: "同期", tooltip: "他のTiddlyWikiファイルやサーバと同期をとります", content: '<<sync>>'},
	importTask: {text: "取り込み", tooltip: "他のTiddlyWikiファイルやサーバからtiddlerやプラグインを取り込みます", content: '<<importTiddlers>>'},
	tweak: {text: "詳細設定", tooltip: "TiddlyWikiの細かな振る舞いを設定します", content: '<<options>>'},
	upgrade: {text: "アップグレード", tooltip: "TiddlyWiki本体をバージョンアップします", content: '<<upgrade>>'},
	plugins: {text: "プラグイン", tooltip: "インストール済みのプラグインを管理します", content: '<<plugins>>'}
});

// Options that can be set in the options panel and/or cookies
merge(config.optionsDesc,{
	txtUserName: "編集したtiddlerに記録されるユーザ名",
	chkRegExpSearch: "検索に正規表現を使います",
	chkCaseSensitiveSearch: "検索で大文字小文字を区別します",
	chkIncrementalSearch: "インクリメンタルサーチを行います",
	chkAnimate: "アニメーションを許可します",
	chkSaveBackups: "保存時にバックアップファイルを残します",
	chkAutoSave: "自動保存します",
	chkGenerateAnRssFeed: "保存時にRSSフィードを生成します",
	chkSaveEmptyTemplate: "空のテンプレートファイルを保存時に生成します",
	chkOpenInNewWindow: "外部へのリンクを新しいウィンドウで開きます",
	chkToggleLinks: "tiddlerへのリンククリックでtiddlerを閉じます",
	chkHttpReadOnly: "HTTP経由で開いているときに編集機能を隠します",
	chkForceMinorUpdate: "更新時にユーザ名と日付を変更しません",
	chkConfirmDelete: "tiddlerを消去する時に確認をします",
	chkInsertTabs: "タブキーを押したとき、フィールド間の移動ではなくタブ文字を挿入します",
	txtBackupFolder: "バックアップ用フォルダの名前",
	txtMaxEditRows: "編集領域の最大行数",
	txtFileSystemCharSet: "保存時のデフォルト文字コード(Firefox/Mozillaのみ)"});

merge(config.messages,{
	customConfigError: "プラグインの読み込み時に問題が発生しました。詳細は PluginManager をご覧ください",
	pluginError: "エラー: %0",
	pluginDisabled: "'systemConfigDisable'タグによって実行が禁止されています",
	pluginForced: "'systemConfigForce'タグによって強制実行されました",
	pluginVersionError: "このプラグインの実行には、新しいバージョンの TiddlyWiki が必要です。",
	nothingSelected: "何も選択されていません。一つ以上選択する必要があります。",
	savedSnapshotError: "この~TiddlyWikiは正常に保存されていません。詳細は http://www.tiddlywiki.com/#DownloadSoftware をご覧ください。",
	subtitleUnknown: "(unknown)",
	undefinedTiddlerToolTip: "この tiddler '%0' はまだ作成されていません",
	shadowedTiddlerToolTip: "この tiddler '%0' はまだ作成されていませんが、隠された規定値があります",
	tiddlerLinkTooltip: "%0 - %1, %2",
	externalLinkTooltip: "(外部へのリンク) %0",
	noTags: "タグの付いた tiddler はありません",
	notFileUrlError: "変更を保存するにはこの~TiddlyWikiをファイルとして保存(ダウンロード)する必要があります",
	cantSaveError: "変更を保存できませんでした。以下の理由が考えられます:\n- 使用しているブラウザが保存に対応していない(Firefox/Internet Explorer/Safari/Operaは、正しく設定していれば保存できます)\n- TiddlyWikiファイルの保存path名に不正な文字が含まれている\n- TiddlyWiki HTMLファイルが移動または名前を変更された",
	invalidFileError: "元のファイル '%0' は正しい~TiddlyWikiファイルではありません",
	backupSaved: "バックアップを保存しました",
	backupFailed: "バックアップの保存に失敗しました",
	rssSaved: "RSSフィードを保存しました",
	rssFailed: "RSSフィードの保存に失敗しました",
	emptySaved: "空のテンプレートファイルを保存しました",
	emptyFailed: "空のテンプレートファイルの保存に失敗しました",
	mainSaved: "TiddlyWikiファイルを保存しました",
	mainFailed: "TiddlyWikiファイルの保存に失敗しました。変更した内容は保存されていません",
	macroError: "次のマクロでエラー発生 <<\%0>>",
	macroErrorDetails: "次のマクロを実行中にエラー発生 <<\%0>>:\n%1",
	missingMacro: "マクロがありません",
	overwriteWarning: "'%0'という名前のtiddlerはすでに存在します。OKで上書きします",
	unsavedChangesWarning: "注意! TiddlyWiki の変更が保存されていません。\n\n'OK'で保存\n'キャンセル'で変更を破棄",
	confirmExit: "--------------------------------\n\nTiddlyWikiの変更が保存されていません。このまま続けると変更が失われます\n\n--------------------------------",
	saveInstructions: "変更を保存",
	unsupportedTWFormat: "次の TiddlyWiki フォーマットには対応していません '%0'",
	tiddlerSaveError: "tiddler '%0' を保存時にエラー発生",
	tiddlerLoadError: "tiddler '%0' の読込時にエラー発生",
	wrongSaveFormat: "保存フォーマット '%0' で保存できません。標準フォーマットで保存します",
	invalidFieldName: "%0 は不正なファイル名です",
	fieldCannotBeChanged: "領域 '%0' は変更できません",
	loadingMissingTiddler: "tiddler '%0' の '%1' サーバーからの回復を試しています:\n\nワークスペース '%3' の中の '%2'",
	upgradeDone: "バージョン %0 へのアップグレードが完了しました。\n'OK' をクリックすると新しくなったTiddlyWikiをリロードします。"});

merge(config.messages.messageClose,{
	text: "閉じる",
	tooltip: "このメッセージを閉じます"});

config.messages.backstage = {
	open: {text: "クイックメニュー", tooltip: "クイックメニューを開きます"},
	close: {text: "閉じる", tooltip: "クイックメニューを閉じます"},
	prompt: "クイックメニュー: ",
	decal: {
		edit: {text: "編集", tooltip: "tiddler '%0' を編集します"}
	}
};

config.messages.listView = {
	tiddlerTooltip: "このtiddlerのテキスト全体を表示します",
	previewUnavailable: "(プレビューがありません)"
};

config.messages.dates.months = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月","12月"];
config.messages.dates.days = ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"];
config.messages.dates.shortMonths = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
config.messages.dates.shortDays = ["日", "月", "火", "水", "木", "金", "土"];
// suffixes for dates, eg "1st","2nd","3rd"..."30th","31st"
config.messages.dates.daySuffixes = ["日","日","日","日","日","日","日","日","日","日",
		"日","日","日","日","日","日","日","日","日","日",
		"日","日","日","日","日","日","日","日","日","日",
		"日"];
config.messages.dates.am = "am";
config.messages.dates.pm = "pm";

merge(config.messages.tiddlerPopup,{
	});

merge(config.views.wikified.tag,{
	labelNoTags: "タグ無し",
	labelTags: "タグ: ",
	openTag: "'%0' タグを開く",
	tooltip: "'%0' タグの付いたtiddlerを表示",
	openAllText: "全て開く",
	openAllTooltip: "以下のtiddlerを全て開く",
	popupNone: "'%0' タグの付いたtiddlerは他にありません"});

merge(config.views.wikified,{
	defaultText: "tiddler '%0' はまだ作成されていません。ダブルクリックで作成できます",
	defaultModifier: "(missing)",
	shadowModifier: "(built-in shadow tiddler)",
	dateFormat: "YYYY.MM.DD", // use this to change the date format for your locale, eg "YYYY MMM DD", do not translate the Y, M or D
	createdPrompt: "作成"});

merge(config.views.editor,{
	tagPrompt: "スペース区切りでタグを入力。スペースを含める場合は[[二重の角括弧]]で囲みます。既存のタグを選択≫",
	defaultText: "'%0' の内容を入力してください"});

merge(config.views.editor.tagChooser,{
	text: "タグ",
	tooltip: "既存のタグを選択して追加します",
	popupNone: "タグが定義されていません",
	tagTooltip: "'%0' タグを追加します"});

merge(config.messages,{
	sizeTemplates:
		[
		{unit: 1024*1024*1024, template: "%0\u00a0GB"},
		{unit: 1024*1024, template: "%0\u00a0MB"},
		{unit: 1024, template: "%0\u00a0KB"},
		{unit: 1, template: "%0\u00a0B"}
		]});

merge(config.macros.search,{
	label: "検索",
	prompt: "この TiddlyWiki 内を検索します",
	accessKey: "F",
	successMsg: "%0 件のtiddlerで %1 が見つかりました",
	failureMsg: "%0 は見つかりませんでした"});

merge(config.macros.tagging,{
	label: "タグあり: ",
	labelNotTag: "タグなし",
	tooltip: "'%0' タグを付けたtiddlerリスト"});

merge(config.macros.timeline,{
	dateFormat: "YYYY年MM月DD日"});// use this to change the date format for your locale, eg "YYYY MMM DD", do not translate the Y, M or D

merge(config.macros.allTags,{
	tooltip: "'%0' タグの付いたtiddlerを表示",
	noTags: "タグの付いたtiddlerがありません"});

config.macros.list.all.prompt = "アルファベット順 全tiddler";
config.macros.list.missing.prompt = "リンクがあるのに存在しないtiddler";
config.macros.list.orphans.prompt = "どこからもリンクされていないtiddler";
config.macros.list.shadowed.prompt = "規定で隠されているtiddler";
config.macros.list.touched.prompt = "ローカルに変更されているtiddler";

merge(config.macros.closeAll,{
	label: "全て閉じる",
	prompt: "表示されている全てのtiddlerを閉じます (編集中を除く)"});

merge(config.macros.permaview,{
	label: "現況リンク",
	prompt: "現在のtiddler表示状態を再現するURLをアドレス欄に生成します"});

merge(config.macros.saveChanges,{
	label: "保存",
	prompt: "全てのtiddlerを保存します",
	accessKey: "S"});

merge(config.macros.newTiddler,{
	label: "新規作成",
	prompt: "新しいtiddlerを作成します",
	title: "新規作成",
	accessKey: "N"});

merge(config.macros.newJournal,{
	label: "新規ジャーナル",
	prompt: "現在日時がタイトルの新しいtiddlerを作成します",
	accessKey: "J"});

merge(config.macros.options,{
	wizardTitle: "詳細設定",
	step1Title: "これらのオプション設定はブラウザのcookieに保存されます",
	step1Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='false' name='chkUnknown'>未知のオプションを表示</input>",
	unknownDescription: "//(未知)//",
	listViewTemplate: {
		columns: [
			{name: 'Option', field: 'option', title: "オプション設定", type: 'String'},
			{name: 'Description', field: 'description', title: "説明", type: 'WikiText'},
			{name: 'Name', field: 'name', title: "オプション名", type: 'String'}
			],
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'}
			]}
	});

merge(config.macros.plugins,{
	wizardTitle: "プラグイン管理",
	step1Title: "ロードされているプラグイン",
	step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
	skippedText: "(このプラグインは起動後に追加されたので実行されていません)",
	noPluginText: "プラグインはインストールされていません",
	confirmDeleteText: "本当にこのプラグインを削除して良いですか?:\n\n%0",
	removeLabel: "systemConfig タグを除去",
	removePrompt: "systemConfig タグを除去します",
	deleteLabel: "削除",
	deletePrompt: "これらのtiddlerを削除します",
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "サイズ", type: 'Size'},
			{name: 'Forced', field: 'forced', title: "強制実行", tag: 'systemConfigForce', type: 'TagCheckbox'},
			{name: 'Disabled', field: 'disabled', title: "無効化", tag: 'systemConfigDisable', type: 'TagCheckbox'},
			{name: 'Executed', field: 'executed', title: "ロード済み", type: 'Boolean', trueText: "Yes", falseText: "No"},
			{name: 'Startup Time', field: 'startupTime', title: "起動時実行", type: 'String'},
			{name: 'Error', field: 'error', title: "ステータス", type: 'Boolean', trueText: "Error", falseText: "OK"},
			{name: 'Log', field: 'log', title: "ログ", type: 'StringList'}
			],
		rowClasses: [
			{className: 'error', field: 'error'},
			{className: 'warning', field: 'warning'}
			]}
	});

merge(config.macros.toolbar,{
	moreLabel: "その他",
	morePrompt: "その他のコマンドも表示します"
	});

merge(config.macros.refreshDisplay,{
	label: "再表示",
	prompt: "TiddlyWiki全体を再描画します"
	});

merge(config.macros.importTiddlers,{
	readOnlyWarning: "読込専用のTiddlyWikiには取り込めません。TiddlyWikiファイルを file:// 形式のURLで開いてみてください",
	wizardTitle: "他のファイルあるいはサーバーからtiddlerを取り込む",
	step1Title: "手順 1: TiddlyWikiファイルあるいはサーバーの位置を指定します",
	step1Html: "種別指定: <select name='selTypes'><option value=''>選択...</option></select><br>URLまたはパス名を入力: <input type='text' size=50 name='txtPath'><br>またはファイルを選択: <input type='file' size=50 name='txtBrowse'><br><hr>または既定のフィードを選択: <select name='selFeeds'><option value=''>選択...</option></select>",
	openLabel: "開く",
	openPrompt: "このファイルあるいはサーバーへ接続する",
	openError: "TiddlyWikiファイルを取り込む際に問題が発生しました",
	statusOpenHost: "ホストをオープン中",
	statusGetWorkspaceList: "有効なワークスペースのリストを取得中",
	step2Title: "手順 2: ワークスペースの選択",
	step2Html: "ワークスペース名を入力: <input type='text' size=50 name='txtWorkspace'><br>またはワークスペースを選択: <select name='selWorkspace'><option value=''>選択...</option></select>",
	cancelLabel: "キャンセル",
	cancelPrompt: "この取り込みをキャンセルする",
	statusOpenWorkspace: "ワークスペースをオープン中",
	statusGetTiddlerList: "有効なtiddlerのリストを取得中",
	errorGettingTiddlerList: "tiddlerのリストを取得中にエラーが発生しました。'キャンセル'でやり直します。",
	step3Title: "手順 3: 取り込むtiddlerの選択",
	step3Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='true' name='chkSync'>変更を同期できるよう、各tiddlerにこのサーバー(ファイル)へのリンクを保持する</input><br><input type='checkbox' name='chkSave'>'systemServer' タグを付けたtiddlerにこのサーバーの詳細を保存する:</input> <input type='text' size=25 name='txtSaveTiddler'>",
	importLabel: "取込",
	importPrompt: "これらのtiddlerを取り込む",
	confirmOverwriteText: "本当にこれらのtiddlerを上書きして良いですか? :\n\n%0",
	step4Title: "手順 4: tiddler %0 を取り込み",
	step4Html: "<input type='hidden' name='markReport'></input>", // DO NOT TRANSLATE
	doneLabel: "完了",
	donePrompt: "ウィザードを閉じる",
	statusDoingImport: "tidderlを取り込み中",
	statusDoneImport: "全てのtiddlerを取り込みました",
	systemServerNamePattern: "%1 / %2",
	systemServerNamePatternNoWorkspace: "%1",
	confirmOverwriteSaveTiddler: "'%0' というtiddlerは既に存在します。'OK'で上書きします。'キャンセル'で変更しません。",
	serverSaveTemplate: "|''種別:''|%0|\n|''URL:''|%1|\n|''ワークスペース:''|%2|\n\nこのtiddlerはこのサーバーの詳細情報を記録するために自動的に作成されました",
	serverSaveModifier: "(System)",
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "サイズ", type: 'Size'},
			{name: 'Tags', field: 'tags', title: "タグ", type: 'Tags'}
			],
		rowClasses: [
			]}
	});

merge(config.macros.upgrade,{
	wizardTitle: "TiddlyWiki本体のアップグレード",
	step1Title: "このTiddlyWikiを最新版へ更新(あるいは修復)",
	step1Html: "TiddlyWiki本体のバージョンを <a href='%0' class='externalLink' target='_blank'>%1</a> から最新版に更新しようとしています。この更新をしてもあなたの作成したデータが削除されることはありません。<br><br>なお、本体をアップデートすることで旧プラグインの動作に支障が出る可能性があります。もし更新後の動作に問題が生じたときは、次のサイトを参照してください。<a href='http://www.tiddlywiki.org/wiki/CoreUpgrades' class='externalLink' target='_blank'>http://www.tiddlywiki.org/wiki/CoreUpgrades</a>",
	errorCantUpgrade: "このTiddlyWikiを更新できませんでした。ローカルに保存したファイルにしか、TiddlyWikiの更新はできません。",
	errorNotSaved: "更新を行う前にまずファイルを保存してください。",
	step2Title: "更新作業の詳細を確認",
	step2Html_downgrade: "TiddlyWikiのバージョンを %1 から %0 へダウングレードしようとしています。<br><br>TiddlyWiki本体を旧バージョンにダウングレードすることは推奨されません。",
	step2Html_restore: "このTiddlyWikiはすでに最新版(%0)です。<br><br>もちろんTiddlyWiki本体が破損していたときなどのために、このまま更新を継続することもできます。",
	step2Html_upgrade: "TiddlyWikiのバージョンを %1 から %0 に更新しようとしています。",
	upgradeLabel: "更新",
	upgradePrompt: "更新処理の準備",
	statusPreparingBackup: "バックアップの準備中",
	statusSavingBackup: "バックアップファイル保存中",
	errorSavingBackup: "バックアップファイルの保存中にエラーが発生しました",
	statusLoadingCore: "本体プログラムを読み込み中",
	errorLoadingCore: "本体プログラムの読み込み中にエラーが発生しました",
	errorCoreFormat: "新しいプログラムにエラーが発生しました",
	statusSavingCore: "本体プログラムの保存中",
	statusReloadingCore: "本体プログラムのリロード中",
	startLabel: "開始",
	startPrompt: "更新処理を開始する",
	cancelLabel: "キャンセル",
	cancelPrompt: "更新処理を中断する",
	step3Title: "更新処理を中断",
	step3Html: "更新処理を中断しました"
	});

merge(config.macros.sync,{
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'},
			{name: 'Server Type', field: 'serverType', title: "種別", type: 'String'},
			{name: 'Server Host', field: 'serverHost', title: "サーバーホスト", type: 'String'},
			{name: 'Server Workspace', field: 'serverWorkspace', title: "ワークスペース", type: 'String'},
			{name: 'Status', field: 'status', title: "同期ステータス", type: 'String'},
			{name: 'Server URL', field: 'serverUrl', title: "サーバーURL", text: "開く", type: 'Link'}
			],
		rowClasses: [
			],
		buttons: [
			{caption: "これらのtiddlerを同期", name: 'sync'}
			]},
	wizardTitle: "外部サーバーやファイルとの同期",
	step1Title: "同期したいtiddlerを選択してください",
	step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
	syncLabel: "同期",
	syncPrompt: "各tiddlerを同期します",
	hasChanged: "ローカル側変更あり",
	hasNotChanged: "ローカル側変更なし",
	syncStatusList: {
		none: {text: "...", color: "transparent", display:null},
		changedServer: {text: "サーバー側で変更あり", color: '#8080ff', display:null},
		changedLocally: {text: "ローカル側で変更あり", color: '#80ff80', display:null},
		changedBoth: {text: "双方で変更あり", color: '#ff8080', display:null},
		notFound: {text: "サーバーに見つかりません", color: '#ffff80', display:null},
		putToServer: {text: "更新をサーバーに保存しました", color: '#ff80ff', display:null},
		gotFromServer: {text: "サーバーから更新を取得しました", color: '#80ffff', display:null}
		}
	});

merge(config.commands.closeTiddler,{
	text: "閉じる",
	tooltip: "このtiddlerを閉じます"});

merge(config.commands.closeOthers,{
	text: "他を閉じる",
	tooltip: "他の全てのtiddlerを閉じます"});

merge(config.commands.editTiddler,{
	text: "編集",
	tooltip: "このtiddlerを編集します",
	readOnlyText: "閲覧",
	readOnlyTooltip: "このtiddlerのソースを表示します"});

merge(config.commands.saveTiddler,{
	text: "確定",
	tooltip: "このtiddlerへの変更を保存します"});

merge(config.commands.cancelTiddler,{
	text: "キャンセル",
	tooltip: "このtiddlerへの変更を破棄します",
	warning: "本当に '%0' の変更を破棄して良いですか?",
	readOnlyText: "終了",
	readOnlyTooltip: "このtiddlerを通常表示にします"});

merge(config.commands.deleteTiddler,{
	text: "削除",
	tooltip: "このtiddlerを削除します",
	warning: "本当に '%0' を削除して良いですか?"});

merge(config.commands.permalink,{
	text: "リンクURL",
	tooltip: "このtiddlerへのURLをアドレス欄に生成します"});

merge(config.commands.references,{
	text: "参照一覧",
	tooltip: "このtiddlerへの参照を一覧表示します",
	popupNone: "参照がありません"});

merge(config.commands.jump,{
	text: "ジャンプ",
	tooltip: "他に開いているtiddlerへジャンプ"});

merge(config.commands.syncing,{
	text: "同期",
	tooltip: "このtiddlerと外部のサーバー(ファイル)との同期を制御します",
	currentlySyncing: "<div>現在の同期状態<br>種別: <span class='popupHighlight'>'%0'</span><br></"+"div><div>ホスト: <span class='popupHighlight'>%1</span></"+"div><br><div>ワークスペース: <span class='popupHighlight'>%2</span></"+"div>", // Note escaping of closing <div> tag
	notCurrentlySyncing: "同期されていません",
	captionUnSync: "このtiddlerの同期を停止",
	chooseServer: "このtiddlerを次のサーバーと同期する:",
	currServerMarker: "\u25cf ",
	notCurrServerMarker: "  "});

merge(config.commands.fields,{
	text: "拡張情報",
	tooltip: "このtiddlerの拡張情報を表示します",
	emptyText: "このtiddlerには拡張情報がありません",
	listViewTemplate: {
		columns: [
			{name: 'Field', field: 'field', title: "項目", type: 'String'},
			{name: 'Value', field: 'value', title: "値", type: 'String'}
			],
		rowClasses: [
			],
		buttons: [
			]}});

merge(config.shadowTiddlers,{
	DefaultTiddlers: "[[TranslatedGettingStarted]]",
	MainMenu: "[[TranslatedGettingStarted]]\n\n\n^^~TiddlyWiki version <<version>>\n(c) 2007 [[UnaMesa|http://www.unamesa.org/]]^^",
	TranslatedGettingStarted: "この空の~TiddlyWikiを使い始めるにあたって、まずは以下のtiddlerを編集してください。:\n;SiteTitle & SiteSubtitle: \n:このサイトのタイトルおよびサブタイトル。この上に表示されています。<br>保存後はブラウザのタイトルバーにも表示されます。\n;MainMenu: \n:メニュー。たいていは左側に表示されています。\n;DefaultTiddlers: \n:ここにtiddlerの名前が書かれていると、この TiddlyWiki を開いたときに、<br>そのtiddlerが初期表示されます。\nあなたの名前(編集したtiddlerに表示されます): <<option txtUserName>>",
	SiteTitle: "My TiddlyWiki",
	SiteSubtitle: "a reusable non-linear personal web notebook",
	SiteUrl: "http://www.tiddlywiki.com/",
	OptionsPanel: "これらの~TiddlyWikiを制御する各オプションの設定は、使用中のブラウザに保存されます。\n\n署名として使用するあなたの名前を~WikiWord形式(例 JoeBloggs)で入力してください。\n<<option txtUserName>>\n\n<<option chkSaveBackups>> バックアップを保存\n<<option chkAutoSave>> 自動保存\n<<option chkRegExpSearch>> 正規表現で検索\n<<option chkCaseSensitiveSearch>> 検索で大文字小文字を区別\n<<option chkAnimate>> アニメーション\n\n----\n詳細設定 [[TranslatedAdvancedOptions|AdvancedOptions]]",
	SideBarOptions: '<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal "YYYY年MM月DD日" "ジャーナル">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "オプション \u00bb" "TiddlyWiki の詳細設定">>',
	SideBarTabs: '<<tabs txtMainTab "時系列" "更新時刻の降順" TabTimeline "全て" "全てのtiddler" TabAll "タグ別" "全てのタグ" TabTags "その他" "その他の一覧" TabMore>>',
	TabMore: '<<tabs txtMoreTab "未作成" "リンクがあるのに存在しないtiddler" TabMoreMissing "孤立" "どこからもリンクされていないtiddler" TabMoreOrphans "隠し" "隠されているtiddler" TabMoreShadowed>>'});

merge(config.annotations,{
	AdvancedOptions: "このtiddlerでは詳細オプションを設定できます",
	ColorPalette: "この隠しtiddlerで設定された各値によって、この~TiddlyWikiでの色の枠組みが規定されます。",
	DefaultTiddlers: "この隠しtiddlerに列挙された各tiddlerは、この~TiddlyWIkiを開くと同時に自動的に表示されます。",
	EditTemplate: "この隠しtiddlerにあるHTMLテンプレートは、tiddler編集中の表示方法を決定します。",
	GettingStarted: "この隠しtiddlerは基本的な使用方法を説明します。",
	ImportTiddlers: "この隠しtiddlerは他のtiddlerの取り込み機能を提供します。",
	MainMenu: "この隠しtiddlerの内容は「メインメニュー」に表示されます。画面左手に表示されます。",
	MarkupPreHead: "この隠しtiddlerの内容は、このTiddlyWikiHTMLファイルの<head>セクション開始直後に挿入されます。",
	MarkupPostHead: "この隠しtiddlerの内容は、このTiddlyWikiHTMLファイルの<head>セクション終了直前に挿入されます。",
	MarkupPreBody: "この隠しtiddlerの内容は、このTiddlyWikiHTMLファイルの<body>セクション開始直後に挿入されます。",
	MarkupPostBody: "この隠しtiddlerの内容は、このTiddlyWikiHTMLファイルのスクリプトブロック直後にある、<body>セクション終了直前に挿入されます。",
	OptionsPanel: "この隠しtiddlerの内容は、右手のサイドバー内でスライド式のオプションパネルとして表示されます。",
	PageTemplate: "この隠しtiddlerにあるHTMLテンプレートは、~TiddlyWiki全体のレイアウトを決定します。",
	PluginManager: "この隠しtiddlerはプラグインマネージャ機能を提供します。",
	SideBarOptions: "この隠しtiddlerの内容は右手のサイドバー内のオプションパネルとして表示されます。",
	SideBarTabs: "この隠しtiddlerの内容は右手のサイドバー内にタブパネルとして表示されます。",
	SiteSubtitle: "この隠しtiddlerはページのサブタイトルとして利用されます。",
	SiteTitle: "この隠しtiddlerはページのメインタイトルとして利用されます。",
	SiteUrl: "この隠しtiddlerには、このTiddlyWikiを公開する際のURLを指定する必要があります。",
	StyleSheetColors: "この隠しtiddlerはページ内各要素の色に関するCSSを規定します。このtiddlerを編集しないでください。色を修正するには代わりに StyleSheet 隠しtiddler を編集してください。",
	StyleSheet: "この隠しtiddlerはカスタムCSSを規定します。",
	StyleSheetLayout: "この隠しtiddlerはページ内各要素のレイアウトに関するCSSを規定します。このtiddlerを編集しないでください。レイアウトを修正するには代わりに StyleSheet 隠しtiddler を編集してください。",
	StyleSheetLocale: "この隠しtiddlerはページ内各要素の翻訳ロケールに関するCSSを規定します。",
	StyleSheetPrint: "この隠しtiddlerは印刷に関するCSSを規定します。",
	TabAll: "この隠しtiddlerの内容は右手のサイドバー内「全て」タブに表示されます。",
	TabMore: "この隠しtiddlerの内容は右手のサイドバー内「その他」タブに表示されます。",
	TabMoreMissing: "この隠しtiddlerの内容は右手のサイドバー内「未作成」タブに表示されます。",
	TabMoreOrphans: "この隠しtiddlerの内容は右手のサイドバー内「孤立」タブに表示されます。",
	TabMoreShadowed: "この隠しtiddlerの内容は右手のサイドバー内「隠し」タブに表示されます。",
	TabTags: "この隠しtiddlerの内容は右手のサイドバー内「タグ別」タブに表示されます。",
	TabTimeline: "この隠しtiddlerの内容は右手のサイドバー内「時系列」タブに表示されます。",
	ToolbarCommands: "この隠しtiddlerはtiddlerツールバーにどのようなコマンドを表示するかを決定します。",
	ViewTemplate: "この隠しtiddlerにあるHTMLテンプレートは、各tiddlerの表示方法を決定します。"
	});
//}}}
!総合
[[目次]]
!ピックアップ
[[XNA Game Studioについて]]
[[XNAの近況]]
[[XNA Game Studio 4.0]]
[[XNA Game Studio 3.1]]
[[XNA開発初級FAQ]]
[[XNA開発中級FAQ]]
[[.NET Framework開発FAQ]]
[[XNA関連サイト]]
[[XNAクリエーターズクラブ]]
[[Xbox LIVEインディーズゲーム]]
[[Xbox LIVEマーケットプレース]]
!機能(一部)
!!フレームワーク
[[Gameクラス]]/[[GameTimeクラス]]/[[コンテンツパイプライン]]
!!グラフィックス
グラフィックスデバイス/バックバッファ/レンダーターゲット/深度バッファ/ビューポート/[[レンダーステート]]/[[フォグ]]/スプライト/[[文字描画]]/[[エフェクト]]/[[アバター]]/[[ミップマップ|ミップマップの解像度とレベルの数]]/[[異方性フィルタリング]]
!!入出力
[[入力デバイス]]/ゲームパッド/キーボード/[[マウス]]/[[タッチパネル]]/[[加速度計]]/[[ストレージ]]
!!音声/動画
[[SoundEffect.Play]]/[[ダイナミックオーディオ]]/[[マイク入力]]/[[XACT]]/[[ビデオ再生]]
!!ネットワーク
[[ネットワーク]]/[[ゲーマーサービス]]/リッチプレゼンス
!ツール
[[XNA Game Studioパッケージユーティリティ]]
!対応プラットフォーム
[[Windows]]
[[Windows Phone 7]]
[[Xbox 360]]
[[Zune HD]]
----
[[ホーム (xelf.info)|http://xelf.info/]]
----
©2009-2010 XELF
----
[[RSS|index.xml]] [[管理]]
/***
|Name|Plugin: jsMath|
|Created by|BobMcElrath|
|Email|my first name at my last name dot org|
|Location|http://bob.mcelrath.org/tiddlyjsmath.html|
|Version|1.5.1|
|Requires|[[TiddlyWiki|http://www.tiddlywiki.com]] &ge; 2.0.3, [[jsMath|http://www.math.union.edu/~dpvc/jsMath/]] &ge; 3.0|
!Description
LaTeX is the world standard for specifying, typesetting, and communicating mathematics among scientists, engineers, and mathematicians.  For more information about LaTeX itself, visit the [[LaTeX Project|http://www.latex-project.org/]].  This plugin typesets math using [[jsMath|http://www.math.union.edu/~dpvc/jsMath/]], which is an implementation of the TeX math rules and typesetting in javascript, for your browser.  Notice the small button in the lower right corner which opens its control panel.
!Installation
In addition to this plugin, you must also [[install jsMath|http://www.math.union.edu/~dpvc/jsMath/download/jsMath.html]] on the same server as your TiddlyWiki html file.  If you're using TiddlyWiki without a web server, then the jsMath directory must be placed in the same location as the TiddlyWiki html file.

I also recommend modifying your StyleSheet use serif fonts that are slightly larger than normal, so that the math matches surrounding text, and \\small fonts are not unreadable (as in exponents and subscripts).
{{{
.viewer {
  line-height: 125%;
  font-family: serif;
  font-size: 12pt;
}
}}}

If you had used a previous version of [[Plugin: jsMath]], it is no longer necessary to edit the main tiddlywiki.html file to add the jsMath <script> tag.  [[Plugin: jsMath]] now uses ajax to load jsMath.
!History
* 11-Nov-05, version 1.0, Initial release
* 22-Jan-06, version 1.1, updated for ~TW2.0, tested with jsMath 3.1, editing tiddlywiki.html by hand is no longer necessary.
* 24-Jan-06, version 1.2, fixes for Safari, Konqueror
* 27-Jan-06, version 1.3, improved error handling, detect if ajax was already defined (used by ZiddlyWiki)
* 12-Jul-06, version 1.4, fixed problem with not finding image fonts
* 26-Feb-07, version 1.5, fixed problem with Mozilla "unterminated character class".
* 27-Feb-07, version 1.5.1, Runs compatibly with TW 2.1.0+, by Bram Chen
!Examples
|!Source|!Output|h
|{{{The variable $x$ is real.}}}|The variable $x$ is real.|
|{{{The variable \(y\) is complex.}}}|The variable \(y\) is complex.|
|{{{This \[\int_a^b x = \frac{1}{2}(b^2-a^2)\] is an easy integral.}}}|This \[\int_a^b x = \frac{1}{2}(b^2-a^2)\] is an easy integral.|
|{{{This $$\int_a^b \sin x = -(\cos b - \cos a)$$ is another easy integral.}}}|This $$\int_a^b \sin x = -(\cos b - \cos a)$$ is another easy integral.|
|{{{Block formatted equations may also use the 'equation' environment \begin{equation}  \int \tan x = -\ln \cos x \end{equation} }}}|Block formatted equations may also use the 'equation' environment \begin{equation}  \int \tan x = -\ln \cos x \end{equation}|
|{{{Equation arrays are also supported \begin{eqnarray} a &=& b \\ c &=& d \end{eqnarray} }}}|Equation arrays are also supported \begin{eqnarray} a &=& b \\ c &=& d \end{eqnarray} |
|{{{I spent \$7.38 on lunch.}}}|I spent \$7.38 on lunch.|
|{{{I had to insert a backslash (\\) into my document}}}|I had to insert a backslash (\\) into my document|
!Code
***/
//{{{

// AJAX code adapted from http://timmorgan.org/mini
// This is already loaded by ziddlywiki...
if(typeof(window["ajax"]) == "undefined") {
  ajax = {
      x: function(){try{return new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){return new XMLHttpRequest()}}},
      gets: function(url){var x=ajax.x();x.open('GET',url,false);x.send(null);return x.responseText}
  }
}

// Load jsMath
jsMath = {
  Setup: {inited: 1},          // don't run jsMath.Setup.Body() yet
  Autoload: {root: new String(document.location).replace(/[^\/]*$/,'jsMath/')}  // URL to jsMath directory, change if necessary
};
var jsMathstr;
try {
  jsMathstr = ajax.gets(jsMath.Autoload.root+"jsMath.js");
} catch(e) {
  alert("jsMath was not found: you must place the 'jsMath' directory in the same place as this file.  "
       +"The error was:\n"+e.name+": "+e.message);
  throw(e);  // abort eval
}
try {
  window.eval(jsMathstr);
} catch(e) {
  alert("jsMath failed to load.  The error was:\n"+e.name + ": " + e.message + " on line " + e.lineNumber);
}
jsMath.Setup.inited=0;  //  allow jsMath.Setup.Body() to run again

// Define wikifers for latex
config.formatterHelpers.mathFormatHelper = function(w) {
    var e = document.createElement(this.element);
    e.className = this.className;
    var endRegExp = new RegExp(this.terminator, "mg");
    endRegExp.lastIndex = w.matchStart+w.matchLength;
    var matched = endRegExp.exec(w.source);
    if(matched) {
        var txt = w.source.substr(w.matchStart+w.matchLength, 
            matched.index-w.matchStart-w.matchLength);
        if(this.keepdelim) {
          txt = w.source.substr(w.matchStart, matched.index+matched[0].length-w.matchStart);
        }
        e.appendChild(document.createTextNode(txt));
        w.output.appendChild(e);
        w.nextMatch = endRegExp.lastIndex;
    }
}

config.formatters.push({
  name: "displayMath1",
  match: "\\\$\\\$",
  terminator: "\\\$\\\$\\n?", // 2.0 compatability
  termRegExp: "\\\$\\\$\\n?",
  element: "div",
  className: "math",
  handler: config.formatterHelpers.mathFormatHelper
});

config.formatters.push({
  name: "inlineMath1",
  match: "\\\$", 
  terminator: "\\\$", // 2.0 compatability
  termRegExp: "\\\$",
  element: "span",
  className: "math",
  handler: config.formatterHelpers.mathFormatHelper
});

var backslashformatters = new Array(0);

backslashformatters.push({
  name: "inlineMath2",
  match: "\\\\\\\(",
  terminator: "\\\\\\\)", // 2.0 compatability
  termRegExp: "\\\\\\\)",
  element: "span",
  className: "math",
  handler: config.formatterHelpers.mathFormatHelper
});

backslashformatters.push({
  name: "displayMath2",
  match: "\\\\\\\[",
  terminator: "\\\\\\\]\\n?", // 2.0 compatability
  termRegExp: "\\\\\\\]\\n?",
  element: "div",
  className: "math",
  handler: config.formatterHelpers.mathFormatHelper
});

backslashformatters.push({
  name: "displayMath3",
  match: "\\\\begin\\{equation\\}",
  terminator: "\\\\end\\{equation\\}\\n?", // 2.0 compatability
  termRegExp: "\\\\end\\{equation\\}\\n?",
  element: "div",
  className: "math",
  handler: config.formatterHelpers.mathFormatHelper
});

// These can be nested.  e.g. \begin{equation} \begin{array}{ccc} \begin{array}{ccc} ...
backslashformatters.push({
  name: "displayMath4",
  match: "\\\\begin\\{eqnarray\\}",
  terminator: "\\\\end\\{eqnarray\\}\\n?", // 2.0 compatability
  termRegExp: "\\\\end\\{eqnarray\\}\\n?",
  element: "div",
  className: "math",
  keepdelim: true,
  handler: config.formatterHelpers.mathFormatHelper
});

// The escape must come between backslash formatters and regular ones.
// So any latex-like \commands must be added to the beginning of
// backslashformatters here.
backslashformatters.push({
    name: "escape",
    match: "\\\\.",
    handler: function(w) {
        w.output.appendChild(document.createTextNode(w.source.substr(w.matchStart+1,1)));
        w.nextMatch = w.matchStart+2;
    }
});

config.formatters=backslashformatters.concat(config.formatters);

window.wikify = function(source,output,highlightRegExp,tiddler)
{
    if(source && source != "") {
        if(version.major == 2 && version.minor > 0) {
            var wikifier = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
            wikifier.subWikifyUnterm(output);
        } else {
            var wikifier = new Wikifier(source,formatter,highlightRegExp,tiddler);
            wikifier.subWikify(output,null);
        }
        jsMath.ProcessBeforeShowing();
    }
}
//}}}
XNA Game Studioでゲームプログラミング .
XNA情報
http://xna.xelf.info/
 [[XNA Game Studio 3.1]]から、SoundEffect.Playメソッドが追加されました。これは、[[XNA Game Studio 3.0]]のSoundEffect.CreateInstanceメソッドと使い分けできるようになっています。なお、音の演奏方法にはSoundEffectクラスのほかに、[[XACT3]]があります。

*SoundEffect.Playメソッド([[XNA Game Studio 3.1]]以降対応)
**効果音を発生させる。
**破棄を管理する必要がない。
**アプリケーションは効果音の状態を変えることはできない(必要がない場合に用いる)
**例外はなく、演奏失敗にfalseの戻り値を得る。
**ループ演奏はできない。

*SoundEffect.CreateInstanceメソッド([[XNA Game Studio 3.0]]以降対応)
**効果音のインスタンスを作成する。
**不要になったらDisposeメソッドを呼んで、破棄を管理すべき。
**戻り値のSoundEffectInstanceで、演奏を制御できる(「演奏」「一時停止」「再開」「停止」「音量」「定位」「音程」「ループ」「3D適用」)。
**確保できないときは例外になる。
**ループ演奏の指定が可能。
!StringBuilder.AppendFormatの書式を事前に解析しておいたら高速化になるか

 ToStringメソッドなどによるガベージの問題とは別に、「StringBuilder.AppendFormatの書式を事前に解析しておいたら高速化になるか」というベンチマークテストです。そのテストとして、後述ソースコードのように、CompiledStringFormatという機能を作成しています。

 このベンチマークテストでは「"Player {0} got {1} points!"」という書式に引数「"xyz", 100」を与えたときの文字列処理のパフォーマンスを比較します。

!!ベンチマークの比較
*手法1 : StringBuilder.AppendFormat : 元の処理
*手法2 : new CompiledStringFormat + CompiledStringFormat.AppendTo : 解析をその場で使うと遅くなることの確認
*手法3 : CompiledStringFormat.AppendTo : 解析しておいた場合

!!ベンチマークのコード(CompiledStringFormat )における書式の制限事項
*「{0}」や「{1}」などのみ対応
*「&#x7b;&#x7b;」や「}}」は認識しない
*「{0:#}」などの指定は処理できない

!!ベンチマークの結果(結果表示の目測)

|!|!PC [ms]|!同一PC手法比較 [%]|!Xbox 360 [ms]|!同一Xbox 360手法比較 [%]|
|手法1 × 100,000| 120| 100.00| 582| 100.00|
|手法2 × 100,000| 300| 250.00| 1,675| 287.80|
|手法3 × 100,000| 91| 75.83| 530| 91.07|

!!手法1→手法3

*手元のPCでは高速化になった
*Xbox 360でもわずかに高速化になった

※手法2は、CompiledStringFormatのパフォーマンス上の不適切な使い方を示しています。

 同じ書式で、動的に値の変化する文字列を毎フレーム表示をする場合などに、若干の効果がありそうです。書式自体を使わないで、1手ずつ文字列を処理するコードを書くこともできますが、多言語対応などで、書式つきの文字列をリソース管理する場合に、作業効率とパフォーマンスを確保できる可能性もあります。

※このベンチマークでは十分なガベージ対策は施していません。

!!ソースコード([[XNA Game Studio 3.1]]対応)
{{{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace XELF.StringFormat {
	public static partial class Helper {
		public static void Clear(this StringBuilder text) {
			text.Remove(0, text.Length);
		}
		public static void AppendFormat(this StringBuilder text, CompiledStringFormat format, params object[] args) {
			format.AppendTo(text, args);
		}
	}

	public struct CompiledStringFormat {
		interface IStringFeeder {
			void AppendTo(StringBuilder text, params object[] args);
		}

		struct StringFeeder : IStringFeeder {
			public readonly string Source;
			public readonly int StartIndex;
			public readonly int Length;
			public StringFeeder(string source, int startIndex, int length) {
				Source = source;
				StartIndex = startIndex;
				Length = length;
			}
			public void AppendTo(StringBuilder text, params object[] args) {
				text.Append(Source, StartIndex, Length);
			}
		}

		struct StringFeederArgument : IStringFeeder {
			public readonly int Index;
			public StringFeederArgument(int index) {
				Index = index;
			}
			public void AppendTo(StringBuilder text, params object[] args) {
				text.Append(args[Index].ToString());
			}
		}

		readonly IStringFeeder[] items;
		public CompiledStringFormat(string format) {
			List<IStringFeeder> items = new List<IStringFeeder>();
			for (int current = 0; current < format.Length; ) {
				var start = format.IndexOf('{', current);
				if (start >= 0) {
					var end = format.IndexOf('}', start);
					var length = start - current;
					if (length > 0) {
						items.Add(new StringFeeder(format, current, length));
					}
					var index = int.Parse(format.Substring(start + 1, end - start - 1));
					items.Add(new StringFeederArgument(index));
					current = end + 1;
				} else {
					start = format.Length;
					items.Add(new StringFeeder(format, current, start - current));
					current = start;
				}
			}
			this.items = items.ToArray();
		}
		public void AppendTo(StringBuilder text, params object[] args) {
			foreach (var item in items) {
				item.AppendTo(text, args);
			}
		}
	}
}

namespace XELF.StringFormat {
	public class StringFormatBenchmarkGame : Microsoft.Xna.Framework.Game {
		GraphicsDeviceManager graphics;
		SpriteBatch spriteBatch;
		SpriteFont font;
		readonly StringBuilder text = new StringBuilder(1024);
		readonly CompiledStringFormat format = new CompiledStringFormat("Player {0} got {1} points!");
		readonly CompiledStringFormat format2 = new CompiledStringFormat(
			"{3} times, \nraw format {0} [ms], \ncompiled format {1} [ms], \nprecompiled format {2} [ms]");
		readonly Stopwatch stopwatch = new Stopwatch();
		const int count = 100000;

		public StringFormatBenchmarkGame() {
			graphics = new GraphicsDeviceManager(this);
			Content.RootDirectory = "Content";
		}

		protected override void LoadContent() {
			spriteBatch = new SpriteBatch(GraphicsDevice);
			font = Content.Load<SpriteFont>("SpriteFont1");
		}

		protected override void Update(GameTime gameTime) {
			if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
				this.Exit();
			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime) {
			GraphicsDevice.Clear(Color.CornflowerBlue);

			TimeSpan t0, t1, t2;
			spriteBatch.Begin();
			{
				stopwatch.Reset();
				stopwatch.Start();
				for (int i = 0; i < count; i++) {
					text.Clear();
					text.AppendFormat("Player {0} got {1} points!", "xyz", 100);
				}
				stopwatch.Stop();
				t0 = stopwatch.Elapsed;
				spriteBatch.DrawString(font, text, new Vector2(100, 100), Color.White);
			}
			{
				stopwatch.Reset();
				stopwatch.Start();
				for (int i = 0; i < count; i++) {
					text.Clear();
					var format3 = new CompiledStringFormat("Player {0} got {1} points!");
					text.AppendFormat(format3, "xyz", 100);
				}
				stopwatch.Stop();
				t1 = stopwatch.Elapsed;
				spriteBatch.DrawString(font, text, new Vector2(100, 200), Color.White);
			}
			{
				stopwatch.Reset();
				stopwatch.Start();
				for (int i = 0; i < count; i++) {
					text.Clear();
					text.AppendFormat(format, "xyz", 100);
				}
				stopwatch.Stop();
				t2 = stopwatch.Elapsed;
				spriteBatch.DrawString(font, text, new Vector2(100, 300), Color.White);
			}

			text.Clear();
			text.AppendFormat(format2, t0.TotalMilliseconds, t1.TotalMilliseconds, t2.TotalMilliseconds, count);
			spriteBatch.DrawString(font, text, new Vector2(50, 400), Color.White);

			spriteBatch.End();
			base.Draw(gameTime);
		}
	}
}
}}}
.cs{white-space:pre; background-color:#f0f8ff; font-family:"MS ゴシック","Courier New",monospace;tab-width:2em;} /* C# code */
.k{color:#0000ff;} /* keyword */
.t{color:#2b91ab;} /* type */
.s{color:#a31515;} /* string literal */
.c{color:#008000;} /* comment */
.d{color:#808080;} /* document comment */
/%
|Name|TidIDECommand|
|Source|http://www.TiddlyTools.com/#TidIDECommand|
|Version|2.0.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|script|
|Requires|TidIDEPlugin, NestedSlidersPlugin, MoveablePanelPlugin, TextAreaPlugin, TiddlerTweakerPlugin, InlineJavascriptPlugin, CompareTiddlers|
|Overrides||
|Description|command link invokes TidIDE editor for current tiddler|

Usage (in ViewTemplate):
	<span class='toolbar' macro='tiddler TidIDECommand'></span>
OR embedded directly in tiddler content:
	<<tiddler TidIDECommand>>

%/+++^[TidIDE|Edit this tiddler using the TiddlyWiki Integrated Development Environment].../%
	%/{{fine smallform nowrap{<<moveablePanel>>/%
	%/<<tidIDE SystemInfo TiddlerTweaker CompareTiddlers +edit:here>>/%
	%/<<resizeEditor>>}}}/%
%/===
TidIDE - TiddlyWiki Integrated Development Environment

Provides tools for authors and developers to help construct and debug the contents of their TiddlyWiki documents.
/***
|Name|TidIDEPlugin|
|Source|http://www.TiddlyTools.com/#TidIDEPlugin|
|Documentation|http://www.TiddlyTools.com/#TidIDEPluginInfo|
|Version|1.8.3|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|TiddlyWiki Integrated Development Environment - tools for authors and plugin writers|
~TidIDE (//prounounced "Tie Dyed"//) - ''Tid''dlyWiki ''I''ntegrated ''D''evelopment ''E''nvironment - lets you define a set of checkboxes to toggle a stack of 'tool panels' containing tools for TiddlyWiki authors to use when creating and debugging their TiddlyWiki documents.  Each tool is defined by a separate tiddler, allowing you to define any convenient set of tools simply by adding/removing tiddler references from the {{{<<tidIDE...>>}}} macro call.

In addition to presenting checkboxes/tool panels that are defined in separate tiddlers, the {{{<<tidIDE>>}}} macro can invoke an optional built-in "editor panel" that presents an alternative tiddler editor to create, modify, and manage the tiddlers in your document... and, if you have also installed [[PreviewPlugin]], the editor can automatically display a ''//formatted preview//'' of the current tiddler content that is updated ''live, key-by-key'' while you edit the tiddler source.
!!!!!Documentation
>see [[TidIDEPluginInfo]]
!!!!!Configuration
<<<
Number of rows to display in text input area <<option txtTidIDEMaxEditRows>> 
{{{usage: <<option txtTidIDEMaxEditRows>>}}}
^^Note: if value is not specified here, default is to use {{{<<option txtMaxEditRows>>}}} core setting (see [[AdvancedOptions]])^^
<<<
!!!!!Revisions
<<<
2008.04.24 [1.8.3] fixed 'run' button onclick handler
2007.12.21 [1.8.2] added txtTidIDEMaxEditRows option as custom override for standard core txtMaxEditRows setting
2007.09.27 [1.8.0] split preview functionality into separate stand-alone plugin (see [[PreviewPlugin]]).  Moved {{{<<DOMViewer>>}}} macro definition to separate plugin (see [[DOMViewerPlugin]]).  Replicated ''run'' button functionality in stand-along plugin (see [[RunTiddlerPlugin]]). Major re-write of documentation
|please see [[TidIDEPluginInfo]] for additional revision details|
2006.04.15 [0.5.0] Initial ALPHA release. Converted from inline script.
<<<
!!!!!Code
***/
// // version
//{{{
version.extensions.TidIDEPlugin= {major: 1, minor: 8, revision: 3, date: new Date(2008,4,24)};
//}}}
// // settings
//{{{
if (config.options.txtTidIDEMaxEditRows==undefined)
	config.options.txtTidIDEMaxEditRows=config.options.txtMaxEditRows
//}}}
// //  macro definition
//{{{
config.macros.tidIDE = {
	versionMsg: "TidIDE v%0.%1.%2: ",
	datetimefmt: "0MM/0DD/YYYY 0hh:0mm",
	titleMsg: "Please enter a new tiddler title",
	isShadowMsg: "'%0' is a shadow tiddler and cannot be removed.",
	evalMsg: "Warning!! Processing '%0' as a systemConfig (plugin) tiddler may produce unexpected results! Are you sure you want to proceed?",
	evalCompletedMsg: "Processing completed",
	toolsDef: "<html><a href='javascript:config.macros.tidIDE.set(\"%0\",\"%1\");'>edit %1...</a></html>",
	editorLabel: "TiddlerEditor"
};
config.macros.tidIDE.handler= function(place,macroName,params) {
	var here=story.findContainingTiddler(place);
	var selectors="";
	var panels="";
	var showsys=false;
	var title="";
	var id=""; if (here) id=here.getAttribute("tiddler").replace(/ /g,"_");
	var p=params.shift();
	if (!p) p="edit:here"; // default to editor if no params
	var openpanels=[];
	var panelcount=0;
	while (p) {
		var defOpen=(p.substr(0,1)=="+"); if (defOpen) p=p.substr(1);
		if (p.substr(0,3)=="id:")
			{ id=p.substr(3); }
		else if (p.substr(0,4)=="edit") {
			panelcount++;
			defOpen=defOpen || (!params[0] && panelcount==1); // if only one panel to show, default to open
			var toolname=this.editorLabel;
			if (p.indexOf('|')!=-1) toolname=p.substr(0,p.indexOf('|'));
			selectors+=this.html.editorchk.replace(/%toolname%/mg,toolname);
			selectors=selectors.replace(/%showpanel%/mg,defOpen?"CHECKED":"");
			panels+=this.html.editorpanel;
			// editor panel setup...
			panels=panels.replace(/%showpanel%/mg,defOpen?"block":"none");
			panels=panels.replace(/%maxrows%/mg,config.options.txtTidIDEMaxEditRows);
			panels=panels.replace(/%disabled%/mg,readOnly?"DISABLED":"");
			panels=panels.replace(/%readonlychk%/mg,readOnly?"CHECKED":"");
			panels=panels.replace(/%minoredits%/mg,config.options.chkForceMinorUpdate&&!readOnly?"":"DISABLED");
			panels=panels.replace(/%minorchk%/mg,config.options.chkForceMinorUpdate?"CHECKED":"");
			var tiddlers=store.getTiddlers("title"); var tiddlerlist=""; 
			for (var t=0; t<tiddlers.length; t++)
				tiddlerlist+='<option value="'+tiddlers[t].title+'">'+tiddlers[t].title+'</option>';
			for (var t in config.shadowTiddlers)
				if (!store.tiddlerExists(t)) tiddlerlist+="<option value='"+t+"'>"+t+" (shadow)</option>";
			panels=panels.replace(/%tiddlerlist%/mg,tiddlerlist);
			var tags = store.getTags(); var taglist="";
			for (var t=0; t<tags.length; t++)
				taglist+="<option value='"+tags[t][0]+"'>"+tags[t][0]+"</option>";
			panels=panels.replace(/%taglist%/mg,taglist);
			if (p.substr(0,5)=="edit:") { 
				title=p.substr(5); 
				if (here && title=="here") title=here.id.substr(7);
			}
		}
		else {
			panelcount++;
			defOpen=defOpen || (!params[0] && panelcount==1); // if only one panel to show, default to open
			var toolid=toolname=p;
			if (p.indexOf('|')!=-1)
				{ toolname=p.substr(0,p.indexOf('|')); toolid=p.substr(p.indexOf('|')+1); }
			selectors+=this.html.toolschk.replace(/%toolid%/mg,toolid).replace(/%toolname%/mg,toolname);
			selectors=selectors.replace(/%showpanel%/mg,defOpen?"CHECKED":"");
			panels+=this.html.toolspanel.replace(/%toolid%/mg,toolid);
			panels=panels.replace(/%showpanel%/mg,defOpen?"block":"none");
			if (defOpen) openpanels.push(toolid);
		}
		p=params.shift(); // next param
	}
	var html=this.html.framework;
	if (panelcount<2)
		html=html.replace(/%version%/mg,'').replace(/%selector%/mg,''); // omit header/selectors if just one panel to display
	else {
		var v=version.extensions.TidIDEPlugin;
		html=html.replace(/%version%/mg, this.versionMsg.format([v.major,v.minor,v.revision]));
		html=html.replace(/%selector%/mg,selectors+"<hr style='margin:0;padding:0'>");
	}
	html=html.replace(/%panels%/mg,panels);
	html=html.replace(/%id%/mg,id);
	var newIDE=createTiddlyElement(place,"span");
	newIDE.innerHTML=html;
	if (title.length) this.set(id,title);  // pre-load tiddler editor values (if needed)
	if (openpanels.length) for (i=0;i<openpanels.length;i++) { config.macros.tidIDE.loadPanel(id,openpanels[i]); }
	// see [[TextAreaPlugin]] for extended ctrl-F/G (search/search again)and TAB handler definitions
	if (window.addKeyDownHandlers!=undefined) {
		var elems=newIDE.getElementsByTagName("textarea");
		for (var i=0;i<elems.length;i++) window.addKeyDownHandlers(elems[i]);
	}
	var prev=document.getElementById(id+'_previewpanel');
	if (config.macros.preview && prev)  // add previewer to editor (if installed)
		config.macros.preview.handler(prev,"preview",["text","15"]);
}
//}}}

// // CUSTOM PANEL FUNCTIONS 
//{{{
config.macros.tidIDE.loadPanel=function(id,toolid) {
	var place=document.getElementById(id+"_"+toolid+"_panel"); if (!place) return;
	var t=store.getTiddlerText(toolid,"");
	place.innerHTML=""; 
	if (t) wikify(t,place); else place.innerHTML=this.toolsDef.format([id,toolid]);
}
//}}}

// // EDITOR PANEL FUNCTIONS
//{{{
config.macros.tidIDE.set=function(id,title) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	if (f.dirty && !confirm(config.commands.cancelTiddler.warning.format([f.current]))) return;
	// reset to form defaults
	f.dirty=false;
	f.current="";
	f.created.value=f.created.defaultValue;
	f.modified.value=f.modified.defaultValue;
	f.author.value=f.author.defaultValue;
	f.content.value=f.content.defaultValue;
	f.tags.value=f.tags.defaultValue;
	f.size.value=f.size.defaultValue;
	if (!title.length) return;
	f.current=title;
	// values for new/shadow tiddlers
	var cdate=new Date();
	var mdate=new Date();
	var modifier=config.options.txtUserName;
	var text=config.views.editor.defaultText.format([title]);
	var tags="";
	// adjust values for shadow tiddlers
	if (store.isShadowTiddler(title))
		{ modifier=config.views.wikified.shadowModifier; text=store.getTiddlerText(title) }
	// get values for specified tiddler (if it exists)
	var t=store.getTiddler(title);
	if (t)	{ var cdate=t.created; var mdate=t.modified; var modifier=t.modifier; var text=t.text; var tags=t.getTags(); }
	if (!t && !store.isShadowTiddler(title)) f.tiddlers.options[f.tiddlers.options.length]=new Option(title,title,false,true); // add item to list
	f.tiddlers.value=title; // select current title (just in case it wasn't already selected)
	f.created.value=cdate.formatString(this.datetimefmt);
	f.modified.value=mdate.formatString(this.datetimefmt);
	f.author.value=modifier;
	f.content.value=text;
	f.tags.value=tags;
	f.minoredits.checked=config.options.chkForceMinorUpdate&&!readOnly;
	f.size.value=f.content.value.length+" bytes";
}

config.macros.tidIDE.add=function(id) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	if (f.dirty && !confirm(config.commands.cancelTiddler.warning.format([f.current]))) return;
	var title=prompt(this.titleMsg,config.macros.newTiddler.title);
	while (title && store.tiddlerExists(title) && !confirm(config.messages.overwriteWarning.format([title])))
		title=prompt(this.titleMsg,config.macros.newTiddler.title);
	if (!title || !title.trim().length) return; // cancelled by user
	f.dirty=false; // suppress unneeded confirmation message
	this.set(id,title);
}

config.macros.tidIDE.remove=function(id) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	if (!f.current.length) return;
	if (!store.tiddlerExists(f.current) && store.isShadowTiddler(f.current)) { alert(this.isShadowMsg.format([f.current])); return; }
	if (config.options.chkConfirmDelete && !confirm(config.commands.deleteTiddler.warning.format([f.current]))) return;
	if (store.tiddlerExists(f.current)) {
		story.closeTiddler(f.current);
		store.removeTiddler(f.current);
		store.setDirty(true);
		if(config.options.chkAutoSave) saveChanges();
	}
	f.tiddlers.options[f.tiddlers.selectedIndex]=null; // remove item from list
	f.dirty=false; // suppress unneeded confirmation message
	this.set(id,""); // clear form controls
}

config.macros.tidIDE.save=function(id,saveAs) {
	var place=document.getElementById(id+"_editorpanel"); if (!place) return;
	var f=document.getElementById(id+"_editorform");
	var title=f.current;
	if (!title || !title.trim().length || saveAs) { // get a new title
		title=prompt(this.titleMsg,config.macros.newTiddler.title);
		while (title && store.tiddlerExists(title) && !confirm(config.messages.overwriteWarning.format([title])))
			title=prompt(this.titleMsg,config.macros.newTiddler.title);
		if (!title || !title.trim().length) return; // cancelled by user
		f.tiddlers.options[f.tiddlers.options.length]=new Option(title,title,false,true); // add item to list
		f.current=title;
	}
	var author=config.options.txtUserName;
	var mdate=new Date();
	var content=f.content.value;
	var tags=f.tags.value;
	var tiddler=store.saveTiddler(title,title,content,author,mdate,tags);
	if (f.minoredits.checked) {
		var author=f.author.value;
		var mdate=new Date(f.modified.value);
		var cdate=new Date(f.created.value);
		tiddler.assign(null,null,author,mdate,null,cdate);
	}
	store.setDirty(true);
	if(config.options.chkAutoSave) saveChanges();
	story.refreshTiddler(title,null,true);
	f.dirty=false;
}
//}}}

// // HTML DEFINITIONS
//{{{
config.macros.tidIDE.html = { };
config.macros.tidIDE.html.framework = " \
	<html> %version% <form style='display:inline;margin:0;padding:0;'>%selector%</form> %panels% </html> \
";
//}}}
//{{{
config.macros.tidIDE.html.editorchk = " \
	<input type=checkbox name=editor \
		style='display:inline;width:auto;margin:1px;' \
		title='add/delete/modify tiddlers' %showpanel% \
		onclick='document.getElementById(\"%id%_editorpanel\").style.display=this.checked?\"block\":\"none\";'>%toolname% \
";
config.macros.tidIDE.html.toolschk = " \
	<input type=checkbox name=tools \
		style='display:inline;width:auto;margin:1px;' \
		title='' %showpanel% \
		onclick='document.getElementById(\"%id%_%toolid%_panel\").style.display=this.checked?\"block\":\"none\"; \
			if (this.checked) config.macros.tidIDE.loadPanel(\"%id%\",\"%toolid%\");'>%toolname% \
";
//}}}
//{{{
config.macros.tidIDE.html.toolspanel = " \
	<div id='%id%_%toolid%_panel' style='display:%showpanel%;margin:0;margin-top:0.5em'> \
	</div> \
";
//}}}
//{{{
config.macros.tidIDE.html.editorpanel = " \
	<div id='%id%_editorpanel' style='display:%showpanel%;margin:0;margin-top:0.5em'> \
	<form id='%id%_editorform' style='display:inline;margin:0;padding:0;'> \
	<!-- tiddler editor list and buttons --> \
	<select size=1 name=tiddlers style='display:inline;width:44%;'  \
		onchange='config.macros.tidIDE.set(\"%id%\",this.value); this.value=this.form.current;'> \
	<option value=''>select a tiddler...</option> \
	%tiddlerlist% \
	</select><!-- \
	--><input name=add type=button style='display:inline;width:8%' \
		value='new' title='create a new tiddler' \
		onclick='config.macros.tidIDE.add(\"%id%\")' %disabled%><!-- \
	--><input name=remove type=button style='display:inline;width:8%' \
		value='remove' title='delete this tiddler' \
		onclick='config.macros.tidIDE.remove(\"%id%\")' %disabled%><!-- \
	--><input name=save type=button style='display:inline;width:8%' \
		value='save' title='save changes to this tiddler' \
		onclick='config.macros.tidIDE.save(\"%id%\")' %disabled%><!-- \
	--><input name=saveas type=button style='display:inline;width:8%' \
		value='save as' title='save changes to a new tiddler' \
		onclick='config.macros.tidIDE.save(\"%id%\",true)' %disabled%><!-- \
	--><input name=view type=button style='display:inline;width:8%' \
		value='open' title='open this tiddler for regular viewing' \
		onclick='if (!this.form.current.length) return;	story.displayTiddler(null,this.form.current)'><!-- \
	--><input name=run type=button style='display:inline;width:8%' \
		value='run' title='evaluate this tiddler as a javascript \"systemConfig\" plugin' \
		onclick='if (!confirm(config.macros.tidIDE.evalMsg.format([this.form.current]))) return false; \
			try { window.eval(this.form.content.value); displayMessage(config.macros.tidIDE.evalCompletedMsg); } \
			catch(e) { displayMessage(config.messages.pluginError.format([err])); }'><!-- \
	--><input name=previewbutton type=button style='display:inline;width:8%;' \
		value='preview' title='show \"live\" preview display' \
		onclick='if (!config.macros.preview) { alert(\"Please install PreviewPlugin\"); return false; } \
			this.form.preview.checked=!this.form.preview.checked; \
			document.getElementById(\"%id%_previewpanel\").style.display=this.form.preview.checked?\"block\":\"none\"; \
			if (this.form.freeze) this.form.freeze.checked=!this.form.preview.checked; \
			if (this.form.preview.checked) config.macros.preview.render(this.form.content.id,this.form.content.getAttribute(\"previewid\"));'><!-- \
	hidden field for preview show/hide state: \
	--><input name=preview type=checkbox style='display:none;'>\
	<!-- tiddler content edit --> \
	<div><textarea id='%id%_content' name='content' edit='text' cols=60 rows=%maxrows% \
		style='width:100%;' \
		onkeyup='var f=this.form; f.dirty=true; f.size.value=this.value.length+\" bytes\";'></textarea></div> \
	<!-- tag edit and droplist --> \
	<table width='100%' style='border:0;padding:0;margin:0'><tr style='border:0;padding:0;margin:0'> \
	<td style='border:0;padding:0;margin:0'> \
		<input type=text name=tags size=60 style='width:100%;' value='' \
			onchange='this.form.dirty=true' %disabled%> \
	</td><td width='1' style='border:0;padding:0;margin:0;'> \
		<select size=1 name=taglist \
			onchange='this.form.dirty=true; this.form.tags.value+=\" \"+this.value' %disabled%> \
		<option value=''>select tags...</option> \
		%taglist% \
		</select> \
	</td></tr></table> \
	<!--  created/modified dates, author, current tiddler size --> \
	<div style='float:right;'> \
		created <input type=text name=created size=15 \
			style='display:inline;;text-align:center;padding:0;' value='' \
			onchange='this.form.dirty=true' %minoredits%> \
		modified <input type=text name=modified size=15 \
			style='display:inline;text-align:center;padding:0;' value='' \
			onchange='this.form.dirty=true;' %minoredits%> \
		by <input type=text name=author size=15 \
			style='display:inline;padding:0;' value='' \
			onfocus='this.select()' onchange='this.form.dirty=true' %minoredits%> \
		<input type=text name=size size=10 \
			style='display:inline;text-align:center;padding:0;' value='' \
			onfocus='this.blur()' onkeydown='return false' DISABLED>  \
	</div> \
	<!-- toggles: read-only, minor edit --> \
	<span style='white-space:nowrap'> \
	<input type=checkbox name=readonly \
		style='display:inline;width:auto;margin:1px;' %readonlychk% \
		title='do not allow tiddler changes to be saved' \
		onclick='readOnly=config.options.chkHttpReadOnly=this.checked;saveOptionCookie(\"chkHttpReadOnly\"); \
			var f=this.form; f.minoredits.disabled=f.tags.disabled=f.taglist.disabled=this.checked; \
			f.add.disabled=f.remove.disabled=f.save.disabled=f.saveas.disabled=this.checked; \
			f.created.disabled=f.modified.disabled=f.author.disabled=this.checked||!f.minoredits.checked;'>readonly \
	<input type=checkbox name=minoredits \
		style='display:inline;width:auto;margin:1px;' %disabled% %minorchk% \
		title='check: save datestamps/author as entered, uncheck: auto-update modified/author' \
		onclick='this.form.created.disabled=this.form.modified.disabled=this.form.author.disabled=!this.checked; \
			config.options.chkForceMinorUpdate=this.checked;saveOptionCookie(\"chkForceMinorUpdate\");'>minor edits \
	</span> \
	<!-- tiddler preview display --> \
	<div id='%id%_previewpanel' style='display:none;white-space:nowrap'></div> \
";
//}}}
/***
|Name|TiddlerTweakerPlugin|
|Source|http://www.TiddlyTools.com/#TiddlerTweakerPlugin|
|Version|2.2.3|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|select multiple tiddlers and modify author, created, modified and/or tag values|
~TiddlerTweaker is a tool for TiddlyWiki authors.  It allows you to select multiple tiddlers from a listbox, either by direct interaction or automatically matching specific criteria.  You can then modify the creator, author, created, modified and/or tag values of those tiddlers using a compact set of form fields.  The values you enter into the fields simultantously overwrite the existing values in all tiddlers you have selected.
!!!!!Usage
<<<
{{{<<tiddlerTweaker>>}}}
{{smallform{<<tiddlerTweaker>>}}}
By default, any tags you enter into the TiddlerTweaker will //replace// the existing tags in all the tiddlers you have selected.  However, you can also use TiddlerTweaker to quickly filter specified tags from the selected tiddlers, while leaving any other tags assigned to those tiddlers unchanged:
>Any tag preceded by a "+" (plus) or "-" (minus), will be added or removed from the existing tags //instead of replacing the entire tag definition// of each tiddler (e.g., enter "-excludeLists" to remove that tag from all selected tiddlers.  When using this syntax, care should be taken to ensure that //every// tag is preceded by "+" or "-", to avoid inadvertently overwriting any other existing tags on the selected tiddlers.  (note: the "+" or "-" prefix on each tag value is NOT part of the tag value, and is only used by TiddlerTweaker to control how that tag value is processed)
Important Notes:
* Inasmuch as TiddlerTweaker is a 'power user' tool that can perform 'batch' functions (operating on many tiddlers at once), you should always have a recent backup of your document (or "save changes" just *before* tweaking the tiddlers), just in case you "shoot yourself in the foot".
* By design, TiddlerTweaker does NOT update the 'modified' date of tiddlers simply by making changes to the tiddler's values.  A tiddler's dates are ONLY updated when the corresponding 'created' and/or 'modified' checkboxes are selected and you enter new values for those dates.  As a general rule, after using TiddlerTweaker, always ''//remember to save your document//'' when you are done, even though the tiddler timeline tab may not show any recently modified tiddlers.
* Because you may be changing the values on many tiddlers simultaneously, selecting and updating all tiddlers in a document operation may take a while and your browser might warn about an "unresponsive script"... you should give it a whole bunch of time to 'continue'... it should complete the processing... eventually.
<<<
!!!!!Revisions
<<<
2008.10.27 [2.2.3] in setTiddlers(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
2008.09.07 [2.2.2] added removeCookie() function for compatibility with [[CookieManagerPlugin]]
2008.05.12 [2.2.1] replace built-in backstage "tweak" task with tiddler tweaker control panel (moved from BackstageTweaks)
2008.01.13 [2.2.0] added "auto-selection" links: all, changed, tags, title, text
2007.12.26 [2.1.0] added support for managing 'creator' custom field (see [[CoreTweaks]])
2007.11.01 [2.0.3] added config.options.txtTweakerSortBy for cookie-based persistence of list display order preference setting.
2007.09.28 [2.0.2] in settiddlers() and deltiddlers(), added suspend/resume notification handling (improves performance when operating on multiple tiddlers)
2007.08.03 [2.0.1] added shadow definition for [[TiddlerTweaker]] tiddler for use as parameter references with {{{<<tiddler>>, <<slider>> or <<tabs>>}}} macros.
2007.08.03 [2.0.0] converted from inline script
2006.01.01 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.TiddlerTweakerPlugin= {major: 2, minor: 2, revision: 3, date: new Date(2008,10,27)};

// shadow tiddler
config.shadowTiddlers.TiddlerTweaker="<<tiddlerTweaker>>";

/// backstage task
if (config.tasks) { // for TW2.2b3 or above
	config.tasks.tweak.tooltip="review/modify tiddler internals: dates, authors, tags, etc.";
	config.tasks.tweak.content="{{smallform small groupbox{<<tiddlerTweaker>>}}}";
}

if (config.options.txtTweakerSortBy==undefined) config.options.txtTweakerSortBy="modified";

// if removeCookie() function is not defined by TW core, define it here.
if (window.removeCookie===undefined) {
	window.removeCookie=function(name) {
		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;'; 
	}
}

config.macros.tiddlerTweaker = {
	html: '<form style="display:inline"><!--\
		--><table style="padding:0;margin:0;border:0;width:100%"><tr valign="top" style="padding:0;margin:0;border:0"><!--\
		--><td  style="text-align:center;white-space:nowrap;width:99%;padding:0;margin:0;border:0"><!--\
			--><font size=-2><div style="text-align:left;"><span style="float:right"><!--\
			-->&nbsp; <a href="javascript:;" \
				title="select all tiddlers"\
				onclick="\
				var f=this; while (f&&f.nodeName.toLowerCase()!=\'form\')f=f.parentNode;\
				for (var t=0; t<f.list.options.length; t++)\
					if (f.list.options[t].value.length) f.list.options[t].selected=true;\
				config.macros.tiddlerTweaker.selecttiddlers(f.list);\
				return false">all</a><!--\
			-->&nbsp; <a href="javascript:;" \
				title="select tiddlers that are new/changed since the last file save"\
				onclick="\
				var lastmod=new Date(document.lastModified);\
				var f=this; while (f&&f.nodeName.toLowerCase()!=\'form\')f=f.parentNode;\
				for (var t=0; t<f.list.options.length; t++) {\
					var tid=store.getTiddler(f.list.options[t].value);\
					f.list.options[t].selected=tid&&tid.modified>lastmod;\
				}\
				config.macros.tiddlerTweaker.selecttiddlers(f.list);\
				return false">changed</a><!--\
			-->&nbsp; <a href="javascript:;" \
				title="select tiddlers with at least one matching tag"\
				onclick="\
				var t=prompt(\'Enter space-separated tags (match ONE)\');\
				if (!t||!t.length) return false;\
				var tags=t.readBracketedList();\
				var f=this; while (f&&f.nodeName.toLowerCase()!=\'form\')f=f.parentNode;\
				for (var t=0; t<f.list.options.length; t++) {\
					f.list.options[t].selected=false;\
					var tid=store.getTiddler(f.list.options[t].value);\
					if (tid&&tid.tags.containsAny(tags)) f.list.options[t].selected=true;\
				}\
				config.macros.tiddlerTweaker.selecttiddlers(f.list);\
				return false">tags</a><!--\
			-->&nbsp; <a href="javascript:;" \
				title="select tiddlers whose titles include matching text"\
				onclick="\
				var txt=prompt(\'Enter a title (or portion of a title) to match\');\
				if (!txt||!txt.length) return false;\
				var f=this; while (f&&f.nodeName.toLowerCase()!=\'form\')f=f.parentNode;\
				for (var t=0; t<f.list.options.length; t++) {\
					f.list.options[t].selected=f.list.options[t].value.indexOf(txt)!=-1;\
				}\
				config.macros.tiddlerTweaker.selecttiddlers(f.list);\
				return false">titles</a><!--\
			-->&nbsp; <a href="javascript:;" \
				title="select tiddlers containing matching text"\
				onclick="\
				var txt=prompt(\'Enter tiddler text (content) to match\');\
				if (!txt||!txt.length) return false;\
				var f=this; while (f&&f.nodeName.toLowerCase()!=\'form\')f=f.parentNode;\
				for (var t=0; t<f.list.options.length; t++) {\
					var tt=store.getTiddlerText(f.list.options[t].value,\'\');\
					f.list.options[t].selected=(tt.indexOf(txt)!=-1);\
				}\
				config.macros.tiddlerTweaker.selecttiddlers(f.list);\
				return false">text</a> &nbsp;<!--\
			--></span><span>select tiddlers</span><!--\
			--></div><!--\
			--></font><select multiple name=list size="10" style="width:99.99%" \
				title="use click, shift-click and/or ctrl-click to select multiple tiddler titles" \
				onclick="config.macros.tiddlerTweaker.selecttiddlers(this)" \
				onchange="config.macros.tiddlerTweaker.setfields(this)"><!--\
			--></select><br><!--\
			-->show<input type=text size=1 value="10" \
				onchange="this.form.list.size=this.value; this.form.list.multiple=(this.value>1);"><!--\
			-->by<!--\
			--><select name=sortby size=1 \
				onchange="config.macros.tiddlerTweaker.init(this.form,this.value)"><!--\
			--><option value="title">title</option><!--\
			--><option value="size">size</option><!--\
			--><option value="modified">modified</option><!--\
			--><option value="created">created</option><!--\
			--></select><!--\
			--><input type="button" value="refresh" \
				onclick="config.macros.tiddlerTweaker.init(this.form,this.form.sortby.value)"<!--\
			--> <input type="button" name="stats" disabled value="totals..." \
				onclick="config.macros.tiddlerTweaker.stats(this)"><!--\
		--></td><td style="white-space:nowrap;padding:0;margin:0;border:0;width:1%"><!--\
			--><div style="text-align:left"><font size=-2>&nbsp;modify values</font></div><!--\
			--><table border=0 style="width:100%;padding:0;margin:0;border:0;"><tr style="padding:0;border:0;"><!--\
			--><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=checkbox name=settitle unchecked \
					title="allow changes to tiddler title (rename tiddler)" \
					onclick="this.form.title.disabled=!this.checked">title<!--\
			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=text name=title size=35 style="width:98%" disabled><!--\
			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=checkbox name=setcreator unchecked \
					title="allow changes to tiddler creator" \
					onclick="this.form.creator.disabled=!this.checked">created by<!--\
			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=text name=creator size=35 style="width:98%" disabled><!--\
			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=checkbox name=setwho unchecked \
					title="allow changes to tiddler author" \
					onclick="this.form.who.disabled=!this.checked">modified by<!--\
			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=text name=who size=35 style="width:98%" disabled><!--\
			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=checkbox name=setcdate unchecked \
					title="allow changes to created date" \
					onclick="var f=this.form; f.cm.disabled=f.cd.disabled=f.cy.disabled=f.ch.disabled=f.cn.disabled=!this.checked"><!--\
				-->created on<!--\
			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=text name=cm size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
				--> / <input type=text name=cd size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
				--> / <input type=text name=cy size=4 style="width:3em;padding:0;text-align:center" disabled><!--\
				--> at <input type=text name=ch size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
				--> : <input type=text name=cn size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=checkbox name=setmdate unchecked \
					title="allow changes to modified date" \
					onclick="var f=this.form; f.mm.disabled=f.md.disabled=f.my.disabled=f.mh.disabled=f.mn.disabled=!this.checked"><!--\
				-->modified on<!--\
			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=text name=mm size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
				--> / <input type=text name=md size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
				--> / <input type=text name=my size=4 style="width:3em;padding:0;text-align:center" disabled><!--\
				--> at <input type=text name=mh size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
				--> : <input type=text name=mn size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=checkbox name=settags checked \
					title="allow changes to tiddler tags" \
					onclick="this.form.tags.disabled=!this.checked">tags<!--\
			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
				--><input type=text name=tags size=35 value="" style="width:98%" \
					title="enter new tags or use \'+tag\' and \'-tag\' to add/remove tags from existing tags"><!--\
			--></td></tr></table><!--\
			--><div style="margin-top:.8em;text-align:center"><!--\
			--><nobr><input type=button name=display disabled style="width:32%" value="display tiddlers" \
				onclick="config.macros.tiddlerTweaker.displaytiddlers(this)"><!--\
			--> <input type=button name=del disabled style="width:32%" value="delete tiddlers" \
				onclick="config.macros.tiddlerTweaker.deltiddlers(this)"><!--\
			--> <input type=button name=set disabled style="width:32%" value="update tiddlers" \
				onclick="config.macros.tiddlerTweaker.settiddlers(this)"></nobr><!--\
			--></div><!--\
		--></td></tr></table><!--\
		--></form><span style="display:none"><!--content replaced by tiddler "stats"--></span>\
	',
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var span=createTiddlyElement(place,"span");
		span.innerHTML=this.html;
		this.init(span.firstChild,config.options.txtTweakerSortBy);
	},
	init: function(f,sortby) { // initialize form controls
		if (!f) return; // form might not be rendered yet...
		while (f.list.options[0]) f.list.options[0]=null; // empty current list content
		var tids=store.getTiddlers(sortby);
		if (sortby=="size") // descending order (largest tiddlers listed first)
			tids.sort(function(a,b) {return a.text.length > b.text.length ? -1 : (a.text.length == b.text.length ? 0 : +1);});
		for (i=0; i<tids.length; i++) {
			var label=tids[i].title; var value=tids[i].title;
			if (sortby=="modified" || sortby=="created") {
				label=tids[tids.length-i-1][sortby].formatString("YY.0MM.0DD 0hh:0mm ")+tids[tids.length-i-1].title;
				value=tids[tids.length-i-1].title;
			}
			if (sortby=="size") label="["+tids[i].text.length+"] "+label;
			f.list.options[f.list.length]=new Option(label,value,false,false);
		}
		f.title.value=f.who.value=f.creator.value=f.tags.value="";
		f.cm.value=f.cd.value=f.cy.value=f.ch.value=f.cn.value="";
		f.mm.value=f.md.value=f.my.value=f.mh.value=f.mn.value="";
		f.stats.disabled=f.set.disabled=f.del.disabled=f.display.disabled=true;
		f.settitle.disabled=false;
		config.options.txtTweakerSortBy=sortby; // remember current setting
		f.sortby.value=sortby; // sync droplist selection with current setting
		if (sortby!="modified") // non-default preference... save cookie
			saveOptionCookie("txtTweakerSortBy");
		else removeCookie("txtTweakerSortBy"); // default preference... clear cookie
	},
	selecttiddlers: function(here) { // enable/disable tweaker fields based on number of items selected
		// count how many tiddlers are selected
		var f=here.form; var list=f.list;
		var c=0; for (i=0;i<list.length;i++) if (list.options[i].selected) c++;
		if (c>1) f.title.disabled=true;
		if (c>1) f.settitle.checked=false;
		f.set.disabled=(c==0);
		f.del.disabled=(c==0);
		f.display.disabled=(c==0);
		f.settitle.disabled=(c>1);
		f.stats.disabled=(c==0);
		var msg=(c==0)?'select tiddlers':(c+' tiddler'+(c!=1?'s':'')+' selected');
		here.previousSibling.firstChild.firstChild.nextSibling.innerHTML=msg;
		if (c) clearMessage(); else displayMessage("no tiddlers selected");
	},
	setfields: function(here) { // set tweaker edit fields from first selected tiddler
		var f=here.form;
		if (!here.value.length) {
			f.title.value=f.who.value=f.creator.value=f.tags.value="";
			f.cm.value=f.cd.value=f.cy.value=f.ch.value=f.cn.value="";
			f.mm.value=f.md.value=f.my.value=f.mh.value=f.mn.value="";
			return;
		}
		var tid=store.getTiddler(here.value); if (!tid) return;
		f.title.value=tid.title;
		f.who.value=tid.modifier;
		f.creator.value=tid.fields['creator']||''; // custom field - might not exist
		f.tags.value=tid.tags.join(' ');
		var c=tid.created; var m=tid.modified;
		f.cm.value=c.getMonth()+1;
		f.cd.value=c.getDate();
		f.cy.value=c.getFullYear();
		f.ch.value=c.getHours();
		f.cn.value=c.getMinutes();
		f.mm.value=m.getMonth()+1;
		f.md.value=m.getDate();
		f.my.value=m.getFullYear();
		f.mh.value=m.getHours();
		f.mn.value=m.getMinutes();
	},
	settiddlers: function(here) {
		var f=here.form; var list=f.list;
		var tids=[];
		for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
		if (!tids.length) { alert("please select at least one tiddler"); return; }
		var cdate=new Date(f.cy.value,f.cm.value-1,f.cd.value,f.ch.value,f.cn.value);
		var mdate=new Date(f.my.value,f.mm.value-1,f.md.value,f.mh.value,f.mn.value);
		if (tids.length>1 && !confirm("Are you sure you want to update these tiddlers:\n\n"+tids.join(', '))) return;
		store.suspendNotifications();
		for (t=0;t<tids.length;t++) {
			var tid=store.getTiddler(tids[t]); if (!tid) continue;
			var title=!f.settitle.checked?tid.title:f.title.value;
			var who=!f.setwho.checked?tid.modifier:f.who.value;
			var tags=tid.tags
			if (f.settags.checked) { 
				var intags=f.tags.value.readBracketedList();
				var addtags=[]; var deltags=[]; var reptags=[];
				for (i=0;i<intags.length;i++) {
					if (intags[i].substr(0,1)=='+')
						addtags.push(intags[i].substr(1));
					else if (intags[i].substr(0,1)=='-')
						deltags.push(intags[i].substr(1));
					else
						reptags.push(intags[i]);
				}
				if (reptags.length)
					tags=reptags;
				if (addtags.length)
					tags=new Array().concat(tags,addtags);
				if (deltags.length)
					for (i=0;i<deltags.length;i++)
						{ var pos=tags.indexOf(deltags[i]); if (pos!=-1) tags.splice(pos,1); }
			}
			if (!f.setcdate.checked) cdate=tid.created;
			if (!f.setmdate.checked) mdate=tid.modified;
			store.saveTiddler(tid.title,title,tid.text,who,mdate,tags,tid.fields);
			if (f.setcreator.checked) store.setValue(tid.title,'creator',f.creator.value); // set creator
			if (f.setcdate.checked) tid.assign(null,null,null,null,null,cdate); // set create date
		}
		store.resumeNotifications();
		this.init(f,f.sortby.value);
	},
	displaytiddlers: function(here) {
		var f=here.form; var list=f.list;
		var tids=[];
		for (i=0; i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
		if (!tids.length) { alert("please select at least one tiddler"); return; }
		story.displayTiddlers(story.findContainingTiddler(f),tids)
	},
	deltiddlers: function(here) {
		var f=here.form; var list=f.list;
		var tids=[];
		for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
		if (!tids.length) { alert("please select at least one tiddler"); return; }
		if (!confirm("Are you sure you want to delete these tiddlers:\n\n"+tids.join(', '))) return;
		store.suspendNotifications();
		for (t=0;t<tids.length;t++) {
			var tid=store.getTiddler(tids[t]); if (!tid) continue;
			if (tid.tags.contains("systemConfig"))
				if (!confirm("'"+tid.title+"' is tagged with 'systemConfig'.\n\nRemoving this tiddler may cause unexpected results.  Are you sure?"))
					continue;
			store.removeTiddler(tid.title);
			story.closeTiddler(tid.title);
		}
		store.resumeNotifications();
		this.init(f,f.sortby.value);
	},
	stats: function(here) {
		var f=here.form; var list=f.list; var tids=[]; var out=''; var tot=0;
		var target=f.nextSibling;
		for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
		if (!tids.length) { alert("please select at least one tiddler"); return; }
		for (t=0;t<tids.length;t++) {
			var tid=store.getTiddler(tids[t]); if (!tid) continue;
			out+='[['+tid.title+']] '+tid.text.length+'\n'; tot+=tid.text.length;
		}
		var avg=tot/tids.length;
		out=tot+' bytes in '+tids.length+' selected tiddlers ('+avg+' bytes/tiddler)\n<<<\n'+out+'<<<\n';
		removeChildren(target);
		target.innerHTML="<hr><font size=-2><a href='javascript:;' style='float:right' "
			+"onclick='this.parentNode.parentNode.style.display=\"none\"'>close</a></font>";
		wikify(out,target);
		target.style.display="block";
	}
};
//}}}
!VibrateControllerクラス ([[XNA Game Studio 4.0]] / [[Silverlight 4.0]])

 [[Windows Phone 7]]において、アセンブリ「Microsoft.Devices.dll」を参照することで使えます。

!!サンプル
{{cs{
Microsoft.Devices.VibrateController.Default.Start(TimeSpan.FromSeconds(1.0));
}}}

*参照: http://msdn.microsoft.com/en-us/library/microsoft.devices.vibratecontroller(VS.92).aspx
!Microsoft Visual Studio

 Microsoft Visual Studioは統合開発環境(IDE)です。「Visual Studio 2008」には、以下の製品が含まれます。

*Visual C++
*Visual C#
*Visual Basic .NET
*Visual Web Developer
*MSDNライブラリ

 [[XNA Game Studio]]のプログラミングでは、基本的にプログラミング言語「C#」を利用するため、主にVisual C#を利用します。

!!Visual Studioのバージョンとエディション

*Visual Studio 2008
**Visual Studio 2008 Standard
**Visual Studio 2008 Professional
**Visual Studio 2008 Tools for the Microsoft Office System
**Visual Studio 2008 Team Edition for Software Architects
**Visual Studio 2008 Team Edition for Software Developers
**Visual Studio 2008 Team Edition for Software Testers
**Visual Studio 2008 Team Edition for Database Professionals
**Visual Studio 2008 Team Suite 

*XNA Game Studioのバージョンに対応するVisual Studioのバージョン

 XNA Game StudioはIDEとして、対応バージョンのVisual Studioの各エディションまたは、対応バージョンのVisual C# Expressエディションのいずれかを使います。

|!|!「[[Visual Studio 2010]]」/<br/>「Visual C# 2010 Express」|!「Visual Studio 2008」/<br/>「Visual C# 2008 Express」|!「Visual Studio 2005」/<br/>「Visual C# 2005 Express」|!それ以前のVisual Studio|
|[[XNA Game Studio 4.0]]| ○ | ― | ― | ― |
|[[XNA Game Studio 3.1]]| ― | ○ | ― | ― |
|[[XNA Game Studio 3.0]]| ― | ○ | ― | ― |
|XNA Game Studio 2.0以前| ― | ― | ○ | ― |
http://www.microsoft.com/japan/visualstudio/products/2010/default.mspx
!WindowsでXNAを使うとき

!!64ビットのサポート状況
*.NETは32ビットと64ビットに対応する
*XNAは32ビットのみ対応する
!以上のことによる注意点
*ビルド構成を「Any CPU」にしていると64ビットWindows環境でエラーとなる。
*ビルド構成を「x86」(32ビット)にする必要がある。
http://www.windowsphone7series.com/

 [[Windows Phone 7]]対応のゲームやアプリケーションは、[[Windows Phone Developer Tools]]を使って開発することができます。[[Windows Phone Developer Tools]]には、ゲーム用の[[XNA Game Studio 4.0]]と、一般アプリケーション用の[[Silverlight 4]]が含まれます。

*静電容量式タッチパネル
*4点以上のマルチタッチ

!Windows Phone for Developers | Windows Phone: Developing applications and games for Windows Phone 7 Series
*http://developer.windowsphone.com/windows-phone-7-series/

!Windows Phone Developer Tools [[CTP]]の内容
*Visual Studio 2010 Express for Windows Phone [[CTP]]
*Windows Phone Emulator [[CTP]]
*Silverlight for Windows Phone [[CTP]]
*[[XNA Game Studio 4.0]] [[CTP]]
 XACTは音楽や効果音のAPIです。XACTの代わりにより簡単なSoundEffectクラスも使うことができます。[[Zune]]ではXACTに対応していないので、SoundEffectクラスを使います。
 XNA Game StudioをインストールするとXACTもインストールされます。XACTはオーサリングツールとファイルが同じバージョンでなければなりません。よって、XNA用のファイルを編集するには、XNAに付属しているものを使いましょう。

|!バージョン|!リリース|![[XNA Game Studio]]が対応するバージョン|
|[[XACT3]]|March 2009|[[XNA Game Studio 3.1]]|
|XACT2|August 2007|~[[XNA Game Studio 3.0]]|
 [[XNA Game Studio 3.1]]で、3.1のプロジェクトを作った場合、XACT Project File([[xap形式]])に対応するバージョンは「Microsoft Cross-Platform Audio Creation Tool 3」(XACT3)です。[[XNA Game Studio 3.0]]のプロジェクトでは、XACT2に対応しています。
 3.0のプロジェクトを3.1にアップグレードした場合、.xapは自動的に変換されることはありません。Windowsの「スタート」メニュー→「XNA Game Studio 3.1」→「Tools」→「Microsoft Cross-Platform Audio Creation Tool 3 (XACT3)」を起動して、.xapファイルを開き、保存し直すことでXACT3のファイルになります。
 [[Xbox LIVEインディーズゲーム]]のゲームの更新版のパッケージが再びピアレビューで承認され、配信された場合、すでにユーザーがダウンロードしている以前のゲームを起動した際には、[[Xbox LIVEインディーズゲーム]]の起動画面に続いて、「更新版が公開されています」画面が表示されます。この画面では、次のような文面があります。

!!日本語設定の場合
>更新版が公開されています
>
>このゲームの更新版が公開されています。更新されたゲー
>ムはダウンロード待ちリストに追加され、既存のゲームと
>置き換えられます。更新版をダウンロードできるのは、そ
>のゲームを購入したプロフィールに限られます。
>
>更新しますか?
>
>(B) いいえ、既存のゲームを使用し続けます
>(X) はい、ゲームを更新します

!!英語設定の場合
>Update Available
>
>An update for this game is available on Xbox LIVE. The
>updated game will be added to your download queue and
>replace the existing game. Only profiles that have
>purchased the game can download the update.
>
>Do you want to apply the update?
>
>(B) No, continue to the game
>(X) Yes, update the game

※[[XNA Game Studio 3.1]]対応(2010-06)時点のものです。
※お試し版と完全版のどちらでも表示されます。
*Xbox Development Kit(XDK)

 Xbox Development Kit(XDK)は、商用Xbox 360ゲームタイトル開発キットです。
 [[Xbox LIVEインディーズゲーム]]では利用できない、XNA Game StudioのXDK限定の拡張機能「XNA Game Studio XDK Extensions」もあります。これらについては、ゲームタイトルの区分や、利用できる開発ツールによって、使える機能を区別する必要があります。
[[XNA Game Studioについて]]

 XNA Game Studio 3.0とは、マイクロソフトが提供するゲーム用フレームワークです。対応プラットフォームは、Windowsと[[Xbox 360]]、[[Zune]]です。

!XNA Framework
 XNA FrameworkのAPIには、Direct3D 9.0のシェーダモデル3.0までの3Dや、シェーダ言語のHLSLに対応する機能が含まれています。パフォーマンスに配慮しつつ、C#としてスマートに記述できるAPIになっています。

!プログラミング言語
 通常、開発に使用するプログラミング言語は、C# 3.0です。

!統合開発環境
 Visual C# 2008 Expressエディションまたは、[[Visual Studio]] 2008の各エディションです。Visual C# 2008 Expressは無償で利用でき、商用利用も可能です。

!基盤技術
 .NET
!新機能
*[[アバター]]
**[[アバターのサンプル]]
**[[アバター機能の利用ルール]]
*[[Xbox LIVEパーティ]]
*[[ビデオ再生]]
*[[XACT3]]のサポート
*[[Visual Studio]]での変更内容(3.0と3.1の両方のプロジェクト作成および3.0から3.1へのアップグレード)
*ダウンロードコンテンツ([[XDK]]拡張限定)

!追加の改良
*オーディオAPI(新しい用法の[[SoundEffect.Play]])
*[[コンテンツパイプライン]]の強化
**[[自動XNBシリアライゼーション]]

!![[XNA Game Studio 3.1]]の[[XNA Game Studio 3.0]]への対応について

*[[XNA Game Studio 3.0]]用と[[XNA Game Studio 3.1]]用の両方に対して、プロジェクト作成・ビルドなど一連の操作が可能です。
*[[XNA Game Studio 3.0]]から[[XNA Game Studio 3.1]]へのプロジェクトのアップグレードが可能です。ただし、ダウングレード機能はないので注意しましょう。
*[[Zune HD]]メディアプレイヤーを対象にして開発できる
*Zune HD用にXNA Frameworkへ新たにタッチAPIの追加
**TouchPanelクラス : [[タッチパネル]]
*Zune HD用にXNA Frameworkへ新たに加速度センサーAPIの追加
**Accelerometerクラス : [[加速度計]]

※少なくともこの拡張では、Zune HDの3D機能への対応の追加はないようです。
※XNA Game Studio 4.0 [[CTP]]版時点における制限事項

*「HiDef」は未対応
*[[Windows Phone 7]]の自動回転機能は未対応
*[[Xbox 360]]での実行はできません。XNA Game Studio 4.0 CTP時点で試したところ、配置はできますが、「ゲームを起動できません。」と表示されます。
*[[Windows Phone 7]]において、MediaPlayer.GetVisualizationDataメソッドはサポートされていません。
*ほか

!新機能
*[[Windows Phone 7]]上でのハードウェア・アクセラレーションされた3D API
*[[Visual Studio 2010]]との統合
*[[ダイナミックオーディオ]](Audio APIにバッファされたオーディオのサポートを追加)
*[[マイク入力]]
*BasicEffectクラスに加えて、エフェクトクラスを追加
**SkinnedEffect(スキンモデル用)
**EnvironmentMapEffect(環境マップ用)
**DualTextureEffect(デュアルテクスチャ用)
**AlphaTestEffect(アルファテスト用)
*ほか

!XNA Game Studio 4.0の改良点
*グラフィックス機能のCapsを、2つのプロファイルレベル「Reach(リーチ)」「HiDef(ハイデフ)」にした
**Reach(リーチ): Windows Phone 7を含めてどのプラットフォームでも動く
**HiDef(ハイデフ): Xbox 360とハイエンドWindowsで動く。Reachの全APIが動く
*多くのグラフィックスAPIの改良。API変更あり
*アセンブリ「Microsoft.Xna.Framework.dll」を、利用できるプラットフォームがわかりやすいようにいくつかのアセンブリに分割

![[Windows Phone 7]]のXboxパートナー(managed developer)限定で利用できる機能
*[[ゲーマーサービス]]APIにおいて
**http://msdn.microsoft.com/en-us/library/bb975582(v=XNAGameStudio.40).aspx
**ユーザーのゲーマータグと2Dアバターの読み取り
**プラットフォーム上での実績のロック解除、実績とゲーマースコアの収集
***http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.gamerservices.achievement(v=XNAGameStudio.40).aspx
**非同期ターンベースのゲーム用の通知
**Xbox LIVEランキング(Leaderboard)の閲覧
***http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.gamerservices.leaderboardentry(v=XNAGameStudio.40).aspx

**Xbox LIVEフレンドのフレンドリストへの追加
**スポットライトのフィードへのアクセス

!リリース時期
 2010-03-10時点では、2010-04にプレビュー版リリースとの情報がありました。実際には、2010-03-16に[[Windows Phone Developer Tools]] [[CTP]]の一部として、XNA Game Studio 4.0 [[CTP]]がリリースされました。

※XNA Game Studio 4.0 FAQ: http://creators.xna.com/en-US/article/XNAGameStudio4.0FAQ
※GDC 2010での公表について: http://creators.xna.com/en-US/news/gdc2010

!!APIの変更

 [[XNA Game Studio 4.0]]では、特にグラフィックスAPIのリファクタリングが行われました。将来を見据えDirectX10 APIに基づいて、APIが変更されています。[[XNA Game Studio 4.0]]時点では、DirectX10の機能が使えるわけではなく、引き続きDirectX9の機能が使え、DirectX9で動作します。

|API変更点(一部)|c
|!XNA Game Studio 4.0 CTP|!XNA Game Studio 3.1以前|
|StorageDevice.BeginShowSelector|Guide.BeginShowStorageDeviceSelector|
|StorageDevice.EndShowSelector|Guide.EndShowStorageDeviceSelector|
|GraphicsDevice.BlendState <br>GraphicsDevice.DepthStencilState <br>GraphicsDevice.RasterizerState|GraphicsDevice.RenderState|
|頻繁に変更するために、ステートと二重化されているプロパティ(ステートとの設定順序に注意): <br>GraphicsDevice.BlendFactor <br>GraphicsDevice.MultiSampleMask <br>GraphicsDevice.ReferenceStencil|RenderState.BlendFactor <br>RenderState.MultiSampleMask <br> RenderState.ReferenceStencil|
|BlendState.ColorBlendFunction|RenderState.BlendFunction|
|BlendState.ColorSourceBlend|RenderState.SourceBlend|
|BlendState.ColorDestinationBlend|RenderState.DestinationBlend|
|BlendState.AlphaBlendFunction|RenderState.AlphaBlendOperation|
|BlendState.AlphaSourceBlend|RenderState.AlphaSourceBlend|
|BlendState.AlphaDestinationBlend|RenderState.AlphaDestinationBlend|
|「ソースに1かつデスティネーションに0」か否かで設定可能(BlendState.Opaqueなど)|RenderState.AlphaBlendEnable|
|BlendStateの色とアルファに異なる設定をするか否かで設定可能|RenderState.SeparateAlphaBlendEnabled|
|廃止|Blend.BothSourceAlpha|
|廃止|Blend.BothInverseSourceAlpha|
|廃止|TextureAddressMode.Border|
|廃止|TextureAddressMode.MirrorOnce|
|AlphaTestEffect|アルファ・テスト: <br>RenderState.AlphaFunction <br>RenderState.AlphaTestEnable <br>RenderState.ReferenceAlpha|
|廃止|PrimitiveType.TriangleFan|
|廃止|ポイント・スプライト: <br>RenderState.PointSize <br>RenderState.PointSizeMax <br>RenderState.PointSizeMin <br>RenderState.PointSpriteEnable|
|廃止|低水準シェーダAPI: <br>VertexShader PixelShader|
|廃止|EffectPool <br>StateBlock <br>GammaRamp <br>ClipPlane|
|EffectPass.Apply|Effect.Begin <br>Effect.End <br>Effect.CommitChanges <br>EffectPass.Begin <br>EffectPass.End|
|ModelMeshPart.IndexBuffer|ModelMesh.IndexBuffer|
|ModelMeshPart.VertexBuffer|ModelMesh.VertexBuffer|
|廃止|ModelMeshPart.BaseVertex|
|GraphicsDevice.SetVertexBuffer <br>GraphicsDevice.SetVertexBuffers|VertexStream.SetSource|
|RenderTarget2D|DepthStencilBuffer <br>RenderTarget2D|
|廃止:RenderTarget2DはTexture2D派生クラスになったため、そのままテクスチャとして指定可能|RenderTarget2D.GetTexture|
|VertexBuffer.VertexDeclaration <br>独自の頂点形式を使う場合、頂点宣言(VertexDeclaration)は次のように受け渡されます。IVertexTypeインターフェースを持つ頂点構造体を定義して、これをVertexBufferコンストラクタで指定します。IVertexType.VertexDeclarationプロパティをもとにVertexBufferの頂点宣言が決定されます。GraphicsDevice.SetVertexBufferメソッドやGraphicsDevice.SetVertexBuffersメソッドにて、グラフィックスデバイスはVertexBufferから頂点宣言を受け取ります。|GraphicsDevice.VertexDeclaration|
|廃止(?) / [[CTP]]時点|Texture2D.GetTextureInformation <br>Texture2D.GetCreationParameters|
|Texture2D.FromStream|Texture.FromFile <br>Texture2D.FromFile <br>Texture3D.FromFile <br>TextureCube.FromFile|
|Texture2D.SaveAsGif <br>Texture2D.SaveAsJpeg <br>Texture2D.SaveAsPng|Texture.Save|

*RenderTarget2DをTexture2Dから派生したクラスにし、深度バッファとの統合
*BGRAフォーマットの廃止(Color構造体のバイトの並びがRGBAになった)

*参考: http://blogs.msdn.com/ito/archive/2010/03/24/xna-game-studio-4-0-refactoring.aspx

|追加API(一部)|c
|!XNA Game Studio 4.0 CTP|! |
|Microphone|[[マイク入力]]|
|DynamicSoundEffectInstance|[[ダイナミックオーディオ]]。8KHz~48KHz(モノラル/ステレオ)|

!!!WP7の[[ストレージ]]は、StorageDeviceではなく、System.IO.IsolatedStorage名前空間のAPIを使う
{{cs{
using (var storage = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication()) {
    &#47;&#47; ...
}
}}}

!!!コンテンツプロジェクトの扱い
|!XNA Game Studio 4.0 CTP|!XNA Game Studio 3.1以前|
|参照方式|サブプロジェクト方式|
 [[XNA Game Studio 3.1]]([[XNA Game Studio 3.0]])は、Microsoftのゲーム開発用のフレームワークです。ゲームやアプリーケーションのソフトウェア開発に用いられます。

!開発環境
 通常、OSはWindows Vista / XP (SP2)上で、プログラミング言語にはC# 3.0を用い、統合開発環境(IDE)としてVisual C# 2008 Expressエディションまたは[[Visual Studio]] 2008各エディションを使います。

*対応するIDE
**Visual C# 2008 Express
**Visual Studio 2008 Standard
**Visual Studio 2008 Professional
**Visual Studio 2008 Tools for the Microsoft Office System
**Visual Studio 2008 Team Edition for Software Architects
**Visual Studio 2008 Team Edition for Software Developers
**Visual Studio 2008 Team Edition for Software Testers
**Visual Studio 2008 Team Edition for Database Professionals
**Visual Studio 2008 Team Suite 

 XNA Game Studio 3.1と、Visual C# 2008 Expressエディションは無償で提供されています。また、商用利用も可能です。
 また、学生の方々は、[[DreamSpark]]についても調べてみるとよいでしょう。XNAでも便利なMicrosoftの開発ツールが無償提供されます。

!動作対象プラットフォーム
*Windows Vista / XP (SP2)
**GPU: DirectX 9 シェーダ1.1以上
*[[Xbox 360]]
*[[Zune]] (2Dのみ)

!技術レイヤー
| [[Visual Studio]] 2008 |>|>|
| XNA Framework |>|>|
| .NET Framework | .NET Compact Framework |>|
| [[Windows]] | [[Xbox 360]] | [[Zune]] |

!概要
 XNA Game Studioパッケージユーティリティは、XNAクリエーターズクラブゲームパッケージ(.ccgame形式)のパック(パッケージ化)、アンパックを行うツールです。

 [[Xbox LIVEインディーズゲームにゲームを提出する]]ときなどに使います。

!使い方
 [[Visual Studio]]からは、XNAのプロジェクトのコンテキストメニューにある「XNA クリエーターズ クラブ ゲームとしてパッケージ化」(Package as XNA Creators Club Game)を選択することで、XNAクリエーターズクラブゲームパッケージ(.ccgame形式)として、1つのファイルにまとめることができます。

 「XNA Game Studioコマンド プロンプト」から利用する場合には、「xnapack.exe」です。

![[.ccgameファイルのUnpackについて]]
*[[XNA Game Studio 4.0]]
*[[XNA Game Studio 3.1]]
*[[XNA Game Studio 3.0]]
*[[XNA Game Studio 2.0]]
*[[XNA Game Studio Express 1.0 Refresh]]
*[[XNA Game Studio Express 1.0]]
!XNA関連の主な動向

!!(最近については[[XNAの近況]]にて)
!!2009-09-16
 [[Zune HD]]が米国で発売されたことに合わせて、XNA Game Studio 3.1用のZune HDのタッチパネルと加速度センサーを扱えるようAPI拡張「[[XNA Game Studio 3.1 Zune Extensions]]」が登場しました。
!!2009-08-11
 [[Xbox 360]]の2009年夏のシステムアップデートが一般に配信開始され、日本での[[Xbox LIVEインディーズゲーム]](Xbox LIVE Indie Games)が正式に開始されました。また、[[XNA Game Studio 3.1]]対応のゲームも公開可能になりました。「更新されたゲームの自動配信」も備わり、ゲームの更新版を用意して再び承認された場合、完全版のユーザー全員に対して起動時に更新されたゲームがダウンロードされるようになりました。
!!2009-07-24
 [[XNAクリエーターズクラブ]]オンラインがリニューアルして、日本語に対応しました。日本でのゲームの受付も開始されました。国内では特に大きな一歩といえるでしょう。また、[[Xbox LIVEインディーズゲーム]](Xbox LIVE Indie Games)の新名称に変更されました。[[Xbox LIVEインディーズゲームの設定価格]]が80/240/400MSPに変更されることになり、「評判」「[[ご利用コード]](Token)」のシステムも導入されました。本ページ中の古い情報は、今後更新していきます。(古い情報を含むことにご注意ください)
 [[Xbox LIVEインディーズゲーム]]の[[Xbox LIVEマーケットプレース]]の日本国内開始は、2009年08月11日(現地時間)のXbox 360システムアップデートで開始され、[[XNA Game Studio 3.1]]対応のゲームの公開も一緒に開始されます。2009-07-24以降、[[Xbox LIVEインディーズゲーム]]の[[Xbox LIVEマーケットプレース]]配信が開始されている地域には、[[ピアレビュー]]の承認を得ることで、日本のクリエーターのゲームも実際に配信されています。
!!2009-07-09
 [[XNA Game Studio 3.1]](日本語版)がリリースされました。他の言語のバージョンと共存できないので、これまで英語版を利用していて、日本語版を使う場合には、英語版を先にアンインストールしましょう。
*http://creators.xna.com/en-US/japan/
!!2009-06-12
 [[XNA Game Studio 3.1]](英語版)がリリースされました。さらに、[[Xbox LIVEコミュニティーゲーム]](Xbox LIVE Community Games)が[[Xbox LIVEインディーズゲーム]](Xbox LIVE Indie Games)と改称されることになっています。
 また、日本国内[[Xbox LIVEインディーズゲーム]]開始前までに[[XNA Game Studio 3.1]]日本語版が登場予定です。[[Xbox LIVEインディーズゲーム]]へのゲームのリリースを考えている方は、英語版で開発を進め、日本語版リリース次第、動作を確認するとよいでしょう。
 なお、[[XNA Game Studio 3.1]]対応ゲームの[[Xbox LIVEインディーズゲーム]]での公開は、2009年夏~秋のシステムアップデートを待つ必要があります。それまでピアレビューは受けられますが、公開が保留されます。日本国内の「Xbox LIVEインディーズゲーム」開始当初は[[XNA Game Studio 3.0]]対応ゲームが公開されることになります。

!XNA関連の近況

!!2010-10-22
 「XNA Game Studio 4.0 Language Pack (日本語)」がリリースされました( http://create.msdn.com/ja-JP/home/news/xnags40jpnlangprel )。英語版「XNA Game Studio 4.0」をインストールした後に「XNA Game Studio 4.0 Language Pack (日本語)」をインストールすることで、「XNA Game Studio 4.0」の開発環境を日本語化することができます。ただし、「Windows Phone Developer Tools」は、2010-10-22現在のところ、英語と一部の欧州言語のみに対応しています。そのため、「Windows Phone Developer Tools」の「Visual Studio 2010 Express for Windows Phone」上では、「XNA Game Studio 4.0 Language Pack (日本語)」の効果はありません。その場合でも、独立している「XNA Game Studio 4.0 のヘルプ ドキュメント」「XNA Game Studio デバイス マネージャー」は日本語で利用できます。
!!2010-10-12
 「XNA Creators Club Online」と「Windows Phoneアプリケーション開発」が統合されました。「XNA Creators Clubメンバーシップ」は「App Hubメンバーシップ」になりました。「App Hubメンバーシップ」により、「Windows Phone Marketplace」(審査)および「Xbox Live インディーズゲームカタログ」(ピアレビュー)にアプリケーションを申請できるようになりました。「XNA Creators Club Online」( http://creators.xna.com )は「App Hub」( http://create.msdn.com )に変わりました。
!!2010-09-16
  2010-09-16に、[[XNA Game Studio 4.0]]が単体版として、また[[Windows Phone Developer Tools]]のセットとしてリリースされました。[[Windows Phone 7]]と[[Windows]]については正式版です。[[Xbox 360]]については、配置とデバッグができるようになります。[[Xbox 360]]機能の完全版は2010年内となり、それ以降に[[XNA Game Studio 4.0]]の[[Xbox 360]]ゲームを[[Xbox LIVEインディーズゲーム]]へ提出できるようになります。
!!2010-09-11
  2010-09-16に、[[XNA Game Studio 4.0]]が[[Windows Phone Developer Tools]]の一部としてリリースされる予定です。[[Windows Phone 7]]と[[Windows]]については正式版です。[[Xbox 360]]については、配置とデバッグができるようになります。[[Xbox 360]]機能の完全版は2010年内となり、それ以降に[[XNA Game Studio 4.0]]の[[Xbox 360]]ゲームを[[Xbox LIVEインディーズゲーム]]へ提出できるようになります。
*http://blogs.msdn.com/b/xna/archive/2010/09/08/what-about-xna-game-studio-4-0.aspx
!!2010-07-13
 [[XNA Game Studio 4.0]] Betaが、[[Windows Phone Developer Tools]] Betaの一部として公開されました。
*http://www.microsoft.com/downloads/details.aspx?FamilyID=c8496c2a-54d9-4b11-9491-a1bfaf32f2e3&displaylang=en
!!2010-04-30
 [[XNA Game Studio 4.0]] [[CTP]] April Refreshが、[[Windows Phone Developer Tools]] [[CTP]] April Refreshの一部として公開されました。
*http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=cabcd5ed-7dfc-4731-9d7e-3220603cad14
!!2010-03-16
 [[XNA Game Studio 4.0]] [[CTP]]が、[[Windows Phone Developer Tools]] [[CTP]]の一部として公開されました。
*http://www.microsoft.com/downloads/details.aspx?FamilyId=2338b5d1-79d8-46af-b828-380b0f854203&displaylang=en
!!2010-03-10
 [[XNA Game Studio 4.0]]がGDC 2010で公表されました。対応プラットフォームに[[Windows Phone 7]]が加わります。「[[Windows Phone 7]]上でのハードウェア・アクセラレーションされた3D API」「[[Visual Studio 2010]]との統合」「Audio APIにバッファされたオーディオのサポートを追加」([[ダイナミックオーディオ]])などが新機能です。
!!それ以前
 [[XNAの動向]]
!!Xbox 360の場合の注意点
*開発時にはストレージとして、HDDが必要です。USBメモリのみでは開発できません。
*マーケットプレースからユーザーがダウンロードして遊ぶときには、HDDは必須ではありません。USBメモリやMUのみでも問題なくXBLIGのゲームは動作します。
*公式の案内
http://msdn.microsoft.com/ja-jp/xna/cc627246.aspx

!XNAクリエーターズクラブプレミアムメンバーシップ

 有償のXNAクリエーターズクラブプレミアムメンバーシップは、次のことをする場合に必要です。

*ソースコードやXNAクリエーターズクラブゲームパッケージ(.ccgame形式)からの[[Xbox 360]]版のデバッグや実行
*プレミアムコンテンツへのアクセス
*[[Xbox LIVEインディーズゲーム]]へのゲーム公開

!XNAクリエーターズクラブプレミアムメンバーシップの期間と価格

 以下の2つの選択肢があり、支払方法はクレジットカードです。

| 4ヶ月間のメンバーシップ|&yen;4,800(税込)|
| 12ヶ月間のメンバーシップ|&yen;9,800(税込)|

!XNAクリエーターズクラブオンライン
*http://creators.xna.com/ja-JP/
 一部回答はタイトルの青字をクリックすると開きます。

![[意図しない青紫の画面(レンダーターゲット)が見えた]]

!Xbox 360またはWindowsの片方でのみ描画がおかしい問題が起きた。
!!それはVertexDeclarationに関係しているかもしれない。
 プラットフォームによりデータの並びが違うことが不具合につながります。頂点の構造体で、たとえばボーンインデックスに「byte i0, i1, i2, i3;」のような定義をする代わりに、Microsoft.Xna.PackedVector.Byte4構造体などを使いましょう。これにより、プラットフォーム依存部分をフレームワークの実装によって吸収してくれます。

![[C#コードをマルチプラットフォーム用に書き分けるには?]]

!Windowsで正常なC#コードが、[[Xbox 360用のコンパイルでエラーが起きた]]。
 一部回答はタイトルの青字をクリックすると開きます。

!XNAは何に使える?
 XNA Game Studioは、基本的に[[Windows]]と[[Xbox 360]]および[[Zune]]で動作するゲーム用のフレームワークです([[XNA Game Studio 4.0]]では、[[Windows Phone 7]]が加わります)。プログラミングによって、2Dや3Dのゲームが作成できます。ただし、[[Zune]]のグラフィックスは、2Dのみ対応します。また、3Dデバイスの初期化が自動的に行われるので、Direct3D 9のGPUを使った3Dのプロトタイピングにも便利です。デバイスの初期化はカスタマイズもできます。応用になりますが、[[Windows]]についてはWindows.Formsなどを組み合わせれば、3D対応の.NETアプリケーションを構築可能です。

!XNAでの開発はどのバージョンで始めればいい?
 できれば最新に近い方がよいでしょう。たとえば、[[XNA Game Studio 2.0]]では、[[Visual Studio]] 2005のいずれかのエディションが必要ですが、無償のVisual C# 2005 Expressの配布が終了しています。[[XNA Game Studio 3.0]]では、[[Visual Studio]] 2008のいずれかのエディションが必要です。無償のVisual C# 2008 Expressも利用できます。このように、状況は変化を続けています。XNA Game Studio 2.0用のサンプルなどは、XNA Game Studio 3.0をインストールしたVisual Studio 2008からプロジェクトを開くことで変換できます。
 また、[[Xbox LIVEインディーズゲーム]]に対応するには、[[XNA Game Studio 3.0]]以降を使う必要があります。

!Windowsでの実行だけに興味があるときには?
 もし、[[Windows]]だけで動けばよい場合には、XNAフレームワーク以外の[[Windows]]専用の外部ライブラリ(.NETアセンブリやネイティブDLL)を組み合わせて開発しても構いません。ただし、後から[[Xbox 360]]にさせたくなっても、対応していないものを組み合わせた場合には、その部分を置き換える必要が出てくるということを考えておくとよいでしょう。

!C++などでプログラミングできるか?
 特別な事情がなく、プログラミング言語の学習よりもゲーム制作が主目的であれば、XNAの説明で通常使われるC#を使う方が無難です。
 ただし、[[Windows]]だけを動作環境にするのであれば、C++を組み合わせることはできます。XNAフレームワークが.NETのクラスライブラリで提供されるため、C++/CLIで結合させることになるでしょう。
 一方で、XNAのプログラムをXbox 360で動作させるには、完全にマネージドコードになる必要があります。その条件を満たせば、C++/CLIやその他の.NET言語を使うことはできます。

!3Dグラフィックスを表示するには?
 Direct3D 9に対応しています。3Dポリゴン描画や、[[HLSL]]でエフェクト(頂点シェーダ、ピクセルシェーダ)が扱えます。GraphicsDeviceクラスを使って、デバイスレベルで制御できます。簡単な3Dモデル描画にはModelクラスが便利です。

!スプライト(2D画像)を表示するには?
 基本的なものはSpriteBatchクラスを使うと簡単です。[[Windows]]や[[Xbox 360]]では、これもまた3Dポリゴンで処理されます。

!文字を表示するには?
 2Dの文字は、XNAの[[コンテンツパイプライン]]を使って、コンパイルするWindowsにインストールされた指定フォントの指定文字を事前に画像にしておき、SpriteFontクラスによって描画できます。残念ながら実行中にフォントデータそのものを扱うXNAのAPIはありません。

→[[文字描画]]

!音楽を鳴らすには?
 [[XACT]]またはSoundEffectクラスを使って再生できます。ユーザーがそのマシン([[Windows]]や[[Xbox 360]])に置いた音楽を再生するAPI(Microsoft.Xna.Framework.Media名前空間)もあります。

!MIDIは鳴らせますか?
 残念ながらXNAのAPIにはありません。演奏を別途wav形式などにして、[[XACT]]またはSoundEffectクラスを使って再生することはできます。または、[[XNA Game Studio 4.0]]以降の[[ダイナミックオーディオ]]を使って、原理的にはソフトウェアシンセサイザから実装すれば可能です。

!効果音を鳴らすには?
 [[XACT]]またはSoundEffectクラスを使って再生できます。

!動的生成した波形を鳴らせますか?
 [[XNA Game Studio 4.0]]以降の[[ダイナミックオーディオ]]で可能です。

!動画を再生するには?
 [[XNA Game Studio 3.1]]以降のVideoクラスとVideoPlayerクラスを使って[[ビデオ再生]]できます。

!ゲームの状態をセーブ・ロードするには?
 [[Windows]]、[[Xbox 360]]、[[Zune]]では、StorageContainerクラス(Microsoft.Xna.Framework.Storage名前空間)を使うことでできます。処理内容は書く必要があります。[[Windows Phone 7]]では、System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplicationメソッドを使います。
|!リリース時期|!名称|!ファイル名|!ファイルサイズ(Bytes)|! ファイル(※古いものは公開終了しています)|
|2010-10-21|XNA Game Studio 4.0 Language Pack (日本語)|xnalangpack.ja-JP.msi| 11,136,000|http://www.microsoft.com/downloads/details.aspx?FamilyID=b3929d3b-3fe1-49dd-9cb1-c701b88d049d&displayLang=ja|
|2010-09-16|XNA Game Studio 4.0|xnags40_setup.exe| 51,182,360|http://go.microsoft.com/fwlink/?LinkId=197288|
|2010-09-16|Windows Phone Developer Tools (XNA ame Studio 4.0を含む)|wm_web.exe ※ウェブインストーラ| 3,375,944|http://download.microsoft.com/download/1/7/7/177D6AF8-17FA-40E7-AB53-00B7CED31729/vm_web.exe|
|2010-04-29|Windows Phone Developer Tools CTP April Refresh (XNA Game Studio 4.0 CTP April Refreshを含む) (2010 April) |wm_web.exe ※ウェブインストーラ| 3,331,400|http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=cabcd5ed-7dfc-4731-9d7e-3220603cad14|
|2010-03-15|Windows Phone Developer Tools CTP (XNA Game Studio 4.0 CTPを含む) (2010 March) |wm_web.exe  ※ウェブインストーラ| 3,342,664|http://www.microsoft.com/downloads/details.aspx?FamilyId=2338b5d1-79d8-46af-b828-380b0f854203&displaylang=en|
|2009-09-15|XNA Game Studio 3.1 Zune Extensions(英語版)|zuneextensions.msi| 11,550,208|http://www.microsoft.com/downloads/details.aspx?FamilyID=48f7ba37-8ba7-4d16-8873-0b7f83ef77f9&displaylang=en|
|2009-07-09|XNA Game Studio 3.1(日本語版)|XNAGS31_setup.exe| 79,185,752|http://www.microsoft.com/downloads/details.aspx?FamilyID=80782277-d584-42d2-8024-893fcd9d3e82&displaylang=ja|
|2009-07-09|XNA Framework Redistributable 3.1(日本語版)|xnafx31_redist.msi| 7,715,328|http://www.microsoft.com/downloads/details.aspx?FamilyID=53867a2a-e249-4560-8011-98eb3e799ef2&displaylang=ja|
|2009-06-11|XNA Game Studio 3.1(英語版)|XNAGS31_setup.exe| 76,729,704|http://www.microsoft.com/downloads/details.aspx?FamilyID=80782277-d584-42d2-8024-893fcd9d3e82&displaylang=en|
|2009-06-11|XNA Framework Redistributable 3.1(英語版)|xnafx31_redist.msi| 7,671,808|http://www.microsoft.com/downloads/details.aspx?familyid=53867A2A-E249-4560-8011-98EB3E799EF2&displaylang=en|
|2009-01-30|Microsoft XNA Game Studio 3.0 ドキュメント - 日本語|xnags30_docs_ja.msi| 18,539,008|http://www.microsoft.com/downloads/details.aspx?familyid=73D6A0E5-7928-4863-9F7E-16CEAE75205B&displaylang=ja|
|2008-10-30|XNA Game Studio 3.0        |XNAGS30_setup.exe| 65,521,504|http://www.microsoft.com/downloads/details.aspx?FamilyId=7D70D6ED-1EDD-4852-9883-9A33C0AD8FEE&displaylang=en|
|2008-09-17|XNA Game Studio 3.0 Beta|XNAGS30_setup.exe| 47,799,832|http://www.microsoft.com/downloads/details.aspx?FamilyID=63f74eeb-02ef-4339-9dcb-0cb58362bd7c&displaylang=en|
|2008-05-07|XNA Game Studio 3.0 CTP|XNAGS30_setup.exe| 43,771,928|http://www.microsoft.com/downloads/details.aspx?FamilyID=df4af56a-58a7-474c-bfd0-7cf8ed3036a3&displaylang=en|
|2008-04-28|XNA Game Studio 2.0 ヘルプドキュメント - 日本語|xnags20_docs_ja.msi| 12,094,976|http://www.microsoft.com/downloads/details.aspx?FamilyID=B616E16C-9C7D-4B2D-AE54-BAF489B5B835&displaylang=ja|
|2007-12-13|XNA Game Studio 2.0       |XNAGS20_setup.exe| 103,407,264|http://www.microsoft.com/downloads/details.aspx?FamilyId=DF80D533-BA87-40B4-ABE2-1EF12EA506B7&displaylang=en|
|2007-11-20|XNA Game Studio 2.0 Beta|XNAGS20_setup.exe| 103,453,688||
|2007-04-24|XNA Game Studio Express 1.0 Refresh|xnagse_setup.msi| 86,300,672|http://www.microsoft.com/downloads/details.aspx?FamilyID=12adcd12-7a7b-4413-a0af-ff87242a78de&DisplayLang=en|
|2006-12   |XNA Game Studio Express 1.0|xnagse_setup.msi| 85,048,320| |
|2006      |XNA Game Studio Express 1.0 Beta|xnagse_setup.msi| 83,256,832| |

[[App Hub|http://create.msdn.com/]]←リダイレクト← [[XNA Creators Club Online|http://creators.xna.com/]]
[[XNA デベロッパー センター|http://www.microsoft.com/japan/msdn/xna/default.aspx]]
[[XNA Creators Clubの概要(日本語)|http://www.microsoft.com/japan/msdn/xna/XNA_creators_club.aspx]]
?←[[XNA Game Studio 3.1 日本語版の公開に関するご案内|http://creators.xna.com/en-US/japan/]]←リダイレクト←[[xna (xna-studio.jp)|http://xna-studio.jp/]]

!公式ブログ
[[ひにけにXNA|http://blogs.msdn.com/ito/default.aspx]]
[[XNA Japan Team Blog|http://blogs.msdn.com/xnajapan/]]

!公式フォーラム
!!新
[[日本語フォーラム - XNA Community Forums|http://forums.xna.com/forums/default.aspx?GroupID=16]]
!!旧(2009-08-25以降、閲覧のみ)
[[XNA Game Studio Express フォーラム|http://social.msdn.microsoft.com/Forums/ja-JP/xnagameja/threads/]] (旧: [[XNA Game Studio Express - MSDNフォーラム|http://forums.microsoft.com/MSDN-JA/ShowForum.aspx?ForumID=1326&SiteID=7|]])
[[XNA Framework フォーラム|http://social.msdn.microsoft.com/forums/ja-JP/xnafxja/threads/]] (旧: [[XNA Framework - MSDNフォーラム|http://forums.microsoft.com/MSDN-JA/ShowForum.aspx?ForumID=1327&SiteID=7]])

!XNAヘルプドキュメント
[[Microsoft XNA Game Studio 3.0 ドキュメント - 日本語|http://www.microsoft.com/downloads/details.aspx?familyid=73D6A0E5-7928-4863-9F7E-16CEAE75205B&displaylang=ja]]
[[Microsoft XNA Game Studio 2.0 ヘルプ ドキュメント - 日本語|http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=b616e16c-9c7d-4b2d-ae54-baf489b5b835]]

!MSDNライブラリ(日本語オンラインドキュメント)
[[XNA Game Studio 3.1|http://msdn.microsoft.com/ja-jp/library/bb200104.aspx]]
[[XNA Game Studio 3.0 ドキュメント (日本語)|http://msdn.microsoft.com/ja-jp/library/bb200104(XNAGameStudio.30).aspx]]
[[XNA Game Studio 2.0 ドキュメント (日本語)|http://msdn.microsoft.com/ja-jp/library/bb200104(XNAGameStudio.20).aspx]]

!オープンソースのXNA関連プロジェクト
[[CodePlex内のキーワード「XNA」を検索|http://www.codeplex.com/site/search?projectSearchText=XNA]]
 家庭用ゲーム機「Xbox 360」です。

!CPU
|!命令セット|Power PC|
|!コア数| 3|
|!ハードウェアスレッド数| 6 (スレッド0~5)|

!XNA + Xbox 360における条件
|!CLR/Frameworkが予約するスレッド([[Xbox 360のスレッド]])|スレッド0とスレッド2|
|!ストレージ上限サイズ| 52MB|
|!プロジェクト(ファイル全体)上限サイズ| 2GB ([[Xbox LIVEインディーズゲーム]]の配信上限サイズとは別)|

!GPU
|!GPU|ATI 500MHz 48ALUs|
*レンダーターゲットに使えるのは、10MBのEDRAM。これが不足するような場合、XNAでは自動的に[[プレディケートタイリング]]が行われる
*全512MBのシステムメモリに直接アクセス可能
*シェーダモデル3.0
**Xbox 360用の拡張あり
***Vertex Fetch (vFetch)対応
***vFetchと組み合わせる、INDEXセマンティクス
***ポイントスプライトを使うにはSPRITETEXCOORDセマンティクスを使う必要がある
***Xbox 360では、エフェクトファイルのプロファイル指定に関係なく、シェーダプロファイル3.0でコンパイルされることに注意が必要
**Vertex Texture Fetch (VTF)対応
**Multi Render Target (MRT)対応
**OcclusionQuery対応。Windowsと挙動が違うので、動作を共通にするには注意が必要
*Xbox 360で非対応なAPI(~[[XNA Game Studio 3.1]])
**代案がvFetchになるもの
***VertexStream.SetFrequencyメソッド
***VertexStream.SetFrequencyOfIndexDataメソッド
***VertexStream.SetFrequencyOfInstanceDataメソッド
**代案がContentManager.Load<T>メソッドになるもの
***Texture2D.FromFileメソッド
***Texture3D.FromFileメソッド
***TextureCube.FromFileメソッド
**代案がContentManager.Load<Effect>メソッドになるもの。または対応できないもの
***ShaderCompiler.AssembleFromFileメソッド
***ShaderCompiler.AssembleFromSourceメソッド
***ShaderCompiler.CompileFromFileメソッド
***ShaderCompiler.CompileFromSourceメソッド
***ShaderCompiler.Disassembleメソッド
 [[Xbox 360]]のコアは3つ、ハードウェアスレッドは合計6つあり、スレッド0とスレッド2はCLRとXNA Frameworkに予約されています。
|!コア|>| 0 |>| 1 |>| 2 |
|!ハードウェアスレッド| 0 | 1 | 2 | 3 | 4 | 5 |
|!CLR/Frameworkの予約| ● | ― | ● | ― | ― | ― |

 Xbox 360において、System.Threading.Thread.SetProcessorAffinityメソッドで設定できます。引数には1つのハードウェアスレッドを指定します。ただし、XNA Frameworkに予約されているハードウェアスレッド0と2は、使用できません。また、ThreadPoolクラス、Timerクラスで作ったスレッドでは使えません。


 Windows用で正常なC#コードが、[[Xbox 360]]用のC#コンパイルでエラーを起こすような場合があります。マルチプラットフォーム対応にする場合には、予めこの制限事項を踏まえた上で開発するとよいでしょう。

 次のコードは、Xbox用のコンパイルでエラーになります。
{{{
void Function(out Vector4 result) {
    result.X = 0;
    result.Y = 1;
    result.Z = 2;
    result.W = 3;
}
}}}

 代わりに、次のようにします。
{{{
void Function(out Vector4 result) {
    result = new Vector4();
    result.X = 0;
    result.Y = 1;
    result.Z = 2;
    result.W = 3;
}
}}}
または、
{{{
void Function(out Vector4 result) {
    result = new Vector4(0, 1, 2, 3);
}
}}}
※Xbox LIVEインディーズゲーム(Xbox LIVE Indie Games)は、当初、Xbox LIVEコミュニティーゲーム(Xbox LIVE Community Games)という名称でした。そのため、一部ではこの旧表記が見られます。

!2009年07月24日現在のサービス中の地域
|!地域|!英語表記|!クリエーターがゲームを提出可能|!消費者がゲームをダウンロード可能|
|日本|Japan| ○(2009-07-24) | ○(2009-08-12予定) |
|米国|United States| ○ | ○ |
|カナダ|Canada| ○ | ○ |
|イギリス|United Kingdom| ○ | ○ |
|フランス|France| ○ | ○ |
|スペイン|Spain| ○ | ○ |
|イタリア|Italy| ○ | ○ |
|スウェーデン|Sweden| ○ | + |
|シンガポール|Singapore| ○ | + |
|ドイツ|Germany | ○(2009-07-24) | + |
|ノルウェー|Norway| ○ | ― |
|オランダ|Netherlands| ○ | ― |
|デンマーク|Denmark| ○ | ― |
|アイルランド|Ireland| ○ | ― |
|ニュージーランド|New Zealand| ○ | ― |
|オーストラリア|Australia| ○ | ― |

「+」: (2009-07-24に追加されたもの。2009-08-12予定?)

!日本国内のサービス開始予定2009-07中旬に決まったことに関する情報
*http://creators.xna.com/en-US/japan/
*http://www.inside-games.jp/news/348/34872.html
*http://jp.joystiq.com/2009/04/21/xbox-live/
!概要
 [[Xbox LIVEインディーズゲーム]]は、[[XNA Game Studio 3.0]]以降で作ったゲームを有償のゲームとして配布することができる仕組みです。サービスは地域ごとに分かれていて、日本国内では、2009年7月中旬にサービス開始予定です。
 公開には、[[XNAクリエーターズクラブ]]プレミアムメンバーシップになった上で、ユーザー同士による[[ピアレビュー]]を通過する必要があります。これを通過することで、アマチュアかプロフェッショナルかを問わず、自作のゲームを公開できます。

 一般の[[Xbox 360]]ユーザーの目に触れることができる[[マーケットプレース]]の[[インディーズゲーム]]に並びます。[[マーケットプレース]]は[[Xbox 360]]本体のほか、PCなどを使って、ウェブブラウザからも閲覧可能です。日本国内サービス開始以降、国内用の[[インディーズゲーム]]も追加されるものと考えられます。
 ユーザーは[[インディーズゲーム]]のゲームはすべて[[お試し版]]で遊ぶことができ、気に入ったら[[マイクロソフトポイント]](MSP)で購入して完全版を遊ぶことができます。[[Xbox LIVEインディーズゲームの設定価格]]は、3段階のMSPで設定します。

 [[お試し版]]はプログラムで判定して処理を分けることができますが、XNAフレームワーク側により一定時間で終了します。
 なお、ゲームに問題があった場合、公開後でもマイクロソフトによって停止されることがあります。

 また、作ったゲームの著作権と知的財産は作者側が保有したままです。

!インディーズゲームの4つのステップ
|![[作る|Xbox LIVEインディーズゲーム用にゲームを作る]]|→|![[提出|Xbox LIVEインディーズゲームにゲームを提出する]]|→|![[ピアレビュー]]|→|![[プレイ|Xbox LIVEインディーズゲームのゲームをプレイする]]|
|!Create|~|!Submit|~|!Peer Review|~|!Play|
|ゲームを作る|~|ゲームを提出する|~|インディーズゲームレビュー|~|ダウンロードとプレイ|
| |~|要プレミアムメンバーシップ|~|要プレミアムメンバーシップ|~| |

!!禁止されているコンテンツへの対策

!!!ビアレビュー
 配信には、クリエーター同士のピアレビューによる承認が必要です。

!!!ペアレンタルコントロール
 Xbox LIVEインディーズゲームで配信されるゲームは無審査扱いのため、最高レベルのペアレンタルコントロールの制限を受けます。そのため、ペアレンタルコントロールが有効なXbox 360で遊ぶことはできません。

!!!Microsoftによる事後チェック機構

|ユーザーからの苦情報告|→|チェック|→|配信停止・ダウンロード済みゲームの無効化・返金|
 プレミアムメンバーは、[[XNAクリエーターズクラブ]]のウェブを通じて、自作ゲームを提出することができます。

(この項目の一部は日本国内サービス開始以前の情報に基づいています。)

!!ゲームプロジェクトを追加する

 この操作には、次の条件を満たす必要があります。

*18歳以上
*プレミアムメンバー
*受付している地域

 プロジェクトは8つまでです。

※プロジェクト数の上限は変更可能なシステムとなっており、状況を見て対応ができるそうです。

!!!ゲームの名称

 ゲームの名称(タイトル)は次の条件を満たす必要があります。

*2文字~30文字
*文字(句読点や記号ではない)で始まること
*全年齢対象であって、不快な内容や禁止されている内容を含まないこと
*サポートされている言語であること
*Xbox 360 本体で表示不可能な文字を含まないこと

!!ゲームをアップロードする(ゲームリリースを追加する)

!!!一般情報(General Information)
!!!!ゲームのジャンル

|!gr (※1)|!g (※2)|!ジャンル (日本語) |!Genre (英語)|
| -1| -1|(すべて)|(All)|
|  1| 3002|アクション & アドベンチャー|Action & Adventure|
|  2| 3018|テーブル ゲーム|Card & Board|
|  3| 3019|懐かしのゲーム|Classics|
|   4| 3020|エデュテイメント|Educational|
|  5| 3005|ファミリー|Family|
|  6| 3006|格闘|Fighting|
|  7| 3007|音楽|Music|
|  8| 3001|その他|Other|
|  9| 3008|キャラクター アクション|Platformer|
| 10| 3022|パズル & 雑学クイズ|Puzzle & Trivia|
| 11| 3009|レース & フライト|Racing & Flying|
| 12| 3010|RPG|Role Playing|
| 13| 3011|シューティング|Shooter|
| 14| 3013|スポーツ & レクリエーション|Sports & Recreation|
| 15| 3012|戦略 & シミュレーション|Strategy & Simulation|

※1: catalog.xna.comのジャンルパラメータ
※2: marketplace.xbox.comのジャンルパラメータ

!!!!ゲームの基本機能
!!!!最大HDTV出力形式
!!!!カスタムサウンドドラック
!!!!Xbox LIVE対応機能
!!!!追加の機能

!!!ゲームの説明(Game Descriptions)
 ゲームをダウンロードやプレイする誰もが見られる説明です。説明文は少なくとも1つ必須で、ゲームがサポートしている各言語に翻訳したものを追加することもできます。
 また、既定の言語を決めるラジオボタンがあります。ここでの「既定」とは、対応していない言語に設定された[[Xbox 360]]本体で見たときに表示されるゲームの説明の言語を決めるために使われる設定のことです。複数の言語の説明を用意する場合には、どの言語が既定となるべきか注意して設定しましょう。

!!!表現項目のレベル設定(Classification)

 ゲームに含まれる表現項目をクリエーター自身で認定することができます。正確に表現項目のレベル設定をすることが非常に重要です。これを見て、他の人はゲームをレビューしたり、レーティングを検証したりします。それらの評価によって、ゲームは承認または差し戻されます。スライダーにカーソルを合わせることで各カテゴリの意味を確認できます。ゲームの内容に基づいてスライダーを設定しましょう。

 数字には0~3の4段階あり、それぞれに具体的な意味があります。項目は次の通りです。

|!暴力的な表現(日本語)|!Violence(英語)|!V|
|出血表現|blood|0~3|
|残虐表現|cruelty|0~3|
|殺傷表現|injuries|0~3|
|!性的な表現|!Sex|!S|
|部分的な裸体表現|partial nudity|0~3|
|全般的な性的表現|sexual overtones|0~3|
|!成人向けの表現|!Mature Content|!M|
|犯罪|crime|0~3|
|不安や恐怖|fear/horror|0~3|
|ギャンブル|gambling|0~3|
|過激な言葉遣い|offensive language|0~3|
|麻薬等薬物の使用|substance use|0~3|

!!!メディア
 ゲームを表す画像が必須です。トレイラー動画を加えることができます。

!!ゲームを送信する

 「プレイテストとピアレビューのページ」では、XNAクリエーターズクラブゲームパッケージ(.ccgame形式)を選んでアップロードし、プレイテストまたはピアレビューに提出します。

!!!ゲームの情報
 前のページで入力したすべての情報です。「ゲームの情報を編集」をクリックすると、ゲームの情報を編集できます。

!!!ゲームのパッケージ
*「ゲームパッケージ」の項目から「新しいゲームのパッケージのアップロード」をクリックします。
*「ゲームのパッケージをアップロード」画面で、パッケージを指定し、対応言語を選択します。
*「アップロード」をクリックして、アップロードします。

!!!ゲームの希望小売価格
*[[Xbox LIVEインディーズゲームの設定価格]]
*ひとたゲームの価格を設定して、ピアレビューを通過すると、価格は変更できなくなるので、慎重に検討して決定しましょう。また、リリース後に、90日に1度変更が可能です。

!!!配信地域
 ゲームが購入できる地域のリストがあります。ひとたび地域のサポートを決めると、タイトルの将来のリリースは自動的にそれらの地域に公開されます。また、新たな地域を追加することもできます。追加の地域へのリリースを追加すると、それらの地域でピアレビューができるようになります。

!!!フォーラムのコメント
 コミュニティーに表示させたいゲームについて「説明」「コメント」「操作方法」などを入力できるテキストボックスがあります。ゲームを提出したときには、フォーラムにこのゲーム専用のスレッドが自動的に作成され、このメッセージが投稿されます。

!!レビューのためのパッケージを提出する

!!!プレイテスト/ピアレビュー
 ゲームを「プレイテスト」または「ピアレビュー」(リリース)のどちらで提出するかを選択します。

 プレイテストとして提出すると、ゲームは1週間の期間、XNAクリエーターズクラブオンラインのプレミアムメンバーによって、XNA クリエーターズクラブオンラインのウェブサイト上でダウンロードできるようになります。プレイテストを終えた後に、ゲームは再提出できます。

 ピアレビュー(リリース)として提出すると、ゲームはピアレビューの行程に入ります。ピアレビューを通過したならば、[[Xbox LIVEマーケットプレース]]にて購入できるようになります。

----
 ひとたびレビューにゲームが提出されると、レビューの行程が完了するまで変更できません。そのため、この選択をする前に全ての情報が正しいことを確かめましょう。

 ゲームは提出からすぐにレビューに入ります。他のクリエーターがゲームに気付いて、レビューが始まります。これ以降には、2つの可能性があります。

*ゲームに「分類が正確」「不適切なコンテンツがない」「不具合がない」、ゲームの「詳細」と「メディア」が誠実であると確認される。ゲームは承認される。
*「不具合」「不適切なコンテンツ」、「ゲームと提供したメディアまたは詳細が不一致」または「提供した分類とピアレビューする人が見つけた分類が不一致」と認定される。ゲームは差し戻される。

 ゲームが承認されると、[[Xbox LIVEマーケットプレース]]に現れます。差し戻されると、分類を編集し、新しいパッケージを提出し、再挑戦できます。ゲームのステータスが変わると、Eメールで通知されます。ゲームがレビューされるのを待つ間、他の人が作ったゲームのレビューに挑戦しましょう。

 「送信」をクリックすると、ゲームをプレイテストまたはピアレビューとして提出が完了します。

※ゲームのアップデート(更新版)は、前回のピアレビューが終わってから7日後に提出することができます。
※ピアレビューでゲームが差し戻された場合や、自分で取り下げた場合、次にピアレビューに提出できるのは、提出したゲームのピアレビューが終了してから7日後以降です。

!!販促素材
 上記の提出で必要な販促素材は次の通りです。画像は解像度が完全に一致しないとなりません。

|!タイトル|2~30文字|
|!説明|1~400文字(最低1言語)。複数の言語へ翻訳したものを追加できる|
|!サムネイル|64x64ピクセル(JPGのみ/16KB以内)1点|
|!パッケージの画像|584x700ピクセル(JPGのみ/390KB以内)1点 ※[[パッケージの画像のデザインについて|ボックスアートのデザインについて]]|
|!スクリーンショット|1000x562ピクセル(JPGのみ/150KB以内)1~4点|
|!ビデオ|YouTubeに投稿したゲームプレイ(またはゲームのマーケティング)のビデオのURL。※当初は、MSN Videoのユーザービデオ投稿サービス「Soapbox」に対応していました。|

!!Xbox LIVEマーケットプレース上のゲームの説明に表示される書式について

 Xbox LIVEマーケットプレースでの日本語の場合のゲームの説明は、次のような書式になります。「''?''」には「表現項目のレベル設定」の数字が入り、「''ゲームの説明''」部分にはクリエーターによる「ゲームの説明」の文が入ります。

----
|このゲームに含まれる各種表現のレベルは、コミュニティーによって次のように設定されています。 - 暴力的な表現 = ''?''/3、 性的な表現 = ''?''/3、 成人向けの表現 = ''?''/3 ''ゲームの説明''|
----
 ゲームが一定のピアレビューの数を通過し、承認(Approved)されると、48時間以内に[[Xbox LIVEマーケットプレース]]から購入できるようなります。

 [[Xbox LIVEマーケットプレース]]で見つけたゲームは購入することでダウンロードできます。また、購入前に試したいならば、[[お試し版]]も利用できます。
 なお、ゲームはxbox.comから直接購入することもでき、関連付けられたXbox LIVEアカウントにサインインしたときに[[Xbox 360]]本体にダウンロードされます。

(この内容は、すでに開始されている地域に基づいています)
 [[Xbox LIVEインディーズゲーム]]では、[[マイクロソフトポイント]](MSP)で3段階から価格設定を選択できます。

!!2009-07-24以降の価格設定

|! |! 低|! 中|! 高|
|!MSP| 80| 240| 400|
|!US$相当| 1.00| 3.00| 5.00|
|!<html>&yen;</html>相当| 120| 360| 600|
|!ファイルサイズ上限|	 50MB| 150MB| 150MB|

※90日に一度価格を変更することもできます。

 MSPの設定によってXNAクリエーターズクラブゲームパッケージ(.ccgame形式)のファイルサイズに上限があります。価格表示はMSPから割引なしの換算値です。

 なお、Xbox LIVEインディーズゲームにおいて、現在のところゲームの無償配布の仕組みはありません。無料でプレイできる[[お試し版]]の限られた時間で、何かを伝えることはできるかも知れません。

!!2009-07-24以前の価格設定

 日本での開始以前には、次の3段階の価格設定でサービスされていましたが、2009-07-24より変更されました。(移行期間あり)

|! |! 低|! 中|! 高|
|!MSP| 200| 400| 800|
|!US$相当| 2.50| 5.00| 10.00|
|!<html>&yen;</html>相当| 300| 600| 1,200|
|!ファイルサイズ上限|	 50MB| 150MB| 150MB|

※90日に一度価格を変更することもできます。
 以下は、[[XNA Game Studio]]を使って、[[Xbox 360]]用の[[Xbox LIVEインディーズゲーム]]を作成する場合の大まかな流れです。

#[[XNAクリエーターズクラブ]]に参加し、[[XNA Game Studio]]をダウンロードする
#ゲーム制作を始める
#プレミアムメンバーシップを購入する
#[[XNA Game Studio]]について[[Xbox 360]]を設定する
#Xbox LIVEへ提出するためにゲームをパッケージする
 「Xbox LIVEコミュニティーゲーム」(Xbox LIVE Community Games)は「[[Xbox LIVEインディーズゲーム]]」(Xbox LIVE Indie Games)の古い名称です。そのため、一部ではこの古い名称が見られます。
*同じマルチプレイヤーセッション内の同じゲームをプレイしていないゲーマーのときでさえも、ゲーマーがコミュニケーションできるようにします。
*ゲーマーの8ウェイグループのボイスチャットまでをサポートしています。
*Xbox 360で「ゲームプレイ中」「ビデオ観賞中」「音楽鑑賞中」「マーケットプレース閲覧中」であるかを問いません。
*LIVEパーティチャットはゲームプレイセッションの「接続前」「接続中」「終了後」でもゲーマーの接続を保持します。
*ゲーマーたちが一緒に簡単にすばやくマルチプレイヤーゲームに入れるようにします。
 [[Xbox LIVEインディーズゲーム]]の[[Xbox 360]]用ゲームは、[[Xbox 360]]本体の「ゲーム マーケットプレース」および、[[Xbox LIVE Marketplace|http://marketplace.xbox.com/ja-JP/]]のサイトがあります。サイトには、PCなどを使って、ウェブブラウザからもアクセスすることができます。

 Zuneは携帯型音楽再生端末です。日本国内では販売されていません。また、Zuneシリーズに、[[Zune HD]]が発表されました。

!Zuneの仕様

!!CPU
|!CPU|Freescale i. MX31L ARMコア|
|!メモリ|16MB|
*浮動小数点拡張

!!GPU
*GPUなし
*XNAにおいて、SpriteBatchクラスをCPUでサポート
 [[Zune]]の後継機です。[[XNA Game Studio 3.1]]のうち、2D機能に対応しています。

!!Zune HDの仕様(公式発表済み)
*画面
**3.3インチ
**タッチスクリーン
**解像度: 480×272 (16:9)
***解像度はPSPと一致
**OLED(有機発光ダイオード)
***有機ELを使ったLED
*Wi-Fi
*Xbox LIVE
*HDMIによるHD (720p) ビデオ出力
**別売りドッキングステーションによる
**[[タッチパネル]] : マルチタッチ対応
**[[加速度計]]
|''種別:''|file|
|''URL:''|http://www.tiddlytools.com/|
|''ワークスペース:''|(default)|

このtiddlerはこのサーバーの詳細情報を記録するために自動的に作成されました
xapの拡張子は、次の2つ異なる形式で使われています。扱いには注意してください。

*[[Silverlight]]や[[Windows Phone 7]]のXNA Game Studioのゲームなどの形式
**zip形式に基づくパッケージ。zip形式を使っています。xap形式ファイルの内容は、zip形式のファイルとして確認が可能です。
*XACT Project File形式
**「Microsoft Cross-Platform Audio Creation Tool」([[XACT]])用
 [[Xbox LIVEインディーズゲーム]]にはお試し版モードがあり、XNAフレームワーク側により一定時間で終了します。[[Xbox LIVEインディーズゲーム]]のお試し版モード(Trial Mode)の時間制限は8分になっています。この時間制限の長さは変更される可能性もあるので、この長さを前提にしないようにしましょう。
 お試し版モードは、Microsoft.Xna.Framework.GamerServices.Guide.IsTrialModeプロパティで判定できます。これにより、プログラムでお試し版モードを判定して、処理を分けることができます。

*参考: http://creators.xna.com/en-US/news/

!!お試し版の期限切れ

 お試し版の時間制限を超えると、次のような内容の画面が表示されます。

----
期限切れ

このゲームのお試し期間は終了しました。
もう一度お試し版をプレイするか、完全版
を購入することができます。

完全版を購入しますか?

(B) ゲーム終了  (X) 完全版を購入する
----


 このページでは、外部リンク以外の項目を選択するとページ内に表示されます。不要な項目は「閉じる」こともできます。
(この項目は、「ご利用コード」機能の開始前に記述しているため、推定を含んています)

![[Xbox LIVEインディーズゲーム]]の「ご利用コード」(Token、トークン)とは
 2009-07-30(現地時間)以降、[[Xbox LIVEインディーズゲーム]]で承認されたゲームのクリエーターは、そのゲームに対する最大50個の「ご利用コード」を受け取ることができます。ご利用コードはメディア(報道)に提供するなどして、ゲームのプロモーションに利用することができます。

 ゲームのクリエーターは、 XNAクリエーターズクラブオンラインの「取引の詳細」ページで「ご利用コード」を取得できます。

!!ご利用コードの用例

*体験記事を書いてくれるメディア関係者やブロガーなどに、ご利用コードを提供してみる。
*そのゲームの制作関係者にご利用コードを配る。

※特にご利用コード機能の利用方法に制限は設けられていませんが、ご利用コードを販売することは許可されてないため、販売するとアカウントが永久追放(Permanently Ban)になりますので注意しましょう。

!!ご利用コードの利用

*ご利用コードは、そのゲーム専用の「?????-?????-?????-?????-?????」といった形式の25文字のコードです。
*Xbox 360上で「ご利用コードを使う」を選択して、ご利用コード1つを入力して消費することで、そのゲームの完全版1つが利用できます。
*ご利用コードを受け取ってから利用するより前に、そのゲームのアップデート(更新)が行われた場合でも、ご利用コードは有効です。

*Xbox 360本体から使う場合(1)
**Xbox 360ガイドボタンを押して、左の「マーケットプレース」ブレードにスクロールする。
**「ご利用コードを使う」を選択する。
**25文字のご利用コードを入力する。

 その他の入力の場所は、以下のいずれかです。(推定)

*「アカウント管理」→「ご利用コード」
*「ゲーム マーケットプレース」→「インディー ゲーム」→ゲーム→「ダウンロード」→「ご利用コードを使う」
*「ゲーム ライブラリ」→お試し版ゲーム→「完全版にアップグレード」→「ご利用コードを使う」
*「ゲーム マーケットプレース」→「インディー ゲーム」→お試し版ゲーム→「完全版にアップグレード」→「ご利用コードを使う」

!!Xbox 360からコードを入力した場合

 次の文面を含む画面が現れます。

|このコードを使うと完全版ゲーム - ''タイトル'' をダウンロードできます|

!!ご利用コードの管理

*ゲームのクリエーターは、 [[XNAクリエーターズクラブ]]オンラインの「取引の詳細」ページで、ゲーム毎に最大50個のご利用コードを取得できます。
*未使用のご利用コードは、ゲームが承認を受けたときに50個作成されます。
*ゲームをアップデートしても、追加の発行はありません。プロジェクト単位で最初の50個がすべてです。
*ゲームのクリエーターは、CSV形式ファイルでご利用コードのリストをエクスポートできます。
*ゲームのクリエーターは、ご利用コードの数を確認できますが、どのご利用コードが消費されたかはわかりません。
*ご利用コードは利用されるまで、どのXbox LIVEアカウントにも関連付けられていません。

*アバター([[XNA Game Studio 3.1]]以降)
**機能対応プラットフォーム: [[Xbox 360]]のみ。[[Windows]]では描画されない。
**2008-11-19にNXE (New Xbox Experience)として追加されたXbox 360のアバター機能が利用できる。
***http://www.xbox.com/ja-jp/nxe/avatar.htm
**AvatarDescription
***SignedInGamerから作成
***ランダム作成
***ネットワーク送信
**AvatarRenderer
***組み込みアニメーションの再生
***任意ボーン行列によるアニメーションの再生
***1つの平行光源
**AvatarAnimation
**AvatarExpression

![[アバターのサンプル]]

!アバター画像はインターネットで見られる
|!|!解像度(横×縦)[ピクセル]|!URL|
|!全身| 150×300 |{{{http://avatar.xboxlive.com/avatar/}}}''ゲーマータグ''{{{/avatar-body.png}}}|
|!顔| 64×64 |{{{http://avatar.xboxlive.com/avatar/}}}''ゲーマータグ''{{{/avatarpic-l.png}}}|
|!顔| 32×32 |{{{http://avatar.xboxlive.com/avatar/}}}''ゲーマータグ''{{{/avatarpic-s.png}}}|
 [[XNA Game Studio 3.1]]の[[アバター]]のサンプルコードです。なお、アバターは[[Xbox 360]]専用機能のため、[[Windows]]では、エラーは起きませんが描画されることはありません。

[img(50%,auto)[AvatarSample.png]]

{{{
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace AvatarSample {
	public partial class AvatarGame : Microsoft.Xna.Framework.Game {
		readonly GraphicsDeviceManager graphics;
		AvatarDescription description;
		AvatarAnimation animation;
		AvatarRenderer renderer;
		AvatarExpression expression = new AvatarExpression();
		float rotationX;
		float rotationY;

		public AvatarGame() {
			graphics = new GraphicsDeviceManager(this);
			graphics.PreferredBackBufferWidth = 1280;
			graphics.PreferredBackBufferHeight = 720;
			Content.RootDirectory = "Content";
			// AvatarRendererのために必要
			Components.Add(new GamerServicesComponent(this));
		}

		protected override void LoadContent() {
			CreateAvatar();
		}

		void CreateAvatar() {
			animation = new AvatarAnimation(AvatarAnimationPreset.Wave);
			description = AvatarDescription.CreateRandom();
			renderer = new AvatarRenderer(description);
		}

		protected override void Update(GameTime gameTime) {
			var state = GamePad.GetState(PlayerIndex.One);
			if (state.Buttons.Back == ButtonState.Pressed)
				this.Exit();
			rotationX = state.ThumbSticks.Left.Y * MathHelper.Pi;
			rotationY = state.ThumbSticks.Left.X * MathHelper.Pi;
			if (state.IsButtonDown(Buttons.Y)) {
				CreateAvatar();
			}
			if (state.IsButtonDown(Buttons.A)) {
				expression.Mouth = AvatarMouth.Happy;
				expression.LeftEye = AvatarEye.Happy;
				expression.RightEye = AvatarEye.Happy;
				expression.LeftEyebrow = AvatarEyebrow.Neutral;
				expression.RightEyebrow = AvatarEyebrow.Neutral;
			} else {
				expression = new AvatarExpression();
			}

			animation.Update(gameTime.ElapsedGameTime, true);

			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime) {
			GraphicsDevice.Clear(Color.CornflowerBlue);
			renderer.LightDirection = Vector3.Normalize(new Vector3(1, 2, 3));
			renderer.World = Matrix.CreateRotationY(rotationY) * Matrix.CreateRotationX(rotationX);
			renderer.View = Matrix.CreateLookAt(new Vector3(0, 1, -3), new Vector3(0, 1, 0), Vector3.Up);
			renderer.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
				GraphicsDevice.Viewport.AspectRatio, 1, 1000);
			renderer.Draw(animation.BoneTransforms, expression);
			base.Draw(gameTime);
		}
	}
}
}}}
 [[Xbox LIVEインディーズゲーム]]において、[[アバター]]機能を利用する場合にはルールがあります。アバター機能を使う場合には、確認するようにしましょう。(リンク先を参照)

*ゲームのピア レビュー : 禁止されているアバターの取扱い
**http://creators.xna.com/ja-jp/help/peerReviewStep22
*Avatars: What Can You Do?(英語)
**http://creators.xna.com/en-US/article/avataruse
*Avatars: What Can You Do?(日本語用ページ/英語)
**http://creators.xna.com/ja-JP/article/avataruse
*禁止されているアバターの取り扱いに関するアップデート(2010-03-08)
**http://creators.xna.com/ja-JP/news/peerreviewavatarupdatemarch2010


 ルールには、アバターを使った描写でしてはならないこと、許容される範囲が示されています。制作時やピアレビュー時の判断の際には、公式の最新情報の参照するようにしましょう。

 以下は、古い英語の内容をもとにしています。正確ではなく、最新の文面ではありません。公式の最新情報の参照してください。

--

 Xbox LIVEアバターは、プレイヤーに利用させることができるユニークで個人的なアイテムです。アバター利用についての誤用を防ぐためのとても具体的なルールがあります。アバターを含むいかなるXbox LIVEインディーズゲームも、アバターが以下の行為をさせることなく、行為を心に浮かばせることなく、あるいは見物人とならないことをチェックするためにピアレビューされなければなりません。

!プレーヤーがまるで別々のキャラクターであるかのように、自身のアバターと対話する

プレーヤーのアバターは、自立した個性や本能をもちません。アバターは所有するプレーヤーの管理下にあります。 待機アニメーションを持つことができて、適切にゲームイベントに応じることができますが、まるでプレーヤーと別であるかのように、ユーザーと対話するべきではなく、煩わしい方法でプレーヤーの注意を得ようとすべきではありません。

!血、流血、切断、打ち首、重傷、バラバラを引き起こす暴力

マンガの暴力は許容されます。暴力は血、流血、切断、打ち首、重傷、バラバラがない限り許容されます。許容できる負傷の例には、アメリカンフットボールなどのスポーツ競技でアバターに降りかかるかもしれない負傷を含んでいます。アバターは失敗を描写するために一時的に死ぬことはできます。

!プレイヤーのアバターの会話

プレイヤーのアバターは声をもつべきではありません。笑いや泣きのような個別の音にすることは許容されますが、声を使うことはできません。

!性的暗示、穏やかに明白な性的描写、イメージ、性的な姿勢の行為

性的行為や専門用語は暗示したり演じたりしてはなりません。

!猥褻な体液や物質の分泌

性的あるいは体液あるいは物質はアバターから出してはなりません。

!犯罪行為を美化する

犯罪活動は、物語と関係があって、好ましくないと示す必要があります。

!好戦的あるいは脅迫的な態度の行為

Gratuitous insults, bullying, intimidation or otherwise violent or emotional abuse of a position of power are not allowed. Avatars may leave innocents or bystanders slightly injured, but not dead.

!下品な行為や冒とく行為

ゲームに制御されたアバターは、冒とく、人種差別、差別用語、卑猥な仕草をすることはできません。

!規制物質の使用

アバターは、アルコール、タバコ、およびドラッグに限らず、いかなる規制物質や規制道具を所持したり、そばに見えたり、参加したりすることも許容されません。

!アバターの特徴を置き換える

アバターの特徴は隠したりあいまいにしたりできず、代替アイテムに置き換えることはできません。マスク、帽子、代替の衣服に限らないアイテムは、許容されません。

!アバターのプロポーションは変化させない

アバターのプロポーション(体型)は元の設定から変化した形にできません。アバターはプロポーションを変えない限り大きさを変えることはできます。
*XNA Game Studio / XNAクリエーターズクラブ / Xbox LIVEインディーズゲームなどに関するXELFからのアンケート (2010-05-06~)
**http://spreadsheets0.google.com/viewform?formkey=dG1GRTMtTTJ6b0d5ZmR1MnpORnNRQ1E6MQ

 上記のアンケートは、XELFが個人的に行っています。必須項目以外は、ご回答できる場合のみ記入ください。アンケートへのご回答内容は、今後の活動の参考にさせていただきます。回答者を特定しない形で、統計情報および回答を各方面で活用させていただく場合もあります。あらかじめご了承ください。
※アンケートシステムの試用も兼ねています。お気軽にご回答ください。
※ここでは、[[Xbox LIVEインディーズゲーム]]に限らず、インディーズゲーム(同人ゲーム)全般について記しています。

!インディーズゲーム(同人ゲーム)

*商業ベースではない体制で作られるゲーム。
*一人または少人数で作れるゲームがある。
*ゲーム開発・制作のプロフェッショナルが趣味でゲームを作ることもある。

!!インディーズゲームの価値

*小規模で短期間での制作体制が実現可能であり、作業工程で多くのゲーム作りについての経験が積める。商業ベースでは、大規模化によって、経験を積みづらくなっている一面がある。
*商業ベースのゲームでできないことができる魅力がある。
**自由な発想でゲームが作ることができるので、商業ベースとは異なる可能性を秘めている。
**採算性を考慮する場合でも損益分岐点(ペイライン)が低いので、一般受けするジャンルや企画に捕らわれる必要はない。

!!インディーズゲームの制作動機となりうるもの

*既製品に対する不満
*楽しませたい

!!インディーズゲームの開発工程(例)

*コンセプト
*デザイン
*開発・制作
**アジャイル・トライアルアンドエラー
**「もてなし」
***そのゲームの初心者にやってもらいたいことが伝えられているか
***上級者が楽しめる要素は何か
**ツール・ミドルウェア
***既製ツール
***自作ツール
*テストプレイ
**理想的には初心者~上級者まで幅広い層がいるのが良い
**開発者は基本的に上級者の立場(初心者の戸惑いに気付きにくい)
*発表・配布
([[XNA Game Studio 4.0]])

 エフェクトは、Effectクラスで表されます。頂点シェーダやピクセルシェーダなどをまとめたものです。

 独自のエフェクトが利用できるプラットフォームでは、エフェクトのコードは、[[HLSL]]を使って記述することができます。ファイルは、エフェクトファイル(.fx)です。

 また、[[XNA Game Studio 4.0]]では、5つのエフェクトが予め用意されています。[[XNA Game Studio 4.0]]において、[[Windows Phone 7]]では、独自のエフェクトを作れないため、この5つのエフェクトのみを利用して、画面を構成する必要があります。

|5つのエフェクト|c
|!クラス名|!用途|
|BasicEffect|基本的なエフェクト。1テクスチャ/3ライト/頂点色/パーピクセルライティング/フォグなどが有効にできる|
|SkinnedEffect|スキンモデル用エフェクト。キャラクターアニメーションなどの基本になる。アニメーション自体は、サンプルコードなどを併用して実現する|
|EnvironmentMapEffect|環境マップ用エフェクト。テクスチャを使った鏡面反射など環境の映り込み表現に使える|
|DualTextureEffect|デュアルテクスチャ用エフェクト。2つのテクスチャが利用できる|
|AlphaTestEffect|アルファテスト用エフェクト。[[XNA Game Studio 4.0]]より、従来のレンダーステートにあったアルファテストは廃止された。代わりにこのエフェクトまたは独自のエフェクトを利用する|

 実際の使い方は、公式にあるサンプル「Reach Graphics Demo」が参考になります。

*Reach Graphics Demo
**http://creators.xna.com/ja-JP/minigame/reachgraphicsdemo

 また、これらのエフェクトの負荷については、「[[エフェクトのコスト]]」を参考にしましょう。
 [[XNA Game Studio 4.0]]のプロファイルレベル「Reach」で使える5つの[[エフェクト]](「BasicEffect」「DualTextureEffect」「AlphaTestEffect」「SkinnedEffect」「EnvironmentMapEffect」)の実行コスト(「頂点シェーダ」「ピクセルシェーダ」)についての情報です。

|!BasicEffect|!頂点コスト|!ピクセルコスト|
|1頂点ライト| 40| 1|
|3頂点ライト| 60| 1|
|3ピクセルライト| 18| 50|
|+テクスチャ| +1| +2|
|+フォグ| +4| +2|

|!DualTextureEffect|!頂点コスト|!ピクセルコスト|
|2テクスチャ| 7| 6|
|+フォグ| +4| +2|

|!AlphaTestEffect|!頂点コスト|!ピクセルコスト|
|<,<=,>=,>| 6| 6|
|==,=| 6| 10|
|+フォグ| +4| +2|

|!SkinnedEffect|!頂点コスト|!ピクセルコスト|
|1頂点ライト| 55| 4|
|3頂点ライト| 75| 4|
|3ピクセルライト| 33| 51|
|+2ボーン| +7| +0|
|+4ボーン| +13| +0|
|+フォグ| +0| +2|

|!EnvironmentMapEffect|!頂点コスト|!ピクセルコスト|
|1ライト| 32| 6|
|3ライト| 36| 6|
|+フレネル| +7| +0|
|+スペキュラー| +0| +2|
|+フォグ| +0| +2|

!参照
!!MIX10
*CL22 Building a High Performance 3D Game for Windows Phone
**http://ecn.channel9.msdn.com/o9/mix/10/wmv/CL22.wmv
![[Windows Phone 7]]では、解像度を下げて、ハードウェアのスケーラ(スケーリング機能)を活用する([[XNA Game Studio 4.0]])

*これはGPU処理能力を消費しない
*バイリニア・アップサンプリングより高品質

|!解像度|!ピクセル数|!ピクセル数の比率[%]|
| 800×480| 384,000| 100.00|
| 600×360| 216,000| 56.25|

!レンダーターゲット

|!×|!○|
|なるべくRenderTargetUsage.PreserveContentsを避けて|RenderTargetUsage.DiscardContentsにする|
※[[Windows Phone 7]]と[[Xbox 360]]で効果がある

!必要なレンダーステート関連([[XNA Game Studio 4.0]])

|!×|!○|
|フレーム毎にインスタンスを作ることは避けて|レンダーステート関連オブジェクトは事前に作っておく|

!動的頂点バッファ

|!×|!○|
|フレーム毎にVertexBuffer.SetDataメソッドを呼ぶのではなく|DrawUserPrimtivesメソッドまたは、DynamicVertexBuffer.SetData(…, SetDataOptions.NoOverwrite)を用いる|

!参照
!!MIX10
*CL22 Building a High Performance 3D Game for Windows Phone
**http://ecn.channel9.msdn.com/o9/mix/10/wmv/CL22.wmv
!GamerServicesComponentクラス

 ゲーマーサービスAPIは、コンポーネントとして「GamerServicesComponentクラス」で提供されているので、ゲーマーサービスAPIを利用するには、Game派生クラスの初期化処理に次のようなコードを加えます。
{{{
Components.Add(new GamerServicesComponent(this));
}}}

![[Windows Phone 7]]のXboxパートナー(managed developer)限定で利用できる機能([[XNA Game Studio 4.0]])
*ゲーマーサービスAPIにおいて
**ユーザーのゲーマータグと2Dアバターの読み取り
**プラットフォーム上での実績のロック解除、実績とゲーマースコアの収集
**非同期ターンベースのゲーム用の通知
**Xbox LIVEランキング(Leaderboard)の閲覧
**Xbox LIVEフレンドのフレンドリストへの追加
**スポットライトのフィードへのアクセス

 XNA Game Studioで作ったゲームの配布方法は、次のようなものが考えられます。これらは、ソースコードなどを含まないエンドユーザー向けた配布の方法です。

!Windows用

*ClickOnceを用いてインストールできるファイルにして配布
*ClickOnceを用いてウェブからインストールできるようにしてウェブに公開
*アーカイブ(ZIP形式など)にファイル一式をまとめて配布。この方法では特に形式にこだわらないならば、Windowsでも標準で展開に対応しているZIP形式が無難でしょう。この場合、各種ランタイムのインストールが必要
*XNAクリエーターズクラブゲームパッケージ(.ccgame形式)で配布。この場合には別途、XNA Game Studioのインストールが必要

!Xbox 360用
*[[Xbox LIVEインディーズゲームでの公開]]に挑戦する
*XNAクリエーターズクラブゲームパッケージ(.ccgame形式)で配布。この場合、XNA Game Studioのインストールと、[[XNAクリエーターズクラブ]]プレミアムメンバーシップが必要。つまり、XNA開発者同士向けといえる
!!ゲームでよくある表現(参考)

 ゲームのインターフェースで使う参考用の日本語や英語の表現です。

|!日本語|!英語|!注釈|
|ゲーム開始|Game Start|
|ゲームを遊ぶ|Play Game||
|クレジット|Credits||
|メニューへ戻る|Return to Menu||
|ゲームオーバー|Game Over||
|コンティニュー|Continue||
|戻る|Back||
|終了する|Exit||
|ロード中|Now Loading|
|フレンド|Friends|
|リプレイ|Replay||
|ヘルプとオプション|Help & Options||
|完全版へロックを解除|Unlock Full Game||
|ランキング(リーダーボード )|Leaderboards|混乱を避けるため、この単語を[[Xbox LIVEインディーズゲーム]]のゲームで使うことは避けなければならない|
|ゲーム ライブラリーへ戻る|Return to Game Library||
|遊び方 / 操作方法|How to Play||
|設定|Settings||
|コントローラー設定|Controls||
|ゲーマータグ|Gamertag|
|実績|Achievements|[[Xbox LIVEインディーズゲーム]]では「実績」機能は利用できない。また混乱を避けるため、この単語を[[Xbox LIVEインディーズゲーム]]のゲームで使うことは避けなければならない|
|追加コンテンツ|Download Content|[[Xbox LIVEインディーズゲーム]]では「追加コンテンツ」機能は利用できない|
!コンテンツパイプライン(Content Pipeline)

(略)

!!コンテンツプロジェクト

!!!コンテンツプロジェクトの扱い
|! |![[XNA Game Studio 4.0]] [[CTP]]|![[XNA Game Studio 3.1]]以前|
|!方式|参照方式|サブプロジェクト方式|
|!既定のコンテンツプロジェクト名|''プロジェクト名''Content|Content|

!!ContentManagerクラス
 コンテンツパイプラインで処理されたアセットは、ゲーム実行時には、ContentManagerクラスがコンテンツを管理します。Gameクラスには標準でContentプロパティにContentManagerインスタンスが用意されています。

*Content.Load<T>メソッドでアセット名を指定して、T型のコンテンツをロードします。このとき、単一のContentManagerインスタンスを使って、同一アセット名のコンテンツを複数回ロードした場合には、同じものを参照し、共有しています。
*Content.Unloadメソッドを呼ぶと、すべてアンロードします。

!!コンテンツをカテゴリ分けする
 必要であれば、コンテンツをカテゴリ分けするために、別途ContentManagerインスタンスを作ることもできます。

!!!例: Game派生クラスにおいて
{{{
		ContentManager Content2;

		protected override void LoadContent() {
			Content2 = new ContentManager(Services, "Content");
			base.LoadContent();
		}
}}}
 ゲームのユーザーデータのロードやセーブを可能にするためには、Microsoft.Xna.Framework.Storage名前空間にあるストレージ機能を使います。

!!ストレージの種類
|!ストレージの種類|!ストリームの開き方([[XNA Game Studio 4.0]])|!パスの決定方法([[XNA Game Studio 3.1]])|
|タイトルストレージ|TitleContainer.OpenStreamメソッドを使う|StorageContainer.TitleLocationプロパティを使う|
|ユーザーストレージ|[[Xbox 360]]では、StorageDevice.OpenContainerメソッドから作成したStorageContainerのPathプロパティを使い、パスからストリームを作る。 <br>[[Windows Phone 7]]では、System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplicationメソッドを使い、IsolatedStorageFileクラスで処理する|StorageDevice.OpenContainerメソッドから作成したStorageContainerのPathプロパティを使う|

!!ストレージの特性([[XNA Game Studio 3.1]])
|!処理|!Windows|!Xbox 360|
|タイトルストレージでのファイル作成| ○ | UnauthorizedAccessException |
|タイトルストレージでのファイル読み込み| ○ | ○ |
|ユーザーストレージでのファイル作成| ○ | ○ |
|ユーザーストレージでのファイル読み込み| ○ | ○ |
|ユーザーストレージの独立性| 共有 | GUIDで独立(※1) |
※1:ゲームはGUIDで区別される。そのGUIDによってストレージ空間は独立している。ゲームAで保存したファイルは、GUIDの異なる別のゲームBから同じパスとファイル名でアクセスしても見つけることはできない。

 上記の特性は実験結果によります。タイトルストレージもユーザーストレージもそれぞれにXbox 360ではGUIDに依存しない特定のパスを持っていて、それでいて「別のGUID同士でファイルを共有する」実験でファイルが見つけられないことから、システムによってストレージ空間が独立になっていると考えられます。

 この結果からは、[[Xbox 360]]では、別の(GUIDを持つ)ゲーム同士でユーザーデータを共有することができないと言えます。同一のGUIDを持たせた異なる複数のゲームを「Xbox LIVEインディーズゲーム」に提出した場合に、どう扱われるかについては不明です。

!!ユーザーストレージの処理について([[XNA Game Studio 3.1]])

*ユーザーストレージを扱う場合には、「ロード」と「セーブ」に関する処理が必要になることでしょう。
*開発環境での開発中には前回のファイルをロードしてセーブする場合も多いので、まだ何もない「ゲームの初期状態」から新規作成の検証も重要になるでしょう。
*以前のゲームのバージョンからセーブデータを引き継ぐ場合には特に注意が必要になるでしょう。

 自作ゲームの場合には、これらをきちんと管理する必要が出てくることでしょう。

!!Xbox 360で手動による特定のゲームのセーブファイル(ユーザーストレージ)の削除方法

 XNA Game Studioで作られたゲームが保存したユーザーストレージは、Xbox 360の次の場所で管理できます。

*「Xbox 360」チャンネル→「システム設定」→「メモリー」→「ストレージ機器」(「ハードディスク」「MU」)→「ゲーム」→「XNA Game Studio Connect」

 これは、他のクリエーターのゲームのレビューにおいて、ストレージに関する不具合が疑われる場合などで、「ゲームの初期状態」を検証するために便利です。
!TouchPanelクラス
 タッチパネルのマルチタッチ(8つまで)の位置・圧力・状態が取得できます。

!!!(例1)APIの概要
{{cs{
{{t{TouchCollection}}} touches = {{t{TouchPanel}}}.GetState();
{{t{TouchLocation}}} touch0 = touches[0]; {{c{&#47;&#47; 1つめのタッチがあると仮定して}}}
{{t{Vector2}}} position = touch0.Position; {{c{&#47;&#47; 画面座標系での位置}}}
{{k{float}}} pressure = touch0.Pressure; {{c{&#47;&#47; 圧力[g]}}}
{{t{TouchLocationState}}} state = touch0.State; {{c{&#47;&#47; 状態}}}
{{t{TouchLocation}}} previousLocation;
{{k{if}}} (touch0.TryGetPreviousLocation({{k{out}}} previousLocation)) { {{c{&#47;&#47; 前回のTouchLocationの取得を試みる}}}
    {{c{&#47;&#47; 取得できた}}}
}
}}}

!!!(例2)タッチの状態で処理する
{{cs{
{{t{TouchCollection}}} touches = {{t{TouchPanel}}}.GetState();
{{k{foreach}}} ({{t{TouchLocation}}} location {{k{in}}} touches) {
    {{k{switch}}} (location.State) {
        {{k{case}}} {{t{TouchLocationState}}}.Pressed:
            {{k{break}}};
        {{k{case}}} {{t{TouchLocationState}}}.Moved:
            {{k{break}}};
        {{k{case}}} {{t{TouchLocationState}}}.Released:
            {{k{break}}};
    }
}
}}}
!DynamicSoundEffectInstanceクラス ([[XNA Game Studio 4.0]])
http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.audio.dynamicsoundeffectinstance(v=XNAGameStudio.40).aspx
----
※[[CTP]]時点のコードです。

 DynamicSoundEffectInstanceクラスを使って、動的に生成した音を鳴らすことができます。

 DynamicSoundEffectInstanceを作って、BufferNeededイベントに応じて、SubmitBufferメソッドにbyte配列でPCMデータを与えれば良いようです。サンプルは、ゲームパッドのスティックで音量や音程を変えて矩形波を鳴らす単純なものです。

!!サンプルコード

{{cs{
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace DynamicAudioSample {
	public class DynamicAudioGame : Microsoft.Xna.Framework.Game {
		GraphicsDeviceManager graphics;
		DynamicSoundEffectInstance dse;
		byte[] buffer;
		double phase;
		ushort volume = 5000;
		int samplingRate = 48000;
		double key;

		public DynamicAudioGame() {
			graphics = new GraphicsDeviceManager(this);
			graphics.GraphicsProfile = GraphicsProfile.Reach;
			Content.RootDirectory = "Content";
		}

		protected override void Initialize() {
			key = 440.0 / samplingRate;
			dse = new DynamicSoundEffectInstance(samplingRate, AudioChannels.Stereo);
			buffer = new byte[dse.GetSampleSizeInBytes(TimeSpan.FromSeconds(1.0 / 5))];
			dse.BufferNeeded += new EventHandler<EventArgs>(GenerateSound);
			dse.Play();
			GenerateSound(this, EventArgs.Empty);
			base.Initialize();
		}

		void GenerateSound(object sender, EventArgs e) {
			var state = GamePad.GetState(PlayerIndex.One);
			for (int i = 0; i < buffer.Length; i += 4) {
				var amplitude = (state.ThumbSticks.Left.Y + 1) * volume;
				var octave = Math.Pow(2, 1 + state.ThumbSticks.Right.Y);
				var pan = (state.ThumbSticks.Left.X + 1) * 0.25f;
				phase += key * octave;

				var sample = (phase % 1) <= 0.5 ? -amplitude : amplitude;
				var leftSample = (ushort)(sample * (1 - pan));
				var rightSample = (ushort)(sample * pan);
				buffer[i + 1] = (byte)(leftSample >> 8);
				buffer[i] = (byte)leftSample;
				buffer[i + 3] = (byte)(rightSample >> 8);
				buffer[i + 2] = (byte)rightSample;
			}
			dse.SubmitBuffer(buffer);
		}

		protected override void OnExiting(object sender, EventArgs args) {
			dse.Dispose();
			base.OnExiting(sender, args);
		}

		protected override void Update(GameTime gameTime) {
			if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
				this.Exit();
			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime) {
			GraphicsDevice.Clear(Color.CornflowerBlue);
			base.Draw(gameTime);
		}
	}
}

}}}

※コード中のイベントハンドラは、CTP March 2010ではEventHandlerであるのに対し、CTP April 2010ではEventHandler<EventArgs>です。
!ネットワーク機能をプレイまたはテストするために必要なメンバーシップ
|!|!XNAゲームの起動|!システムリンク|!Live!へのサインイン|!開発中のLive!でのセッション接続|!Live!ランクマッチ|
|!NetworkSessionType列挙型|!(Local)|!SystemLink|! |!PlayerMatch|!Ranked|
|![[Windows]]| 不要 | 不要 | Xbox LIVEシルバー <br>+ XNAクリエーターズクラブ | Xbox LIVEシルバー <br>+ XNAクリエーターズクラブ | 商用ゲーム限定 |
|![[Xbox 360]]| Xbox LIVEシルバー <br>+ XNAクリエーターズクラブ | Xbox LIVEシルバー <br>+ XNAクリエーターズクラブ | Xbox LIVEシルバー <br>+ XNAクリエーターズクラブ | Xbox LIVEゴールド <br>+ XNAクリエーターズクラブ | 商用ゲーム限定 |
|![[Zune]]| 不要  | 不要 | 非対応 | 非対応 | 非対応 |
|![[Windows Phone 7]]| 不要 | 不要 | 非対応 | 非対応 | 非対応 |

*Live!
**Windows : Games for Windows - LIVE
**Xbox 360 : Xbox Live!

!バッファの形式 ([[XNA Game Studio 3.0]])

 グラフィックス用のバッファの形式は、用途によってXbox 360で選択できない形式(Vector4やHalfSingleなど)があります。Windowsと処理を共用する場合には注意が必要です。Windowsの場合には対応形式はGPUによって変わります。
 GraphicsAdapter.CheckDeviceFormatメソッド、GraphicsAdapter.CheckDepthStencilMatchメソッドで動的に対応フォーマットを調べることができます。幅広い環境で最適な動作をさせたい場合には、用途に合わせて動的に形式を選択する処理を作ってバッファを作るようにします。
 実際のところ、Xbox 360など特定プラットフォームを対象にしている場合には、事前に対応フォーマットを知っておいて、用途によって使い分けるとよいでしょう。

!!Xbox 360でRenderTarget2Dに指定できるSurfaceFormat

|SurfaceFormat.Single|
|SurfaceFormat.Vector2|
|SurfaceFormat.HalfVector2|
|SurfaceFormat.HalfVector4|
|SurfaceFormat.Color|
|SurfaceFormat.Bgr32|
|SurfaceFormat.Rgba32|
|SurfaceFormat.Rgb32|
|SurfaceFormat.Bgra1010102|
|SurfaceFormat.Rgba1010102|
|SurfaceFormat.NormalizedAlpha1010102|

!!Xbox 360でDepthStencilBufferに指定できるDepthFormat

|DepthFormat.Depth24|
|DepthFormat.Depth24Stencil8|
|DepthFormat.Depth24Stencil8Single|

!!Xbox 360で使うことができないバッファ形式

|SurfaceFormat.Bgr24|
|SurfaceFormat.Bgra2338|
|SurfaceFormat.Bgr233|
|SurfaceFormat.NormalizedByte2Computed|
|SurfaceFormat.LuminanceAlpha8|
|SurfaceFormat.Palette8|
|SurfaceFormat.PaletteAlpha16|
|SurfaceFormat.Multi2Bgra32|
|SurfaceFormat.Depth15Stencil1|
|SurfaceFormat.Depth24Stencil4|

*参照: XNA Game Studio 3.0 ドキュメント Xbox 360 Surface Formats 
*ビデオ再生([[XNA Game Studio 3.1]]以降)
**機能対応プラットフォーム: [[Windows]]と[[Xbox 360]](※)
**[[Video]]および[[VideoPlayer]]
**[[Song]]と[[MediaPlayer]]に類似
**[[MediaLibrary]]のパターンではない
**[[VideoPlayer]]インスタンスは複数保持可能
**[[コンテンツパイプライン]]によるWMVファイルのインポート
**[[VideoSoundTrackType]] : [[Music]], [[Dialog]], [[MusicAndDialog]]
**ゲームのコンテンツにもつビデオ再生のみ対応(※)
**シークはできない。一時停止・再開可能(※)

![[コンテンツパイプライン]]によるWMVファイルのインポート(※)

*対応するビデオ(WMV形式)の条件
**Windows Media エンコーダ9シリーズのMainプロファイル
**最大解像度: 1280×720
**ビデオとオーディオのストリームはCBR(Constant Bit Rate)でエンコードされていること
**保護されていない非DRMコンテンツのみ

!ビデオ再生の例(C#)
{{cs{
{{k{partial class}}} {{t{VideoPlaybackGame}}} : {{t{Game}}} {
    {{t{SpriteBatch}}} spriteBatch;
    {{t{Video}}} video;
    {{t{VideoPlayer}}} videoPlayer = {{k{new}}} {{t{VideoPlayer}}}();

    {{k{protected override void}}} LoadContent() {
        spriteBatch = {{k{new}}} {{t{SpriteBatch}}}(GraphicsDevice);
        video = Content.Load<{{t{Video}}}>({{s{"video"}}});
        videoPlayer.Play(video); {{c{&#47;&#47; 再生}}}
        {{c{&#47;&#47;videoPlayer.Stop(); &#47;&#47; 停止}}}
    }

    {{k{protected override void}}} Draw({{t{GameTime}}} gameTime) {
        spriteBatch.Begin();
        spriteBatch.Draw(videoPlayer.GetTexture(), destinationRectangle, {{t{Color}}}.White);
        spriteBatch.End();
    }
}
}}}

(※)

 VideoPlayer.GetTextureメソッドの呼び出しによって、最新のビデオのフレームがテクスチャに書きこまれたテクスチャを取得します。あるビデオのフレームを複数の場所で使いまわす場合には、VideoPlayer.GetTextureメソッドを1回だけ呼んで、取得したテクスチャを使い回すようにします。ビデオのフレームはテクスチャで取得できるので、3Dポリゴンに張り付けたり、テクスチャに対するポストエフェクトの技法を使って、映像に効果をつけたりすることができます。

*ミュート(無音)にするにはVideoPlayer.IsMutedプロパティを使う。
*ループ再生をするにはVideoPlayer.IsLoopingプロパティを使う。ただし、ひっかかりがあることに注意。
*高解像度・高ビットレートのビデオ再生はCPU負荷が大きいことに気をつけよう。

※参考: http://klucher.com/blog/video-support-in-xna-game-studio-3-1/
 提出したゲームはすべて、他のプレミアムメンバーによる「ピアレビュー」を受けなければなりません。ピアレビューのレビュー内容は次の事柄であり、ゲームの面白さなどは関係しません。

*提出されたゲームの情報が正しいか
*ゲームが正常に動作するか
*禁止事項に違反していないか
*ゲーム提出者による表現項目のレベル設定が妥当か

!ゲームをレビューする

!!レビューの内容

 レビューでは、次のことを行います。

*ゲームの表現項目のレベル設定を検証する
*成人向けコンテンツを正確に認定しているか確かめる
*禁止されているコンテンツや不具合を探して報告する

!!レビューに必要なもの

*[[XNAクリエーターズクラブ]]のプレミアムメンバーになる
*[[Windows]] PCに[[XNA Game Studio]]をインストールしておく
*[[Xbox 360]]本体でXNA Game Studio Connectを起動しておく

!!レビューするゲームを見つける

*レビューを始めるために、XNAクリエーターズクラブオンラインのウェブサイトにサインインします。
*メインメニューのゲームを選んで、「ゲームカタログ」をクリックします。
*すると、XNAクリエーターズクラブオンラインのウェブサイトに現在提出されているゲームのリストが見られます。
**ジャンルを選ぶことでフィルタすることもできます。
**「クリエーターを探す」ボックスにクリエーターの名前を入力することで、特定のクリエーターが作ったゲームにジャンプすることもできます。
*レビューできる状態にあるゲームには、「このゲームをレビュー」のリンクがあります。レビューの行程を始めるには、リンクをクリックします。

!!ゲームの状態

|!日本語|!英語|!注釈|
|処理中|In Process|ゲームを送信した後の状態。システムが処理をしている。数時間程度かかる模様。このまま待機すると「プレイテスト中」または「レビュー中」になる|
|プレイテスト中|In Playtest|プレイテスト者を受け付けている|
|レビュー中|In Review|ピアレビュー者を受け付けている|
|レビュー終了|Review Closed|[[Xbox LIVEマーケットプレース]]への配信の準備中。このまま待機すると48時間以内に「承認済み」になる|
|承認済み|Approved|ピアレビューの承認を得て[[Xbox LIVEマーケットプレース]]に並んでいる|

!!①ゲームの情報

 レビューするゲームを選択した後には、数ステップからなる「ゲームのピアレビュー」ページがあります。

 レビューを完成させるためには、まず、ゲームをダウンロードして、遊ばなければなりません。次のような手順で進めます。

!!!ゲームをダウンロードして検証する

*「ダウンロード」をクリックして、XNAクリエーターズクラブゲームパッケージ(.ccgame形式)ファイルをダウンロードします。
*ゲームをダウンロードしている間に、Xbox 360本体のXNA Game Studio Connectを開始しましょう。それには、Xbox 360本体の電源を入れ、自分のXbox LIVEプロフィールにサインインします。
*「Xbox 360」チャンネル→「ゲーム ライブラリー」→「すべて」→「XNA Game Studio Connect」を選びます。
*Windows PCとの接続を確認しましょう。
*ダウンロードできたら、ファイルを開きましょう。XNA Game StudioがXbox 360本体に自動的にゲームを配置します。(※[[.ccgameファイルのUnpackについて]])
*ゲームをプレイしてみて、「クラッシュ」「プレイ不能になる」「著しく遅延する」などを起こさないか注目しましょう。
*レビューページ上のゲームのメディア「ビデオ」「スクリーンショット」「説明」を確認します。これらの内容がゲームを何らかの方法で不適当あるいは不当表示していると感じないか注目しましょう。

 ダウンロードして、ゲームをプレイし、記載内容を確認したら、「私は、このゲームをダウンロードしてプレイし、このページに記載されている内容を確認しました。」のチェックボックスにチェックをします。「次へ」をクリックして進みます。

!!②禁止されているコンテンツ

 禁止されているコンテンツの有無を調べます。

 Xbox LIVEのインディーゲームには様々な内容がありますが、異なるプレイヤーに適した内容があり、一部は決して許容されない内容があります。この種の内容は禁止されているコンテンツです。

 レビューページの禁止されているコンテンツの説明に合う、いずれかの内容を見つけたならば、適切なチェックボックスをチェックしましょう。

*ゲームの不具合
**プログラムの問題(フリーズしてゲームをプレイできない、など)
**ゲームの情報に記載されている内容が不適切 (実際の内容と異なっている、など)
**Xbox LIVE に対して不適切 (Xbox LIVE の使用条件に反している、など)
*禁止されているコンテンツ
**タバコ、賭博施設、アルコール関連製品に関するゲーム内での広告表現
**極めて残虐な描写、極度の暴力表現
**犯罪行為を肯定、推奨する表現
**実在の個人もしくは団体に対して一方的に非難、中傷する表現
**排泄行為
**ナチスに関連する記号やナチスを擁護するコンテンツ
**個人情報の収集
**人種差別もしくは差別的な言い回し
**過激な裸体表現
**過激な性的表現
**児童ポルノ
**不適切なコンテンツ (二次利用が認められていないコンテンツ、など)
*禁止されているアバターの取扱い
**攻撃的、威嚇的な行為
**不快な体液や類似の物質を排出する
**魅力的に表現されている犯罪行為
**プレイヤーのアバターが、まるで別のキャラクターのように振る舞う
**アバターのプロポーションの変更
**アバターの特徴を取り替える
**明らかに性的なほのめかしや、軽いながらはっきりと性的な表現やポーズを示す行動
**麻薬等薬物の使用
**プレイヤーのアバターが話す
**出血や流血、手足または頭部の切断、身体への損傷、身体に致命的な欠損を生じるような暴力行為
**下品、冒涜的な行為

 禁止されているコンテンツに該当するかよくわからないときには、「?」をクリックすることで、各タイプの詳しい情報が表示されます。チェックボックスに1つでもチェックをした場合には、ゲーム内で禁止されているコンテンツを見つけたところを説明する正確なフィードバックを提供しましょう。この場合、「次へ」をクリックすると、「ゲームのピアレビュー」ページの「④評価の結果」の「差し戻しの概要」に進みます。
 該当項目がない場合、「次へ」をクリックすると「③表現項目のレベル設定」に進みます。

!!③表現項目のレベル設定

 クリエーターは、ゲームを提出するときにゲームに含まれる表現項目のレベル設定をしています。これによって、プレイヤーは何を予期しておけばよいかわかります。レビューする人として、責任を持ってクリエーターの表現項目のレベル設定が正確であるかどうか決定しましょう。

 数字とスライダーバーのあるカテゴリのリストがあります。各カテゴリについて、経験したゲームの内容を正しく表すと感じる数字へとバーをスライドさせましょう。

 「各カテゴリの意味」「各数字の意味」は、カーソルを合わせることでわかります。カテゴリの「?」をクリックすると、特定のカテゴリや数字の意味について、詳しい情報が確認できます。

 完了したら「次へ」をクリックして「④評価の結果」に進みます。

!!④評価の結果

 「④評価の結果」まで来ると、現在のゲームのレビューの行程はほぼ完了です。

 ゲームが何らかの「説明」「スクリーンショット」「ビデオ」の問題、「禁止されているコンテンツ」などの技術的問題があると示した場合、「差し戻しの概要」が表示されます。慎重にコメントに目を通し、正確であることを確かめてみましょう。何か変更する必要があれば「戻る」をクリックします。

 表示内容に問題がなければ「評価を送信」をクリックします。以上でレビューの行程は完了して、フィードバックがクリエーターにEメールで送られます。

※ピアレビューを受けて、すでに特定地域で配信しているゲームに、追加の配信地域を加える場合には、ピアレビューを受け直す必要はありません。他言語版など、ゲームに修正を加えた場合には、ピアレビューが必要です。
 [[Xbox LIVEインディーズゲーム]]では、[[ピアレビュー]]によって、クリエーター間で評価が行われます。そのため、ゲームを提出する場合、開発者自身の考えのみでは通用しない部分もあります。以下のような情報を参考に、ゲームのコンテンツが適正であるように心がけましょう。また、フォーラムなどでのさらなる提案や議論が必要な部分もあるかもしれません。

*「Xbox LIVE インディーズ ゲームのベスト プラクティス ガイド」
**http://creators.xna.com/ja-JP/education/bestpractices

!!初期地域のクリエーター間で議論されたピアレビューの基準

 「差し戻しにならないため」あるいは「ピアレビューをするとき」のチェックリストとして参考になると思います。

*差し戻しとする問題点
**The Evil Checklist for playtest/peer review
***http://forums.xna.com/forums/t/37260.aspx (参考和訳)
***http://forums.xna.com/forums/t/19525.aspx (英語原文)
*差し戻しとしない問題点
**The Not SO Evil checklist of things we don't fail for
***http://forums.xna.com/forums/t/37294.aspx (参考和訳)
***http://forums.xna.com/forums/t/30487.aspx (英語原文)

!!法的なこと

 注釈を確認の上、参照ください。

*フォーラムとピア レビューにおける法的なアドバイス
**http://forums.xna.com/forums/p/37259/215858.aspx#215858 (参考和訳)
**http://forums.xna.com/forums/t/17830.aspx (英語原文)
!多言語対応している場合の[[Xbox LIVEインディーズゲーム]]の[[ピアレビュー]]について

|! 言語の使い方 |! |! 必要なレビュー者 |! レビュー者の使用言語に対するシステムの判断方法 |
|「ゲームの説明」に登録した言語 |→| その各言語のレビュー者が必要 | プロフィールの言語の設定による |
|「ゲームのパッケージ」(バイナリ)中で使われている言語 |→| その各言語のレビュー者が必要 | ピアレビューのチェックボタンによる |

※[[Xbox LIVEインディーズゲーム]]がサポートしている言語(「英語」「フランス語」「スペイン語」「イタリア語」「日本語」「ドイツ語」)以外を含まないようにしましょう。
※ゲームパッケージ中で1単語でも含んでいる言語は、「対応している言語」のチェックボックスにチェックをつけましょう。(参考: http://creators.xna.com/ja-jp/news/mixed-language-games )
※各言語で不適切な表現を含まないように、レビューされなければなりません。

(注:以下の内容については完全ではない可能性があり調査中です。ご注意ください)

 あるゲームにおいて、X言語でゲームの説明、Y言語でゲームの説明とゲームのパッケージ、Z言語でゲームのパッケージに対応させたとします。X, Y, Z言語は、[[Xbox LIVEインディーズゲーム]]の対応言語として選べて、重複しないいずれかの言語です。
 そのゲームのピアレビューでは、以下のような言語のレビュー者が必要となります。

[img(512,512)[multilanguage.png]]

 このときには、「X言語とY言語」または「X言語とZ言語」のバイリンガルなレビュー者、「Y言語」のレビュー者、「X言語とZ言語」または「Y言語とZ言語」のバイリンガルなレビュー者が一定数必要とされます。

*Y言語の対応方法の場合、Y言語のレビュー者が必要。無難な言語対応の方法
*X言語の対応方法の場合、「X言語とY言語」または「X言語とZ言語」のバイリンガルなレビュー者が必要
*Z言語の対応方法の場合、「X言語とZ言語」または「Y言語とZ言語」のバイリンガルなレビュー者が必要

!!例
*説明{日本語} | パッケージ{日本語} → 要レビュー者{日本語(Y)}
*説明{英語, 日本語} | パッケージ{英語, 日本語} → 要レビュー者{英語(Y), 日本語(Y)}
*説明{英語} | パッケージ{英語, 日本語} → 要レビュー者{英語(Y),  英語 + 日本語(バイリンガル)(Z)}
*説明{英語, 日本語} | パッケージ{日本語} → 要レビュー者{英語 + 日本語(バイリンガル)(X), 日本語(Y)}
*説明{英語, 日本語} | パッケージ{英語, 日本語} → 要レビュー者{英語(Y), 日本語(Y)}

※パッケージの言語対応表示{英語} | パッケージ内容の実際の言語対応{日本語}  → 「ゲームの情報に記載されている内容が不適切」の可能性
!フォグ([[XNA Game Studio 3.1]])

 標準のフォグ効果の機能には、以下の方法があります。

*RenderStateクラスのフォグ関連プロパティ
*BasicEffectクラスのフォグ関連プロパティ

 前者はWindowsのみです。[[Windows]]と[[Xbox 360]]のどちらでも対応できるようにするには、後者を使いましょう。

|!RenderState|!BasicEffect|!機能|
|FogColor|FogColor|フォグの色|
|FogStart|FogStart|フォグの開始距離|
|FogEnd|FogEnd|フォグの終了距離|
|FogEnable|FogEnabled|フォグが有効か否か|
|FogDensity|-|フォグの密度(既定値:1.0f)|
|FogTableMode|-|ピクセルフォグのフォグ式|
|FogVertexMode|-|頂点フォグのフォグ式|
|RangeFogEnable|-|範囲ベースの頂点フォグを使うか否か|
 [[Xbox 360]]において、レンダーターゲット(+深度バッファ)が専用のメモリ(EDRAM)のサイズ(10MB)を超えるとき、XNA Game Studioは自動的にプレディケートタイリング(Predicated Tiling)を行います。プレディケートタイリングでは、画面を必要な数に分割(タイリング)して描画します。

 XNA Game Studioでは、自動でプレディケートタイリングを行うので、ほどんど気にする必要はありません。しかし、一部の制限事項があります。パフォーマンスについては、頂点処理の負荷が若干増えるだけなので、それほど低下しません。

*http://msdn.microsoft.com/ja-jp/library/bb464139.aspx
!デザイン時に考慮したい点について

 [[Xbox LIVEインディーズゲームにゲームを提出する]]ときの販促素材の「パッケージの画像」(ボックスアート、仮想のパッケージデザイン)については、販促素材として提出する「パッケージの画像」(図の緑矢印の範囲)のさらに上に、自動的に帯状にロゴが加わります(図の赤矢印の範囲)。
 また、[[Xbox 360]]上では、全体に対して丸い角取りが若干加わった状態で表示されています。

 これらを想定してデザインするとよいでしょう。

!!模式図
[img[BoxArtMeasure.png]]

 2009-07-21現在、実際に開始されている地域の[[Xbox LIVEマーケットプレース]]をみると、デザインされた「COMMUNITY GAMES」のロゴがついています。これは今後、インディーズゲームを示すデザインに変わると予想されます。
 2009-07-27現在は「INDIE GAMES」のロゴがついています。

!!アスペクト比における検証

 販促素材に指定されるサイズと、[[Xbox LIVEマーケットプレース]]での画像のサイズを見ると、次のことがわかります。

|! |!解像度 |!パッケージの画像のアスペクト比 |
|! 提出するパッケージの画像 | 584 x 700 | 584 / 700 = 0.834285714 |
|! xbox.comの[[Xbox LIVEマーケットプレース]]の画像 | 219 x 300 (219 x 38 + 219 x 262) | 219 / 262 = 0.835877863 |

 このように、「パッケージの画像」のサイズに含まないアスペクト比がほぼ一致することから、上部の帯状のロゴ部分(219 x 38)は「パッケージの画像」とは別に加えられていると考えられます。
http://www.xbox.com/ja-JP/live/SKU/microsoftpoint.htm
!Microphoneクラス ([[XNA Game Studio 4.0]])
http://msdn.microsoft.com/ja-jp/library/microsoft.xna.framework.audio.microphone(v=XNAGameStudio.40).aspx
----
※[[CTP]]時点のコードです。

!!大まかなAPIの使用方法

*Microphone.AllまたはMicrophone.DefaultからMicrophoneインスタンスを取得する
*ReadyBufferイベントに応じて
*GetDataメソッドを使ってbyte配列に波形データ(PCM)を得る

!!サンプルコード

 初期化時に最初に発見されるマイクからの入力音声をオーディオ再生するサンプルです。ただし、入出力の同期処理は特に行っていません。

{{cs{
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace MicrophoneSample {
	public class MicrophoneGame : Microsoft.Xna.Framework.Game {
		GraphicsDeviceManager graphics;
		Microphone microphone;
		DynamicSoundEffectInstance dse;
		byte[] buffer;

		public MicrophoneGame() {
			graphics = new GraphicsDeviceManager(this);
			Content.RootDirectory = "Content";
		}
		protected override void Initialize() {
			microphone = Microphone.All[0];
			microphone.BufferDuration = TimeSpan.FromSeconds(0.25f);
			microphone.BufferReady += new EventHandler<EventArgs>(ReadSoundBuffer);
			microphone.Start();
			buffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)];

			dse = new DynamicSoundEffectInstance(microphone.SampleRate, AudioChannels.Mono);
			dse.BufferNeeded += new EventHandler<EventArgs>(WriteSoundBuffer);
			dse.Play();
			WriteSoundBuffer(this, EventArgs.Empty);

			base.Initialize();
		}

		void ReadSoundBuffer(object sender, EventArgs e) {
			microphone.GetData(buffer);
		}
		void WriteSoundBuffer(object sender, EventArgs e) {
			dse.SubmitBuffer(buffer);
		}

		protected override void Update(GameTime gameTime) {
			if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
				this.Exit();
			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime) {
			GraphicsDevice.Clear(Color.CornflowerBlue);
			base.Draw(gameTime);
		}
	}
}

}}}

※コード中のイベントハンドラは、CTP March 2010ではEventHandlerであるのに対し、CTP April 2010ではEventHandler<EventArgs> です。
 XNAでは、[[Windows]]において、マウスをサポートしています。[[Xbox 360]]では使えません。

 WindowsでのXNAウィンドウ上でOSによるマウスカーソルが見えるようにするには、GameクラスのIsMouseVisibleプロパティを使います。
{{{
IsMouseVisible = true;
}}}
 ここでは[[Xbox LIVEマーケットプレース]]を指しています。
 ミップマップつきのテキスチャにおいて、ミップマップの各レベルの解像度とレベルの数は、以下のように決まります。
 各辺(width, height, ...)の解像度は、ミップマップのレベルは1つ進むごとに、端数切捨てで半分の整数になります。ただし、1を下限とします。すべての辺が1となったら、そのレベルを最後として打ち切ります。
 これを満たさない場合には、適合していない旨の例外が発生します。

!コンテントパイプラインの「Texture2DContent」を扱うコンテントプロセッサにおいて、明示的にミップマップのレベルを追加する例
※形式は「Color」を前提としています。また、ビットマップの内容は処理していません。
{{{
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using TInput = Microsoft.Xna.Framework.Content.Pipeline.Graphics.Texture2DContent;
using TOutput = Microsoft.Xna.Framework.Content.Pipeline.Graphics.Texture2DContent;
namespace Mipmap {
	[ContentProcessor(DisplayName = "Mipmap")]
	public class ContentProcessor1 : ContentProcessor<TInput, TOutput> {
		public override TOutput Process(TInput input, ContentProcessorContext context) {
			var source = input.Mipmaps[0];
			input.Mipmaps.Clear();
			input.Mipmaps.Add(source);
			var width = source.Width;
			var height = source.Height;
			do {
				width = Math.Max(1, width >> 1);
				height = Math.Max(1, height >> 1);
				var content = new PixelBitmapContent<Color>(width, height);
				input.Mipmaps.Add(content);
				// TODO: content.SetPixelData(...);
			} while ((width | height) > 1);
			return input;
		}
	}
}
}}}

!値の例
|!Mipmap level| 0| 1| 2| 3| 4| 5| 6|
|!Width| 16| 8| 4| 2| 1| 1| 1|
|!Height| 70| 35| 17| 8| 4| 2| 1|
![[XNA Game Studio 4.0]]でレンダーステートに相当するもの

 [[XNA Game Studio 3.1]]におけるGraphicsDeviceのレンダーステートは、[[XNA Game Studio 4.0]]では、「BlendState」「DepthStencilState」「RasterizerState」に分類されました。「SamplerState」も含めて、それぞれに事前に用意されているステートがあり、これまでよりも簡潔に扱えるようになっています。それ以外のものが必要ならば、ゲーム中で使うものを予め作成しておくようにします。

 ステートは必要なときに、「GraphicsDevice.BlendStateプロパティ」「GraphicsDevice.DepthStencilStateプロパティ」「GraphicsDevice.RasterizerStateプロパティ」「GraphicsDevice.SamplerStatesプロパティ」に対応するステートを設定して使います。

|!予め用意されたステート|!用途|
|BlendState.Additive|加算合成。光っている表現によく使われる。重ね合わせ順序が変わっても加算結果は同じなので、ソートの必要がない利点もある|
|BlendState.AlphaBlend|アルファ値を不透明度とする合成。ただし、アルファ乗算済みのR, G, B用。基本的な半透明表現。正しい半透明のためには重ね合わせ順序が重要。[[XNA Game Studio 4.0]]のコンテンツパイプラインでは、アルファ乗算済みが既定値になっている|
|BlendState.NonPremultiplied|アルファ値を不透明度とする合成。アルファ乗算済みではない一般的なR, G, B用|
|BlendState.Opaque|不透明(既定値)|
|DepthStencilState.Default|既定値。深度バッファの読み書きあり(既定値)|
|DepthStencilState.DepthRead|読み取りのみ。[[プリミティブ]]は深度バッファに影響されるが、深度バッファを更新しない|
|DepthStencilState.None|深度バッファを使わない。[[プリミティブ]]は上書きされ、深度バッファを更新しない|
|RasterizerState.CullClockwise|時計回りの[[プリミティブ]]はカリングされる|
|RasterizerState.CullCounterClockwise|反時計回りの[[プリミティブ]]はカリングされる(既定値)|
|RasterizerState.CullNone|カリングしない。[[プリミティブ]]は両面とも描画される|
|SamplerState.AnisotropicClamp|異方性フィルタリング/クランプ|
|SamplerState.AnisotropicWrap|異方性フィルタリング/ラッピング|
|SamplerState.LinearClamp|線形フィルタリング/クランプ|
|SamplerState.LinearWrap|線形フィルタリング/ラッピング(既定値)|
|SamplerState.PointClamp|ポイントフィルタリング/クランプ|
|SamplerState.PointWrap|ポイントフィルタリング/ラッピング|

!!グラフィックスデバイスのレンダーステートを初期値に戻す場合
{{{
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
for (int i = 0; i < 16; i++)
    GraphicsDevice.SamplerStates[i] = SamplerState.LinearWrap;
}}}

*参考: http://blogs.msdn.com/ito/archive/2010/03/25/renderstate-where-are-you.aspx
!お勧めの操作の受付方法について

 [[Xbox LIVEインディーズゲーム]]において、ユーザーから良いゲームだと思ってもらうために、ゲームの入力デバイスについて、次のような配慮を検討してみましょう。

*キーボードの入力を前提にしない
*プレイヤーが#1のゲームパッドを使うことを前提にしない
**ゲームの最初で、「AボタンまたはSTARTボタンを入力してください」といったメッセージを画面に表示し、入力を促して、使用中のゲームパッドを特定します。
*使用中と特定したゲームパッドを継続的に利用できるようにする

 これらのことは、以下のページの「プレイヤーは単一の Xbox 360 コントローラーを使用する」で触れられていますので、合わせてご覧ください。
*Xbox LIVE インディーズ ゲームのベスト プラクティス ガイド
**http://creators.xna.com/ja-JP/education/bestpractices
!Accelerometerクラス

!!!座標系
|!軸|!方向|
|+X|デバイスの右方|
|+Y|デバイスの上方|
|+Z|デバイスの前方|

!!!例
{{cs{
{{t{AccelerometerState}}} state = {{t{Accelerometer}}}.GetState();
{{t{Vector3}}} accelaration = state.Acceleration; {{c{&#47;&#47; 重力加速度[g]}}}
}}}
!ビルドの使い分け
*配布用のビルドには、最適化のあるReleaseビルドを使います。
*Windows用の開発では、エディット・コンティニュが使えるので、Debugビルドが便利です。Xbox 360用では、.NET Compact Framework上で動作するため、エディット・コンティニュはできませんが、トレースすることはできます。

!注意点
*ビルド構成のDebugビルドとReleaseビルドでは、C#コンパイラの最適化が変わる。
*「デバッグ実行」(デバッガのアタッチ)と「デバッグなしで開始」では、JIT(Just In Time)コンパイラの最適化が変わる。
*これらの違いは、浮動小数点演算コードが最適化の有無により、計算誤差が変わることがある。
*「#if」などを含む場合は当然変わる。

 よって、開発中のビルドと、配布用のビルドの両方で頻繁に動作テストすることが重要です。
 [[Windows]]と[[Xbox 360]]のように実行しているプラットフォームに合わせた動作の変更については、通常、根本の.NET Frameworkから別のアセンブリであるため、それぞれのプロジェクトを作り、コードの書き分けには条件付きコンパイルシンボルを利用します。
 次に示す方法は、あえて動的に判定するものです。

 System.Environment.OSVersionプロパティによって、実行しているプラットフォームがわかります。

|!プラットフォーム|!値(PlatformとVersion)|
| [[Xbox 360]] | Xbox 2.360.0 |
| [[Windows]] Vista (SP2) | Win32NT 6.0.6002.131072 |

※これらは実測値です。異なるバージョンが得られる可能性があります。
(古い情報です)

|!参考訳|!英語|
|個人情報の収集|Collecting personal information|
|裸体|Nudity|
|強烈な性的描写|Strong sexual content|
|児童ポルノ|Child pornography|
|現実世界の個人や集団への直接的な脅迫|Direct threats to a person or groups of people in the physical world|
|現実世界での不法行為の直接的な奨励や勧誘|Direct encouragement/solicitation of illegal behavior in the physical world|
|人道に反する犯罪、強烈かつ不快な写実的暴力|Crimes against humanity and/or intense and distasteful graphical violence|
|無認可のコンテンツ使用|Unauthorized content use|
 指定していないはずの青紫(水色ではない)が見えた場合、レンダーターゲットが初期化された状態である可能性があります。特にXbox 360の場合、レンダーターゲットは同時に1つしかないので、RenderTargetUsage.PreserveContentsを指定していないレンダーターゲットは、別のレンダーターゲットに切り替えたときに、内容が破棄されます。破棄されたレンダーターゲットを見た場合にこの現象はよく起きます。
 クリアや描画がうまくいっているか、あるいは破棄されていないか、動作を確認してみましょう。
 .NETでは通常、文字コードとして、Unicodeを使います(文字を表すchar型、文字列のstring型など)。XNA Game StudioのSpriteFontクラスでも同様です。
 Unicodeのごく一部(ASCIIコード互換)は以下の表のようになっています。独自のスプライトによる文字列描画処理など、文字コードに依存する特別な処理を記述する際の参考にしてください。

|! |!+0|!+1|!+2|!+3|!+4|!+5|!+6|!+7|!+8|!+9|!+A|!+B|!+C|!+D|!+E|!+F|
|!U+0000|(NUL)|(SOH)|(STX)|(ETX)|(EOT)|(ENQ)|(ACK)|(BEL)|(BS)|(HT)|(LF)|(VT)|(FF)|(CR)|(SO)|(SI)|
|!U+0010|(DLE)|(DC1)|(DC2)|(DC3)|(DC4)|(NAK)|(SYN)|(ETB)|(CAN)|(EM)|(SUB)|(ESC)|(FS)|(GS)|(RS)|(US)|
|!U+0020|(SP)<br>空白|&#x21;|&#x22;|&#x23;|&#x24;|&#x25;|&#x26;|&#x27;|&#x28;|&#x29;|&#x2a;|&#x2b;|&#x2c;|&#x2d;|&#x2e;|&#x2f;|
|!U+0030|&#x30;|&#x31;|&#x32;|&#x33;|&#x34;|&#x35;|&#x36;|&#x37;|&#x38;|&#x39;|&#x3a;|&#x3b;|&#x3c;|&#x3d;|&#x3e;|&#x3f;|
|!U+0040|@|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|
|!U+0050|P|Q|R|S|T|U|V|W|X|Y|Z|&#x5b;|&#x5c;|&#x5d;|&#x5e;|&#x5f;|
|!U+0060|`|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|
|!U+0070|p|q|r|s|t|u|v|w|x|y|z|&#x7b;|&#x7c;|&#x7d;|&#x7e;|(DEL)|
|!U+0080|(XXX)|(XXX)|(BPH)|(NBH)|(IND)|(NEL)|(SSA)|(ESA)|(HTS)|(HTJ)|(VTS)|(PLD)|(PLU)|(RI)|(SS2)|(SS3)|
|!U+0090|(DCS)|(PU1)|(PU2)|(STS)|(CCH)|(MW)|(SGA)|(EGA)|(SOS)|(XXX)|(SCI)|(CSI)|(ST)|(OSC)|(PM)|(APC)|
|!U+00A0|(NBSP)|&#xa1;|&#xa2;|&#xa3;|&#xa4;|&#xa5;|&#xa6;|&#xa7;|&#xa8;|&#xa9;|&#xaa;|&#xab;|&#xac;|(SHY)<br>ソフトハイフン|&#xae;|&#xaf;|
|!U+00B0|&#xb0;|&#xb1;|&#xb2;|&#xb3;|&#xb4;|&#xb5;|&#xb6;|&#xb7;|&#xb8;|&#xb9;|&#xba;|&#xbb;|&#xbc;|&#xbd;|&#xbe;|&#xbf;|
|!U+00C0|&#xc0;|&#xc1;|&#xc2;|&#xc3;|&#xc4;|&#xc5;|&#xc6;|&#xc7;|&#xc8;|&#xc9;|&#xca;|&#xcb;|&#xcc;|&#xcd;|&#xce;|&#xcf;|
|!U+00D0|&#xd0;|&#xd1;|&#xd2;|&#xd3;|&#xd4;|&#xd5;|&#xd6;|&#xd7;|&#xd8;|&#xd9;|&#xda;|&#xdb;|&#xdc;|&#xdd;|&#xde;|&#xdf;|
|!U+00E0|&#xe0;|&#xe1;|&#xe2;|&#xe3;|&#xe4;|&#xe5;|&#xe6;|&#xe7;|&#xe8;|&#xe9;|&#xea;|&#xeb;|&#xec;|&#xed;|&#xee;|&#xef;|
|!U+00F0|&#xf0;|&#xf1;|&#xf2;|&#xf3;|&#xf4;|&#xf5;|&#xf6;|&#xf7;|&#xf8;|&#xf9;|&#xfa;|&#xfb;|&#xfc;|&#xfd;|&#xfe;|&#xff;|

!参考
*U+0000~U+007Fの詳細な資料: http://www.unicode.org/charts/PDF/U0000.pdf
*U+0080~U+00FFの詳細な資料: http://www.unicode.org/charts/PDF/U0080.pdf
!SpriteFontクラス

 文字列の2D描画には、SpriteFontクラスを使う方法が簡単です。SpriteFontクラスは、いわゆるビットマップフォント方式です。XNAの[[コンテンツパイプライン]]を使って、コンパイルするWindowsにインストールされた指定フォントの指定文字を事前に画像にします。
 SpriteFontクラスを実際に描画するには、SpriteBatchクラスのDrawStringメソッドを使います。

!!再配布可能フォントパック

 SpriteFontクラスで利用できるように、XNA Game Studioとともにインストールされるフォントがあります。以下より、ダウンロードも可能です。これらのフォントは基本的な英数字と記号だけに対応していますが、安心して手軽に使えます。

*http://creators.xna.com/ja-JP/contentpack/fontpack

|再配布可能フォントパックの概要|c
|!書体名|!通常|!ボールド|
|!<FontName>|!<Style>Regular</Style>|!<Style>Bold</Style>|
|Kootenay| ○ | - |
|Lindsey| ○ | - |
|Miramonte| ○ | ○ |
|Pericles| ○ | - |
|Pericles Light| ○ | - |
|Pescadero| ○ | ○ |

[img(50%,auto)[Font.png]]

※通常、フォントは利用条件が適合するものを用意する必要があります。

!!パフォーマンス・チューニング
 string.Formatメソッドでは、ガベージを発生させますので、なるべくStringBuilderクラスを使って、文字列を構成し、StringBuilderを引数とするDrawStringメソッドを使うようにします。
 また、数値のToStringメソッドによる文字列化などもstringインスンタンスを作るため、ガベージとなります。仮にガベージ・コレクションがパフォーマンス低下の原因である場合の改善方法は、ToStringメソッドに頼らないで、StringBuilderクラスに文字を並べる独自の処理を作ることです。
!テクスチャの異方性フィルタリングを有効にする([[XNA Game Studio 3.1]])

!!16x異方性フィルタリングをC#コードから設定する例
※SamplerStates[0]を使う場合
{{{
GraphicsDevice.SamplerStates[0].MagFilter = TextureFilter.Anisotropic;
GraphicsDevice.SamplerStates[0].MinFilter = TextureFilter.Anisotropic;
GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.Linear;
GraphicsDevice.SamplerStates[0].MaxAnisotropy = 16;
}}}

!!16x異方性フィルタリングをエフェクトファイル(HLSLコード)から設定する例
※「Sampler」で「Texture」をルックアップする場合
{{{
texture Texture;
sampler Sampler = sampler_state {
	Texture = <Texture>;
	MagFilter = ANISOTROPIC;
	MinFilter = ANISOTROPIC;
	MipFilter = LINEAR;
	MaxAnisotropy = 16;
};
}}}
 XNA(「[[XNA Game Studio 4.0]]」「[[XNA Game Studio 3.1]]」「[[Xbox LIVEインディーズゲーム]]」など)に関する若干の情報を提供しています。内容は修正または更新することがあります。各項目の情報は、どのXNA Game Studioのバージョンに対応しているかにご留意下さい。

*[[XNA Game Studioについて]]
*[[インディーズゲーム(同人ゲーム)全般について|インディーズゲーム]]

<<tiddler XNAの近況>>

!XNA開発者向け
*[[XNA開発初級FAQ]]
*[[XNA開発中級FAQ]]
*[[.NET Framework開発FAQ]]
*[[ゲームの配布方法]]
*[[Xbox LIVEインディーズゲーム]]
**[[Xbox LIVEインディーズゲームでの公開]]
***[[ゲームを作る|Xbox LIVEインディーズゲーム用にゲームを作る]] → [[ゲームを提出する|Xbox LIVEインディーズゲームにゲームを提出する]] → [[ピアレビュー]] → [[ゲームをプレイする|Xbox LIVEインディーズゲームのゲームをプレイする]]
***[[ピアレビューに向けての準備]]
**[[Xbox LIVEインディーズゲームの設定価格]]
**[[お試し版]](お試し版モード)
**Xbox LIVEインディーズゲームでのゲームのプロモーション
***[[ご利用コード]] / スポットライト
**[[XBLIGの「更新版が公開されています」画面]]
*[[XNAクリエーターズクラブ]]
**ロイヤリティーの支払いに関する留意点→http://creators.xna.com/ja-JP/news/taxandpaymentquestions
**よくある質問→http://creators.xna.com/ja-JP/faq
*[[XNA関連サイト]]

*グラフィックス
**[[バッファの形式]]
**[[フォグ]]
*[[入力デバイス]](お勧めの操作の受付方法について)
**ゲームパッド(Xbox 360コントローラー)
***ゲームパッドは最大4つつながります。配布するようなゲームでは、一人プレイなどで、どの番号(PlayerIndex)のゲームパッドから操作してもいいものは、最初にゲームパッドのAボタンやSTARTボタンへの入力を促して、どの番号のゲームパットを使っているかを決定し、そのゲームパッドで継続して操作できるようにしましょう。
**キーボード
**[[マウス]]
**タッチパネル(マルチタッチ)
*[[ストレージ]](ファイルのロードとセーブ)
**[[実行環境を動的に判別する]]
*ローカライズ
**多言語対応
***[[ピアレビューの言語について]]
***[[言語設定を判別する]]
***[[ゲーム用語]]
*[[動作テストについて]]
*パフォーマンス・チューニング
**[[EffectPassCollectionクラスのforeach文でガベージが発生してしまう問題を回避する方法]]
**[[グラフィックスのパフォーマンス・チューニング]]
**[[StringBuilder.AppendFormatの書式を事前解析で高速化]]
*応用編
**[[Gameクラスを使わないXNA Game Studioプログラム]]

*XNAのプラットフォーム
**[[Windows]]
**[[Xbox 360]]
***[[Xbox 360のスレッド]]
**[[Zune]]
***[[Zune HD]]
**[[Windows Phone 7]]

*[[XNAのバージョン]]
**[[XNA開発者用ファイル履歴]]
**[[XNA Game Studio 4.0]]
***プラットフォーム「[[Windows Phone 7]]」対応
***[[ダイナミックオーディオ]]
***[[マイク入力]]
***プロファイルレベル「Reach」と「HiDef」
****Reach
*****[[エフェクトのコスト]]
***[[Windows Phone 7]]で使える関連API([[Silverlight 4]]と共通)
****Microsoft.Devices名前空間
*****[[VibrateControllerクラス]] : [[Windows Phone 7]]デバイスの振動
****Microsoft.Phone.Notification名前空間 : プッシュ通知
****System.Device.Location名前空間 : デバイスの位置情報

**[[XNA Game Studio 3.1 Zune Extensions]]([[Zune HD]]用のAPI拡張)
***Zune HDメディアプレイヤーを対象にして開発できる
***Zune HD用にXNA Frameworkへ新たにタッチAPIの追加
****TouchPanelクラス
***Zune HD用にXNA Frameworkへ新たに加速度センサーAPIの追加
****加速度計(Accelerometerクラス)
**[[XNA Game Studio 3.1]]
***[[アバター]]
****[[アバターのサンプル]]
****[[アバター機能の利用ルール]]
***[[Xbox LIVEパーティ]]
***[[ビデオ再生]]
***オーディオAPI(新しい用法の[[SoundEffect.Play]])
***[[コンテンツパイプライン]]の強化
****[[自動XNBシリアライゼーション]]
***[[XACT3]]のサポート
***Visual Studioでの変更内容(3.0と3.1の両方のプロジェクト作成および3.0から3.1へのアップグレード)
**[[XNA Game Studio 3.0]]
***[[マーケットプレース]]・[[お試し版]]モード機能
***フレンドの招待機能
***Visual Studio 2008に対応IDEが移行
***C#3.0対応
***アセット(.XNB)圧縮対応
***[[Zune]]対応
***[[ClickOnce]]配布
***SoundEffect API
***Media API
***リッチプレゼンス
 ご意見・ご感想などは、ブログのコメントもしくはメールをご利用ください。
 誤字等の簡単なご指摘は、twitterのxelfia宛へのダイレクトメッセージ(http://twitter.com/direct_messages/create/xelfia)でも構いません。

----

※以下の項目は管理・編集者用のメニューです。

;SiteTitle & SiteSubtitle: 
:このサイトのタイトルおよびサブタイトル。この上に表示されています。<br>保存後はブラウザのタイトルバーにも表示されます。
;MainMenu: 
:メニュー。たいていは左側に表示されています。
;DefaultTiddlers: 
:ここにtiddlerの名前が書かれていると、この TiddlyWiki を開いたときに、<br>そのtiddlerが初期表示されます。
あなたの名前(編集したtiddlerに表示されます): <<option txtUserName>>
 ゲームを多言語に対応しようと考えた場合には、自動的にユーザーに適正な言語を既定の設定にしてゲームを提供したいものです。
 それを可能にするには、システムの言語設定を判別する必要があります。その方法を次にあげます。

 System.Globalization.CultureInfo.CurrentCultureプロパティの情報を見ることで、言語設定が判別できます。この方法は、.NET Frameworkあるいは.NET Compact Frameworkで動く[[XNA Game Studio]]で使え、[[Windows]]と[[Xbox 360]]ともに有効な情報が得られます。[[Xbox 360]]ではシステムの言語設定に応じた情報が得られます。

 System.Globalization.CultureInfo.CurrentCultureプロパティは、特定のロケールの設定(System.Globalization.RegionInfo.CurrentRegionプロパティ)との組み合わせにも影響されます。
※ただし、中国語(簡体字)と中国語(繁体字)は、言語の設定で決まります。

!!一覧

※これらは、[[Xbox 360]]本体の「言語」と「国や地域」の設定に対するSystem.Globalization.CultureInfo.CurrentCultureプロパティの値です。

|! Xbox 360/本体の設定/言語|! Xbox 360/本体の設定/国や地域 | ! EnglishName |! LCID |! 2文字ISO |! 3文字ISO |! CultureInfo |
| 日本語 | (すべて) | Japanese (Japan) | 1041 | ja | jpn | ja-JP |
| 한국어 | (すべて) | Korean (Korea) | 1042 | ko | kor | ko-KR |
| 中文(简体) | シンガポール | ? | ? | zh | zho | zh-SG |
|~| (その他すべて) | ? | ? | zh | zho | zh-CH |
| 中文(繁體) | 香港特別行政区 | Chinese (Hong Kong S.A.R.) | 3076 | zh | zho | zh-HK |
|~| (その他すべて) | Chinese (Taiwan) | 1028 | zh | zho | zh-TW |
| English または English (QWERTY Keyboard) | オーストラリア | English (Australia) | 3081 | en | eng | en-AU |
|~| カナダ | English (Canada) | 4105 | en | eng | en-CA |
|~| イギリス | English (United Kingdom) | 2057 | en | eng | en-GB |
|~| アイルランド | English (Ireland) | 6153 | en | eng | en-IE |
|~| ニュージーランド | English (New Zealand) | 5129 | en | eng | en-NZ |
|~| 南アフリカ | English (South Africa) | 7177 | en | eng | en-ZA |
|~| (その他すべて) | English (United States) | 1033 | en | eng | en-US |
| Français | ベルギー | French (Belgium) | 2060 | fr | fra | fr-BE |
|~| カナダ | French (Canada) | 3084 | fr | fra | fr-CA |
|~| スイス | French (Switzerland) | 4108 | fr | fra | fr-CH |
|~| (その他すべて) | French (France) | 1036 | fr | fra | fr-FR |
| Deutsch | オーストリア | German (Austria) | 3079 | de | deu | de-AT |
|~| スイス | German (Switzerland) | 2055 | de | deu | de-CH |
|~| (その他すべて) | German (Germany) | 1031 | de | deu | de-DE |
| Italiano | スイス | Italian (Switzerland) | 2064 | it | ita | it-CH |
|~| (その他すべて) | Italian (Italy) | 1040 | it | ita | it-IT |
| Português (Brasil) | ポルトガル | Portuguese (Portugal) | 2070 | pt | por | pt-PT |
|~| (その他すべて) | Portuguese (Brazil) | 1046 | pt | por | pt-BR |
| Español | チリ | Spanish (Chile) | 13322 | es | spa | es-CL |
|~| コロンビア | Spanish (Colombia) | 9226 | es | spa | es-CO |
|~| メキシコ | Spanish (Mexico) | 2058 | es | spa | es-MX |
|~| (すべて) | Spanish (Spain) | 3082 | es | spa | es-ES |
| Русский | (すべて) | Russian (Russia) | 1049 | ru | rus | ru-RU |
| Polski | (すべて) | Polish (Poland) | 1045 | pl | pol | pl-PL |

!!サンプル
 以下はSystem.Globalization.CultureInfo.CurrentCultureプロパティの情報の一部を画面に文字列で表示するサンプルです。サンプルではいくつか併記していますが、実践上ではどれか都合がよいものを選ぶと良いでしょう。

 多言語対応するには、この判定結果を使って、言語別の情報を表示するようにしましょう。

※以下のサンプルでは、アセット名「Default」のスプライトフォントを用意してください。

!!サンプルコード

{{cs{
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace MultiLanguage {
	public class CultureGame : Microsoft.Xna.Framework.Game {
		readonly GraphicsDeviceManager graphics;
		SpriteBatch spriteBatch;
		SpriteFont font;
		readonly StringBuilder text = new StringBuilder();

		public CultureGame() {
			graphics = new GraphicsDeviceManager(this);
			Content.RootDirectory = "Content";
		}

		protected override void LoadContent() {
			spriteBatch = new SpriteBatch(GraphicsDevice);
			font = Content.Load<SpriteFont>("Default");
		}

		protected override void Update(GameTime gameTime) {
			if (GamePad.GetState(PlayerIndex.One).IsButtonDown(Buttons.Back))
				Exit();
			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime) {
			GraphicsDevice.Clear(Color.CornflowerBlue);

			spriteBatch.Begin();

			var culture = System.Globalization.CultureInfo.CurrentCulture;

			text.Remove(0, text.Length);
			text.AppendFormat(
@"EnglishName: {0}
LCID: {1}
Two Letter ISO Language Name: {2}
Three Letter ISO Language Name: {3}
",
				culture.EnglishName,
				culture.LCID,
				culture.TwoLetterISOLanguageName,
				culture.ThreeLetterISOLanguageName);

			var resolution = new Vector2(GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
			var size = font.MeasureString(text);
			spriteBatch.DrawString(font, text,
				(resolution - size) * 0.5f, Color.Black);
			spriteBatch.End();

			base.Draw(gameTime);
		}
	}
}
}}}