<!--{{{-->
<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のMathHelper静的クラスにあります。

!疑似乱数を作るには?

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

!!XNA Game Studio 3.1の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]])のコードを書き分けるには、次のようにします。
{{{
#if XBOX
    // Xbox 360用コード
#elif WINDOWS
    // Windows用コード
#endif
}}}
 このように、XNA用のプロジェクトには条件付きコンパイルシンボルがあらかじめ定義されています。
 多くの部分は共通のコードで書けますが、機能の差などによって書き分ける必要がある場合に使います。
 [[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 2など)が無償で利用できます。詳細な利用条件などについては、関連サイトをよくご確認ください。

*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;
	}
}
//}}}
/***
|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の表示方法を決定します。"
	});
//}}}
[[目次]]
----
[[上位ページ|index.html]]
[[ホーム|../index.html]]
----
©2009 XELF
----
[[RSS|xna.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://xelf.info/xna/xna.html
 [[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適用」)。
**確保できないときは例外になる。
**ループ演奏の指定が可能。
.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";
	}
};
//}}}
!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 2008」/<br/>「Visual C# 2008 Express」|!「Visual Studio 2005」/<br/>「Visual C# 2005 Express」|!それ以前のVisual Studio|
|[[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/
 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のプロジェクトを作った場合、.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 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]])
*コンテント・パイプラインの強化
**自動シリアライゼーション

!![[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機能への対応の追加はないようです。

!!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}}};
    }
}
}}}

!!Accelerometerクラス

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

!!!例
{{cs{
{{t{AccelerometerState}}} state = {{t{Accelerometer}}}.GetState();
{{t{Vector3}}} accelaration = state.Acceleration; {{c{&#47;&#47; 重力加速度[g]}}}
}}}
!新機能
*[[Windows Phone 7 Series]]上でのハードウェア・アクセラレーションされた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 Seriesを含めてどのプラットフォームでも動く
**HiDef(ハイデフ): Xbox 360とハイエンドWindowsで動く。Reachの全APIが動く
*多くのグラフィックスAPIの改良。API変更あり
*アセンブリ「Microsoft.Xna.Framework.dll」を、利用できるプラットフォームがわかりやすいようにいくつかのアセンブリに分割

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

!リリース時期: 2010-04 プレビュー版(2010-03-10時点の情報)

※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
 [[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 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]]
*公式の案内
http://msdn.microsoft.com/ja-jp/xna/cc627246.aspx

!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]]で動作するゲーム用のフレームワークです。プログラミングによって、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クラスを使って再生することはできます。

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

!動的生成した波形を鳴らせますか?
 残念ながらXNAのAPIにはありません。

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

!ゲームの状態をセーブ・ロードするには?
 StorageContainerクラス(Microsoft.Xna.Framework.Storage名前空間)を使うことでできます。処理内容は書く必要があります。
|!リリース時期|!名称|!ファイル名|!ファイルサイズ(Bytes)|! ファイル(※古いものは公開終了しています)|
|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| |

[[XNA デベロッパー センター|http://www.microsoft.com/japan/msdn/xna/default.aspx]]
[[XNA Creators Club Online|http://creators.xna.com/]]
[[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]]
!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
**代案が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|

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

!!ゲームを送信する

 「プレイテストとピアレビューのページ」では、.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点|
|!MSNビデオ|YouTubeに投稿したゲームプレイ(またはゲームのマーケティング)のビデオのURL。当初は、MSN Videoのユーザービデオ投稿サービス「Soapbox」に対応していましたが、終了したため、YouTubeに変更になります。|

!!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の設定によって.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への対応の有無は発表待ちです。

!!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はこのサーバーの詳細情報を記録するために自動的に作成されました
 [[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.

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

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

!規制物質の使用

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

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

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

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

アバターのプロポーション(体型)は元の設定から変化した形にできません。アバターはプロポーションを変えない限り大きさを変えることはできます。
※ここでは、[[Xbox LIVEインディーズゲーム]]に限らず、インディーズゲーム(同人ゲーム)全般について記しています。

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

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

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

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

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

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

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

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

!Windows用

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

!Xbox 360用
*[[Xbox LIVEインディーズゲームでの公開]]に挑戦する
*.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インディーズゲーム]]では「追加コンテンツ」機能は利用できない|
 ゲームのユーザーデータのロードやセーブを可能にするためには、Microsoft.Xna.Framework.Storage名前空間にあるストレージ機能を使います。

!!ストレージの種類
|!ストレージの種類|!パスの決定方法|
|タイトルストレージ|StorageContainer.TitleLocationプロパティを使う|
|ユーザーストレージ|StorageDevice.OpenContainerメソッドから作成したStorageContainerのPathプロパティを使う|

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

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

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

!!ユーザーストレージの処理について

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

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

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

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

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

 これは、他のクリエーターのゲームのレビューにおいて、ストレージに関する不具合が疑われる場合などで、「ゲームの初期状態」を検証するために便利です。
 グラフィックス用のバッファの形式は、用途によって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マーケットプレース]]に並んでいる|

!!①ゲームの情報

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

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

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

*「ダウンロード」をクリックして、.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単語でも含んでいる言語は、「対応している言語」のチェックボックスにチェックをつけましょう。
※各言語で不適切な表現を含まないように、レビューされなければなりません。

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

 あるゲームにおいて、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)}

※パッケージの言語対応表示{英語} | パッケージ内容の実際の言語対応{日本語}  → 「ゲームの情報に記載されている内容が不適切」の可能性
!デザイン時に考慮したい点について

 [[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
 XNAでは、Windowsでのみマウスをサポートしています。

 WindowsでのXNAウィンドウ上でOSによるマウスカーソルが見えるようにするには、GameクラスのIsMouseVisibleプロパティを使います。
{{{
IsMouseVisible = true;
}}}
 ここでは[[Xbox LIVEマーケットプレース]]を指しています。
!お勧めの操作の受付方法について

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

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

 これらのことは、以下のページの「プレイヤーは単一の Xbox 360 コントローラーを使用する」で触れられていますので、合わせてご覧ください。
*Xbox LIVE インディーズ ゲームのベスト プラクティス ガイド
**http://creators.xna.com/ja-JP/education/bestpractices
!ビルドの使い分け
*配布用のビルドには、最適化のある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を指定していないレンダーターゲットは、別のレンダーターゲットに切り替えたときに、内容が破棄されます。破棄されたレンダーターゲットを見た場合にこの現象はよく起きます。
 クリアや描画がうまくいっているか、あるいは破棄されていないか、動作を確認してみましょう。
 XNA(「[[XNA Game Studio 3.1]]」「[[Xbox LIVEインディーズゲーム]]」など)に関する若干の情報を提供しています。内容は修正または更新することがあります。

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

!XNA関連の近況
!!2010-03-10
 [[XNA Game Studio 4.0]]がGDC 2010で公表されました。対応プラットフォームに[[Windows Phone 7 Series]]が加わります。「[[Windows Phone 7 Series]]上でのハードウェア・アクセラレーションされた3D API」「[[Visual Studio 2010]]との統合」「Audio APIにバッファされたオーディオのサポートを追加」などが新機能です。
!!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開発者向け

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

*[[バッファの形式]]
*[[動作テストについて]]
*[[入力デバイス]](お勧めの操作の受付方法について)
**ゲームパッド(Xbox 360コントローラー)
***ゲームパッドは最大4つつながります。配布するようなゲームでは、一人プレイなどで、どの番号(PlayerIndex)のゲームパッドから操作してもいいものは、最初にゲームパッドのAボタンやSTARTボタンへの入力を促して、どの番号のゲームパットを使っているかを決定し、そのゲームパッドで継続して操作できるようにしましょう。
**キーボード
**[[マウス]]
*[[ストレージ]](ファイルのロードとセーブ)
*XNAのプラットフォーム
**[[Windows]]
**[[Xbox 360]]
***[[Xbox 360のスレッド]]
**[[Zune]]
***[[Zune HD]]
**[[実行環境を動的に判別する]]

*ローカライズ
**多言語対応
***[[ピアレビューの言語について]]
***[[言語設定を判別する]]
***[[ゲーム用語]]

*パフォーマンス・チューニング
**[[EffectPassCollectionクラスのforeach文でガベージが発生してしまう問題を回避する方法]]

*[[XNAのバージョン]]
**[[XNA開発者用ファイル履歴]]
**[[XNA Game Studio 4.0]]
**[[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]])
***コンテント・パイプラインの強化
****自動シリアライゼーション
***[[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
***リッチプレゼンス
 ご意見・ご感想などは、ブログのコメントもしくはメールをご利用ください。

----

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

;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);
		}
	}
}
}}}