1 /*                      ------ new ValueConstractors.js
  2 コーディング中なので、マージは保留   2016- 12.24
  3     xMap/Xpsで使用する値オブジェクト群
  4 
  5     新規のオブジェクトは、基本的に new コンストラクタ() ではなく
  6     Object.create(親オブジェクト)又は、各クラスの クラス.newオブジェクト() メソッドで作成すること
  7     各々のValueオブジェクトはnas.xMapElementのcnontentプロパティとなる
  8     置きかえタイムラインの(区間)値としては参照を持つ
  9     タイムシート上は回数未定で同じ値が再利用される
 10 
 11 このソースは、nasライブラリの基底オブジェクトを組み合わせて構成される
 12 タイムライントラックの値(=xMapに登録されるelementの値)となるオブジェクト群
 13 
 14 ライブラリを分割して nas_AnimationValues.js として nas_common.jsの後 xpsio mapioの前に読み込むものとする
 15 
 16             nas.Animation<Values>
 17 
 18 xMapElementの値オブジェクト
 19 xMapElementを介してXpsTimelineSectionの値となる
 20 
 21 nas.AnimationCamerawork     抽象化された撮影指示を記述する値オブジェクト
 22 nas.AnimationComposite      画像合成を記述する値オブジェクト
 23 nas.AnimationDesctiption    注意点や特記内容を記述するオブジェクト
 24 nas.AnimationGeopmetry      要素の配置を記述する値オブジェクト
 25 nas.AnimationReplacement    画像データを保持してその置き換えを記述するオブジェクト
 26 nas.AnimationSound          音響情報を記述するオブジェクト
 27 nas.AnimationDialog         セリフ情報を記述するオブジェクト
 28 
 29 */
 30  
 31 
 32  
 33 /**
 34  *  置きかえ(セル)タイムラインのパース
 35  *  
 36  contentTextはxMapの記述の該当部分を改行区切りテキストで与える
 37  
 38  データ型式は 第一、第二型式を自動判別
 39 
 40     第一型式
 41 ^<group>\t<elementID>[\t<optionString>[\t<comment>]]$   
 42 エントリーの定義を兼ねる
 43  
 44     第二型式
 45 ^\t<property> = <value>$
 46  第二型式(プロパティ名=値)型式の場合はそのまま使用
 47 
 48 
 49  第二型式に当てはまらない場合は、第一型式とし最大4フィールドのタブ区切りテキストとみなす
 50  =冒頭から3つまでのタブで分割する
 51 
 52 
 53  第一フィールドは、グループ名パース時点のみの情報
 54  第二フィールドは、エレメント名 エレメント名にグループ記述が欠けている場合はこれを補う?
 55  第三フィールドは、オプションプロパティ URI,width,height,offsetX,offsetY,offsetR
 56  第四フィールドは、エレメントに対するコメント
 57  
 58   csvパーサを通してプロパティに割り付けを行う
 59 第3フィールド以降、データ内のタブを含めすべての記述がエレメントに対するコメントプロパティとなる
 60  
 61 情報はすべて省略可能
 62 省略時は、各要素の親となるグループの持つプロパティを引き継ぐ
 63 
 64 以上、各エレメント共通
 65 
 66 
 67 以下種別ごとの第一型式情報並び(エレメントの配置)フォーマット
 68 
 69     置きかえタイムラインエレメント    
 70 ["file","size.x","size.y","offset.x","offset.y","offset.r"]
 71 
 72     カメラワークタイムラインエレメント
 73 [フィールドテキスト]     フィールド記述テキストは別定義のパーサに通す 16夏改装では保留
 74 
 75     エフェクトタイムラインエレメント
 76 [エフェクトテキスト]     エフェクト記述テキストは別定義のパーサに通す 16夏改装では保留
 77 
 78 xMapのパース時は、ドキュメントの記述を整形してそれを引数としてオブジェクトを初期化する
 79 
 80 XPSのデータをパースする場合は、データ記述からキーワードを抽出して適合するxMapエレメントを検索する
 81 検索に外れた場合は、デフォルトでオブジェクトを初期化
 82 都度値を与えてxMapに登録する
 83 
 84 xMapがない場合(暫定コード)では、仮のxMapデータにエントリを送り以降の再利用に供する
 85 
 86 
 87 以下 各値オブジェクトに共通
 88 
 89 親オブジェクト参照としてparentプロパティを置く
 90 基礎プロパティからの設定拡張のフラグとして extendedプロパティ
 91 
 92 一時的にセクションの値として初期化する場合は、第二引数が第一形式で与えられる
 93 
 94     new nas.AnimationReplacement(null,"GroupID\tElementName");
 95         または
 96     new nas.AnimationReplacement(Object xMapElmentGroup,"GroupID\tElementName");
 97 
 98 parent オブジェクトなしで初期化される場合があるので要注意
 99 その場合は 可能な限りGroupを抽出してparentを設定して不能な場合はnullのままにしておく
100 
101  */
102 nas.AnimationReplacement=function(myParent,myContent){
103     this.parent = (myParent)? myParent : null     ;//xMapElementGroup or null
104     this.contentText = (myContent)? myContent : 'blank-cell';//xMap上のコンテントソースを保存する 自動で再構築が行なわれるタイミングがある
105                                                    //myContent undefined で初期化を行った場合の値は blank-cell
106     this.name                                     ;//素材名(グループ名はあっても除かない)
107     this.source                                   ;//nas.AnimationElementSource
108     this.comment                                  ;//コメント文字列 エレメントの注釈プロパティ-xMap編集UIのみで確認できる
109     this.extended = false;
110 
111     this.formGeometry                             ;//nas.AnimationFieldオブジェクト
112     this.resolution                               ;//要素の解像度   nas.Resolution()
113     this.size                                     ;//要素のサイズ   nas.Size()
114     this.offset                             ;//要素の原点オフセット   nas.Offset()
115     this.pegOffset                          ;//要素のペグオフセット* これらはオブジェクトで統合?
116     this.overlay                            ;//カブセの対象となるエレメントへの参照  < elementのプロパティへ移行が必要?
117     
118     this.parseContent();
119 }
120 /**
121     //  引数なし または引数が1つで文字列'basic'またはfalseと判断される場合は標準保存形式出力
122     標準保存形式(グループ名/エレメント名+主要プロパティの1行出力)
123 ^<group>\t<cellDescription>\t< ここまではElementObjectの出力範囲
124 <proppertyValues>\t<comment>
125126 "./stages/kd/kt#00[pilot]__s-c001_kd.psd///kd/A/0001+",254mm,142.875mm,127mm,71.4375mm	testOverlay
127 
128 proppertyValuesは、comma区切りで以下の順のデータ
129 ["<source>"[,size.X,size.Y[,offset.X,offset.Y[,offset.R]]]]
130 末尾から順にすべて省略可能
131 各エントリに登録のない場合はデフォルトの値が使用される
132 
133     //  引数が 'extended'の場合は拡張保存形式で返す
134     拡張保存形式(グループ名,エレメント名を含まないタブを先頭にした複数行出力)
135 ^\t<propname> = <proppertyValue>$\n
136137 	file = "./stages/kd/kt#00[pilot]__s-c001_kd.psd///kd/A/0001+"
138 	
139 	
140     //  引数が一つ以上ある場合の処理
141 
142 */
143 nas.AnimationReplacement.prototype.toString=function(exportForm){
144 //return this.contentText;//動作確認用ダミー行
145 
146     if(exportForm == 'extend'){
147         var resultArray=[];
148         if(this.source)   resultArray.push('\tfile = "'    + this.source.toString(true)+'"');
149         if(this.size)     resultArray.push('\tsize = '     + this.size.toString());
150         if(this.offset)   resultArray.push('\toffset = '   + this.offset.toString());
151         if(this.rotation) resultArray.push('\trotation = ' + this.rotation.toString());
152         if(this.comment)  resultArray.push('\tcomment = '  + this.comment);
153         return resultArray.join("\n");
154     }else if ((arguments.length==0)||((arguments.length==1)&&(! arguments[0]))||(exportForm == 'basic')){
155         var resultArray=[];
156         
157         if(this.source)   resultArray.push('"'+this.source.toString()+'"');
158         if(this.size)     resultArray.push(this.size.toString());
159         if(this.offset)   resultArray.push(this.offset.toString());
160         if(this.rotation) resultArray.push(this.rotation.toString());
161         resultArray = [resultArray.join(",")];
162         if(this.comment) resultArray.push(this.comment);
163         return ([this.parent.name,this.name,resultArray.join("\t")]).join('\t');
164     }
165 }
166 //nas.AnimationReplacement.prototype.valueOf=function(){
167 //    return nas.parseNumber(nas.normalizeStr(this.name).replace(/^[^0-9]*/,""))
168 //valueOfの設定自体にあまり意味が無いのでやめたほうがヨサゲ 
169 //}
170 /** 与えられたオブジェクトとプロパティ同士を比較して 変更状態を返す
171     引数
172 対照する基準値(オブジェクト)
173     戻り値
174 変更状態コード
175 0   変化なし    最小標準出力に対応
176 1   標準変更    拡張標準出力に対応
177 2   重度変更    フルダンプに対応
178 */
179 nas.AnimationReplacement.prototype.compareWith= function(targetValue){
180     var igunoreProps    =['contentText','source'];
181     var basicProp       =['size','offset','comment'];
182     var extendProps     =['pegOffset',];
183 }
184 /** タイミングパラメータに従って指定されたフレームのキー間の補完値を返す
185 
186    置きかえタイムラインの中間値は前方値で代表されるので基本的に戻り値は自分自身
187     オプションの状態によって(時間的)中間タイミングで後方値に切り替える
188     return endValue;
189     又はブランク状態のオブジェクトを返す
190    return new nas.newAnimationReplacement("blank");
191 */
192 nas.AnimationReplacement.prototype.interpolate= function(endValue,indexCount,indexOffset,frameCount,frameOffset,props){
193     return this;
194 }
195 
196 /** Contentをパースして プロパティを設定する内部メソッド
197 引数でcontentを与えてオブジェクト全体の値を更新することも可能
198 引数がAnimationRepalcementであった場合は、全プロパティを継承して引き写す
199 ただし引数と同じジョブ内のコレクションに追加を行う場合は、失敗するので要注意
200 
201 xMap形式のデータをパースする nas.AnimationXXX シリーズオブジェクトの共通メソッド
202 xMapパーサから呼び出す際に共通でコールされる
203 引数が与えられない場合は、現在の保持コンテンツを再パースする
204 */
205 nas.AnimationReplacement.prototype.parseContent = function(myContent){
206 //    var blankRegex  = new RegExp("^[xXxX×〆00]$");//カラ判定 システム変数として分離予定
207     var interpRegex = new RegExp("^[\-\+=○●・a-zア-ン]$|^\[[^\]]+\]$");//中間値補間(動画記号)サイン 同上
208     var valueRegex  = new RegExp("^[\(<]?([A-Z][\-_\.]?)?[0-9].+[>\)]?$");//無条件有効値 同上
209 //    var valueRegex  = new RegExp("^[\(<]?[0-9]+[>\)]?$");//無条件有効値 同上
210 
211 //引数がなければ現在のコンテンツを再パース
212     if(typeof myContent == 'undefined'){
213         myContent = this.contentText;
214     }else{
215         
216         this.contentText = myContent;
217     }
218 /*
219     AnimatiopnReplacementの特殊値として
220     contentText='blank-cell'を設ける
221     AnimationElementSource("")
222     サイズは不問  シンボルとしての「カラセル」
223 
224 */
225     if(myContent == 'blank-cell') return this;
226     var isGroup = (myContent.indexOf('[')==0)? true:false;
227 //第一形式グループ ^[\<group>\t<typeName>[\t<option-text>[\t<comment>]]\]$
228 //第二形式エントリ ^<group>\t<name>[\t<option-text>[\t<comment>]]$
229 
230     myContent = String(myContent).split('\n');
231     for ( var line = 0 ; line < myContent.length ; line++){
232 
233     if((isGroup)&&(myContent[line].indexOf('[')==0)) myContent[line] = myContent[line].slice(1,-1);//ブラケット削除
234 
235         if(myContent[line].match(/^\t(\S+)\s*=\s*(.+)\s*$/)){
236             //第二形式(タブ開始)でプロパティ別のデータ更新を行う
237             this.extended=true;
238 
239             var myProp=RegExp.$1;var valueArray=csvSimple.parse(RegExp.$2)[0];
240 
241             switch(myProp){
242             case "file":
243                 this.file = new nas.AnimationElementSource(valueArray[0]);
244             break;
245             case "resolution":
246                 this.resolution= new nas.Resolution(valueArray.join(','));
247             break;
248             case "resolution.X":
249                 this.resolution.x = new nas.UnitResolution(valueArray[0],this.resolution.type);
250             break;
251             case "resolution.Y":
252                 this.resolution.y = new nas.UnitResolution(valueArray[0],this.resolution.type);
253             break;
254             case "size":
255                 this.size = (valueArray.length<3)?
256                     new nas.Size(valueArray[0],valueArray[1]):new nas.Size(valueArray[0],valueArray[1],valueArray[2]);
257             break;
258             case "size.X":
259                 this.size.x = new nas.UnitValue(valueArray[0]);
260             break;
261             case "size.Y":
262                 this.size.y = new nas.UnitValue(valueArray[0]);
263             break;
264             case "offset":
265                 this.offset = (valueArray.length<3)?
266                     new nas.Offset(valueArray[0],valueArray[1]):new nas.Offset(valueArray[0],valueArray[1],valueArray[2]);
267             break;
268             case "offset.X":
269                 this.offset.x = new nas.UnitValue(valueArray[0]);
270             break;
271             case "offset.Y":
272                 this.offset.y = new nas.UnitValue(valueArray[0]);
273             break;
274             case "offset.R":
275                 this.offset.r = new nas.UnitAngle(valueArray[0]);
276             break;
277             case "pegOffset":
278                 this.offset = (valueArray.length<3)?
279                     new nas.Offset(valueArray[0],valueArray[1]):new nas.Offset(valueArray[0],valueArray[1],valueArray[2]);
280             break;
281             case "pegOffset.X":
282                 this.offset.x=new nas.UnitValue(valueArray[0]);
283             break;
284             case "pegOffset.Y":
285                 this.offset.y=new nas.UnitValue(valueArray[0]);
286             break;
287             case "pegOffset.R":
288                 this.offset.r=new nas.UnitAngle(valueArray[0]);
289             break;
290            default:
291                 this[myProp]=valueArray[0];
292             }
293         } else if(myContent[line].match(/^(\S+)\t?(\S+)\t?([^\t]+)?\t?(.*)$/)){
294         // 第一形式の再パース
295 //console.log(myContent[line]);
296             var myGroup=RegExp.$1; //グループの再パースは行われない
297             var myName =RegExp.$2;
298             var myComment=RegExp.$4;
299             var valueArray=nas.parseDataChank(RegExp.$3);
300             var numeProps =[["size","x"],["size","y"],["offset","x"],["offset","y"]];
301 
302 //console.log(myComment);
303 //console.log(myName);
304 //console.log(valueArray);
305 //console.log(this);
306 /*
307     フィールド文字列であった場合の判定が必要 2018 10 09
308 
309 case :this.parent == null
310 */
311             if((! (this.parent))||(myGroup == this.parent.name)){
312 //                if(! isGroup) this.name = myName.replace(new RegExp('^'+myGroup+'\-'),"");
313                 if(! isGroup) this.name = myName;
314                 var numCount=0;
315                 for(var vix=0;vix<valueArray.length;vix++){
316                     switch(valueArray[vix].type){
317                     case "numeric":
318                     case "unitValue":
319                         if(numCount<numeProps.length){
320                             if(! this[numeProps[numCount][0]]){
321                                 this[numeProps[numCount][0]] = ([numeProps[numCount][0]]=='size')? new nas.Size():new nas.Offset();
322                             }
323                             this[numeProps[numCount][0]][numeProps[numCount][1]] = new nas.UnitValue(valueArray[vix].value);
324                             numCount++;
325                         }
326                     break;
327                     case "unitAngle":
328                         if(! this.offset) this.offset = new nas.Offset();
329                         this.offset.r==new nas.UnitAngle(valueArray[vix].value);            
330                     break;
331                     case "unitResolution":
332                         this.resolution=new nas.Resolution(valueArray[vix].value);            
333                     break;
334                     case "source":
335                         this.source=new nas.AnimationElementSource(valueArray[vix].value);            
336                     break;
337                     default:
338                         continue;
339                     }
340                 }
341                 if(myComment) this.comment = myComment;
342             }
343         }
344 
345     }
346     return this;    
347 }
348 /** 指定フレーム数に内容を展開して配列で返す
349 引数 :cellCount
350 戻値 :配列 + offset
351 */
352 nas.AnimationReplacement.prototype.getStream=function(cellCounts){
353     var myResult=new Array(cellCounts);
354     myResult[0]=(this.name)? this.name:"";
355     if (myResult[0].match(/blank(-cell)?/)) myResult[0]="×";
356     return myResult;
357 }
358 /**
359     置きかえタイムライントラックをパースしてセクションコレクションを返す
360     セクションの値を各トラックごとの値オブジェクトからxMapを介したxMapエレメントに変更する
361 
362     パース時にセクションの値判定を行う
363     ・無効記述
364     ・有効記述 値あり(xMap既存エレメント)・なし(新規エレメント)
365     
366  タイムライントラックをパースする際に統一手順としてトラックに対応するxMapエレメントグループの有無を確認する。
367 現行Jobにトラックと同名のエレメントグループが、存在しなかった場合(Stageには存在する可能性あり)は、新規にグループを作成してエントリすること。
368 この処理は、トラックパースの前段階で共通で行うことにする
369 
370 確認手段は xMap.getElementByName(グループ名)を使用
371 //XpsTimelineTrack.parseTimelineTrack() メソッドに置く
372 
373 
374 中間値補間区間の空セルに対応するために全体のブランク処理をサブセクションコレクションに置く
375 置きかえタイムラインのみの処置
376 カラ状態のみを扱うsctionCollectionを併置してセットで扱うので注意
377 各セクションのvalueは on/off(true/false)のみでオブジェクトは使用されない エレメントへのリンクも無い
378 一つのトラックをパースして二つのセクションコレクションを得る
379 値側のコレクションは、従来のカラを含むことができるが、このパーサが書き出すデータ上は従来型のカラが含まれることは無い
380 カラ区間の値は先行区間の値となる
381 カラセル区間コレクションは2つの状態しか持ち得ないので、サブセクションは発生しない
382 
383  */
384 _parseReplacementTrack=function(){
385 //    var blankRegex  = new RegExp("^[xXxX×〆00]$");//カラ判定 システム変数として分離予定
386     var interpRegex = new RegExp("^[\-\+=○◯●・a-zア-ン]$|^\[[^\]]+\]$");//中間値補間(動画記号)サイン 同上
387     var valueRegex  = new RegExp("^[\(<][^>\)]+[>\)]$|^[\(<]?([A-Z][\-_\.]?)?[0-9]\S+[>\)]?$|^[0-9]+.?$");//無条件有効値 同上
388 //    var valueRegex  = new RegExp("^[\(<]?([A-Z][\-_\.]?)?[0-9]\S+[>\)]?$|^[0-9]+.?$");//無条件有効値 同上
389     //自分自身(トラック)を親として新規セクションコレクションを作成
390     var myCollectionBlank = new XpsTimelineSectionCollection(this);//ブランクベースコレクション
391     var myCollection      = new XpsTimelineSectionCollection(this);//ベースコレクション
392 
393     var appearance    = new nas.AnimationAppearance(null,'on');
394     var disAppearance = new nas.AnimationAppearance(null,'off');
395 
396     //継続時間0で値未定初期セクションを作成
397     //値を持たないセクションをブランク値のオブジェクトとするか?
398     var currentSection=myCollection.addSection(null);
399     
400     var currentSubSection = null;
401     var currentValue      = this.getDefaultValue();
402     if(! currentValue) currentValue = new nas.AnimationReplacement('system','blank-cell');
403 //console.log(currentValue)
404     var isInterp = false;
405     var isBlank  = ((! currentValue)||(currentValue.contentText == "blank-cell"))? true:false ;//デフォルトのブランク状態を取得
406 
407 var currentSectionBlank=(isBlank)? myCollectionBlank.addSection(disAppearance):myCollectionBlank.addSection(appearance);
408 
409     var valueDetect = false;
410 /**
411     タイムライントラックのデフォルト値は、以下の手続きで取得
412     タイムラインラベルが指定するグループがあらかじめ存在する場合は、そのグループオブジェクトが保持する値
413     存在しない場合は、新規にグループを作成する。その際にトラックの種別ごとのValueオブジェクトを初期値として登録するのでその値を使用
414     XpsTimelineTrack.getDefeultValue()側で調整
415     Replacementの場合基本はブランクだが、必ずしもブランクとは限らないので要注意
416     トラック上で明示的なブランクが指定された場合は、値にfalse/null/"blank"を与える。
417 */
418     for (var fix=0;fix<this.length;fix++){
419         var currentCell=Xps.sliceReplacementLabel(new String(this[fix]));//記述をラベルとエントリに分解
420         if( currentCell.length == 1 ){ currentCell.push(this.id); }//エントリにグループ名が含まれないようならばトラックのラベルで補う
421         // ここでデータの形式は [name,groupName] となる
422         currentSection.duration ++; //
423         currentSectionBlank.duration ++;     //セクション長加算
424         if(currentSubSection) currentSubSection.duration ++ ;
425         //未記入データ これが一番多いので最初に処理しておく(処理高速化のため)
426         if(currentCell[0].match(/^([\||;]|\s+)$/)||currentCell.length==0) continue;
427         /*      ブランク判定
428             値処理に先立ってブランク関連の処理をすべて終了する
429             ブランク状態切り替え判定 カレントを切り替えて新規セクションを積む
430         */
431         var valueDetect   = false;//値検出状態初期化
432         var blankDetect   = (String(currentCell[0]).match(nas.CellDescription.blankRegex))?  true:false;//値からブランク状態を検出
433         var interpDetect  = (String(currentCell[0]).match(nas.CellDescription.interpRegex))? true:false;//括弧つきの補間サインも同時検出へ
434 //console.log(fix+":"+this[fix]+" interp:"+interpDetect + "  blank: " + blankDetect);
435         //ブランク処理判定
436         if(blankDetect){
437                 if(! isBlank){
438                     if(fix==0){
439                         currentSectionBlank.value=disAppearance;
440                         currentSection.value = new nas.AnimationReplacement('system','blank-cell');// *Blank-set
441                     }else{
442                         currentSectionBlank.duration --;
443                         currentSectionBlank=myCollectionBlank.addSection(disAppearance);
444                         currentSectionBlank.duration ++;
445                         currentSection.duration --;// *
446                         currentSection=myCollection.addSection(this.pushEntry('blank-cell','system'));// *
447                         currentSection.duration ++;// *
448                         if(currentSubSection){
449                             currentSubSection.duration --;
450                             currentSubSection = null;
451                         }
452                     }
453                     isBlank=true;
454                 }
455                 continue;
456         }
457 //         else if(fix==0){    currentSectionBlank.value=appearance; }
458         //中間値補間サインを検出したら中間値処理モード
459         //既定値以外の補間サイン検出が必要>> 規定値のみを補完サインと定義する 他の記述はコメントとして利用
460         if(interpDetect){
461               if( isBlank ){
462                  if(fix==0){
463                     currentSectionBlank.value=appearance;
464                  }else{
465                     currentSectionBlank.duration --;
466                     currentSectionBlank=myCollectionBlank.addSection(appearance);
467                     currentSectionBlank.duration ++;
468                  }
469                  isBlank = false;
470               }
471               if(! isInterp ){
472                 //中間値補間区間開始 カレントセクションを切り替え サブセクションを登録
473                 isInterp = true;
474                 if(fix==0){
475                     currentSection.value="interpolation";
476                         currentSection.subSections=new XpsTimelineSectionCollection(currentSection);
477                 }else{
478                     currentSection.duration --;
479                     currentSection=myCollection.addSection("interpolation");
480                     currentSection.duration ++;
481                 }
482                 currentSubSection = currentSection.subSections.addSection(new nas.AnimationReplacement(null,currentCell.join("-")));
483                 currentSubSection.duration ++;
484                 //新規中間値補間セクションを立てる 以降は、モードを抜けるまでカレント固定
485               }else{
486                 currentSubSection.duration --;
487                 currentSubSection = currentSection.subSections.addSection(new nas.AnimationReplacement(null,currentCell.join("-")));
488                 currentSubSection.duration ++;
489                 //中間値補間モード内ではサブセクションを登録
490               }
491               continue;
492         }
493         //区間値を処理
494 /**
495     既存エントリがない場合、エントリ文字列が条件を満たせば新規エントリとしてxMapにグループとエントリを登録して使用する
496     それ以外は、無効エントリとなる
497 */
498         var currentElement = this.xParent.parentXps.xMap.getElementByName(currentCell.join("-"));
499         if(currentElement) {
500 //console.log("value detcted in xMap:");
501             valueDetect=true;
502         }else{
503 //console.log("value not detcted in xMap: push Entry "+currentCell.reverse().join("-"));
504             if(String(currentCell[0]).match(valueRegex)){
505                 valueDetect = true;
506                 currentElement=this.pushEntry(currentCell[0],currentCell[1]);
507                 currentElement=this.pushEntry(this[fix],currentCell[1]);
508             }
509         }
510 //console.log(valueDetect);
511 //console.log(currentElement);
512         if(valueDetect){
513                 currentValue = currentElement.content;
514             if(isBlank){
515                 if(fix==0){
516                     currentSectionBlank.value=appearance;
517                 }else{
518                     currentSectionBlank.duration --;
519                     currentSectionBlank=myCollectionBlank.addSection(appearance);
520                     currentSectionBlank.duration ++;
521                 }
522                 isBlank = false;
523             }
524             if(isInterp){
525                 isInterp = false;
526                 currentSubSection.duration --;
527                 currentSubSection = null;
528             }
529             if(fix==0){
530                 currentSection.value = currentValue;
531             }else{
532                 currentSection.duration --;
533                 currentSection = myCollection.addSection(currentValue);
534                 currentSection.duration ++;
535             }
536         }
537         continue
538     }
539 //console.log(myCollection)
540     this.sections       = myCollection;
541     this.sectionsBlank  = myCollectionBlank;
542 //console.log("sections-length:"+myCollection.length +":blank:"+myCollectionBlank.length);
543     return this.sections;//ブランク情報の返し方を考えたほうが良いかも
544 }
545 
546 /*test
547 
548 XpsTimelineTrack.prototype.parseReplacementTrack=_parseReplacementTrack;
549 XPS.xpsTracks[2].parseReplacementTrack();
550 XPS.xpsTracks[2].sections[1].toString();
551 
552 XpsTimelineTrack.prototype.parseReplacementTrack=_parseReplacementTrack;
553 
554 XpsTimelineTrack.prototype.parseCameraWorkTrack=_parseCameraworkTrack;
555 
556 XpsTimelineTrack.prototype.parseCompositeTrack=_parseCompositeTrack;//コンポジット
557 
558 //XpsTimelineTrack.prototype.parseTrack=_parseTrack;
559 //XpsTimelineTrack.prototype.parseTrack=_parseTrack;
560 */
561 /**
562 ノートテキスト・タイムシート記述(カメラワーク・エフェクト)オブジェクト
563 具体的なステージワークやコンポジットワークを抽象化した シンボリックオブジェクト
564 トラック内には複数のオブジェクトを表記可能
565 
566 値区間のみ
567 または値区間にぶら下がった補完区間を一組として扱う
568 トラック名は、基本的に論理的な分類の役割のみをあつかう
569 
570 各効果は必要に従ってジオメトリトラック コンポジットトラックとして分解統合が期待される
571 このトラックのリンクとペアレントは、必ずしも整合性を持たない。
572 
573 "[A],▽,|,|,|,|,|,PAN,|,|,|,|,|,△,[B]"
574 "[1],▽,|,|,|,|,|,SL→,|,|,|,|,|,△,[2]"
575 "]OL[,|,|,|,|,s-c12,*,s-c13,|,|,|,|,]OL["
576 "]WIPE[,|,|,|,|,s-c12,*,s-c13,|,|,|,|,]WIPE["
577 "▲,|,|,FI,|,|,▲"
578 "■","■","■","<黒コマ>","■","■","■"
579 等のソースストリームをパースする
580 
581 >ブランクセクション   値なしで長さのみがある Section.value.type = geometryセクションの前後には必ずつく
582 
583 区間を開始するエントリー
584     [ブラケット]値エントリ
585 後続フレームから値つきgeometry区間を開始
586 
587     ]逆ブラケット[エントリ
588 トランジション区間を開始・終了
589 開始時に終了サインを設定
590 
591     空白エントリ
592 空白区間を開始
593 何らかの有効エントリーで終了
594 
595 
596 
597 
598 */
599 
600 _parseCameraworkTrack= function(){
601     var myCollection       = new XpsTimelineSectionCollection(this);//自分自身を親としてセクションコレクションを新作
602     var currentSection     = myCollection.addSection(null);//開始セクションを作成 継続時間0 値は保留
603     var currentValue       = new nas.AnimationCamerawork(null,"");//コンテンツはカラで初期化も保留
604     var currentSymbol      = null;
605 
606     var startNodeRegex=new RegExp("^[▼▽⇑●◯◎◆◇★☆┳┬]$");
607     var endNodes={
608         "▼":"▲",
609         "▽":"△",
610         "⇑":"⇓",
611         "●":"●",
612         "○":"◯",
613         "◎":"◎",
614         "◆":"◆",
615         "◇":"◇",
616         "☆":"☆",
617         "★":"★",
618         "┳":"┻",
619         "┬":"┴"
620     };// */
621     var startNodeId = 0;
622     var endNode;
623     var lastBracketsId ;
624     
625     for (var fix=0;fix<this.length;fix++){
626         var isBlank = (String(this[fix]).match(/^\s*$/))? true :false ;
627         if (String(this[fix]).match(/^\[[^\[]+\]$/)){ lastBracketsId = fix;isBlank = true;}
628         currentSection.duration ++;//currentセクションの継続長を加算
629 
630          if((lastBracketsId == fix)&&(!(currentSection.value))) currentSection.tailMargin = -1 ;
631 
632 //未記入セル カレントが空白セクションならば継続それ以外の場合は、セクション更新して継続
633 //[値]セルは未記入セル扱いにする
634 
635         if(isBlank){
636             if( currentSection.value ){
637 //console.log(currentSection.value)
638                 currentSection.duration --;
639                 if (fix == lastBracketsId){
640                     currentSection.value.postfix = this[fix];
641                     currentSection.tailMargin = 1;
642 //console.log(currentSection.value.type.join(':'));
643                 }
644                 currentSection.value.attributes.push([currentSection.value.prefix,currentSection.value.postfix].join('-'));
645                 if(currentSection.value.prefix)  currentSection.headMargin = 1;
646 //                currentSection.value.parseContent();
647                 currentSection = myCollection.addSection(null);//changeCurrentNull
648                  if (fix == lastBracketsId) currentSection.headMargin = -1;
649                 currentSection.duration = 1;
650                 if(endNode)         endNode       = undefined ;//終了ノードクリア
651                 if(currentSymbol)   currentSymbol = null;//シンボルクリア
652             }
653             continue;
654         }
655 //継続バー カレントが空白セクションの場合のみセクション更新して継続
656         if(
657             (String(this[fix]).match(nas.cameraworkDescriptions.barRegex))
658         ){
659             if(!(currentSection.value)){
660                 currentSection.duration --;
661                 if(currentSection.duration < 1) myCollection.pop();
662                 currentSection = myCollection.addSection(new nas.AnimationCamerawork(null,false));//changeCurrent unknown
663                 currentSection.duration = 1;
664                 startNodeId = fix;
665                 // イレギュラー開始なので endNode を設定しない
666                 currentSymbol = nas.cameraworkDescriptions.get('unknown');
667 //先行セクションが[値]セルであった場合
668                 if(lastBracketsId == (fix-1)){
669                     currentSection.value.prefix = this[lastBracketsId];
670                     currentSection.headMargin = 1;
671                 };// */
672             }
673             continue;
674         }
675 //エンドノードを検出した場合 検出用変数をクリアして 後続のセルを判定して動作を切り分け
676 /*
677     記述継続の場合のみ先行でセクションを切り替える
678     後続セルが空白セル||[値]セルならばNOP
679     
680     endNode検知
681     フレーム内容がstartNodeに対応するendNodeでかつ後続フレームが値エントリでない場合のみセクションを閉じる
682     最終フレーム処理では startNodeId==durationとなるが、以降の判定はないので放置
683 
684 */
685        if((endNode)&&(this[fix] == endNode)){
686         if(fix == (this.length-1)){
687             var nextBlank = true;
688         }else{
689             var nextBlank = (String(this[fix+1]).match(/^\s*$/))? true :false ;
690             if (String(this[fix+1]).match(/^\[[^\[]+\]$/)){ nextBlank = true;}
691         }
692                 if(! nextBlank ){
693                     var mySymbol = nas.cameraworkDescriptions.get(this[fix+1]);
694                     var detectedName = false;
695                     if((this[fix+1]).match(/^<([\>]+)>$/)){
696                         detectedName = RegExp.$1;
697                     }else if(mySymbol){
698                         detectedName = mySymbol.name;
699                     }
700                     if(currentSection.duration < 1) myCollection.pop();
701                     //if(currentSection.value) currentSection.value.parseContent();
702                     currentSection = myCollection.addSection(new nas.AnimationCamerawork(null,detectedName));//changeCurrent unknown
703                     startNodeId   = fix + 1;
704                     endNode       = undefined ;//終了ノードクリア
705                     currentSymbol = null;//シンボルクリア 判定保留
706 //先行セクションが[値]セルであった場合
707                 if(lastBracketsId == (fix-1)){
708                     currentSection.value.prefix = this[lastBracketsId];
709                     currentSection.headMargin = 1;
710                 };// */
711                 }
712 //console.log(currentSection.value.type.join(':'))
713                 continue;
714         }
715 //開始ノード(予約語)を検知 強制的に新しい区間を開始
716        if( String(this[fix]).match(startNodeRegex)){
717 //区間の開始
718             if(fix != 0){
719                 startNodeId = fix;//シート入力をスタートノードに設定
720                 endNode = endNodes[this[startNodeId]];//頭尾は
721                 currentSection.duration --;
722                 if((currentSection.duration < 1)&&(lastBracketsId!=(fix-1))) myCollection.pop();
723                 if(lastBracketsId == (fix-1)){
724                     currentSection.tailMargin = -1;                    
725                 }
726 //                if(currentSection.value) currentSection.value.parseContent();
727                 currentSection = myCollection.addSection(new nas.AnimationCamerawork(null,false));//changeCurrent
728                 currentSection.duration = 1;
729 //先行セクションが[値]セルであった場合
730                 if(lastBracketsId == (fix-1)){
731                     currentSection.value.prefix = this[lastBracketsId];
732                     currentSection.headMargin = 1;
733                 };// */
734 //console.log(currentSection.value.type.join(':'))
735                 continue;
736             }
737         };
738 //].*[トランジションエントリ()
739         if( String(this[fix]).match(/\^][^\[]+\[$/) ){
740             var mySymbol = nas.cameraworkDescriptions.get(this[fix]);
741             if(
742                 ((currentSection.value)&&(String(this[fix])!=endNode))||
743                 (!(currentSection.value))
744             ){
745 //]transition[区間の開始
746                 startNodeId = fix;//シート入力をスタートノードに設定
747                 endNode = this[startNodeId];//トランジションの頭尾は一致
748                 if(fix==0){
749                     currentSection.value=new nas.AnimationCamerawork(null,(mySymbol)?mySombol.name:this[startNodeId]);//change Value;
750                     continue;
751                 }else{
752                     currentSection.duration --;
753                     if(currentSection.duration < 1) myCollection.pop();
754                     //if(currentSection.value) currentSection.value.parseContent();
755                     currentSection = myCollection.addSection(new nas.AnimationCamerawork(null,(mySymbol)?mySombol.name:this[startNodeId]));//changeCurrent
756                     currentSection.duration = 1;
757                 }
758             }
759 //console.log(currentSection.value.type.join(':'))
760             continue;
761         }
762 //第一エントリで区間タイプが判別可能な区間の判定
763         if(
764             String(this[fix]).match(nas.cameraworkDescriptions.singleRegex)
765          ){
766             var mySymbol = nas.cameraworkDescriptions.get(RegExp.$1);
767 if(! mySymbol) console.log(this[fix]);
768             if((!(currentSection.value))||(currentSection.value.type[1]!=mySymbol.name)){
769 //Symbol区間の開始
770                 if(fix==0){
771                     currentSection.value=new nas.AnimationCamerawork(null,mySymbol.name);//change Value;
772 //console.log(currentSection.value.type.join(':'))
773                     continue;
774                 }else{
775                     currentSection.duration --;
776                     if(currentSection.duration < 1) myCollection.pop();
777                     //if(currentSection.value) currentSection.value.parseContent();
778                     currentSection = myCollection.addSection(new nas.AnimationCamerawork(null,mySymbol.name));//changeCurrent
779                     currentSection.duration = 1;
780 //先行セクションが[値]セルであった場合
781                     if(lastBracketsId == (fix-1)){
782                         currentSection.value.prefix = this[lastBracketsId];
783                         currentSection.headMargin = 1;
784                     };// */
785                 }
786             } else if(
787                 (fix<(this.length-1))&&(this[fix+1]!=this[fix])
788             ){
789                 if(currentSection.duration < 1) myCollection.pop();
790                 //if(currentSection.value) currentSection.value.parseContent();
791                 if(String(this[fix+1]).match(/^\s*$/)){
792                     currentSection = myCollection.addSection(null);//changeCurrentNull
793                     endNode     = undefined;
794                     currnetSymbol = null;
795                 }else{
796                     currentSection = myCollection.addSection(new nas.AnimationCamerawork(null,false));//changeCurrent
797                     startNodeId = fix+1;//シート入力をスタートノードに設定
798                     if ((!(endNode)) && (endNodes[this[startNodeId]])) endNode = endNodes[this[startNodeId]] ;
799                     currnetSymbol = mySymbol;
800                }
801 //先行セクションが[値]セルであった場合
802                 if(lastBracketsId == (fix-1)){
803                     currentSection.value.prefix = this[lastBracketsId];
804                     currentSection.headMargin = 1;
805                 };// */
806             }
807 //console.log(currentSection.value.type.join(':'))
808             continue;
809         }
810 /*==================================================================*/
811 //一般セクションの処理
812 //トラック開始フレームであった場合のみ無条件でセクション開始 
813 //セクション開始Idは初期値で更新不用 エンドノードは 予約語内の対応文字列>シンボルが同定可能ならそのデータ>開始文字列と同じ
814         if((fix==0)||(! currentSection.value)){
815 //先行セクションが空白であった場合のみセクション開始
816             startNodeId = fix;
817             if(! currentSymbol) currentSymbol = nas.cameraworkDescriptions.get(this[startNodeId]);
818             if(! currentSymbol) currentSymbol = nas.cameraworkDescriptions.get('unknown');
819             var detectName = false;
820             if(currentSymbol.name != 'unknown') detectName = currentSymbol.name;
821             if(fix==0){
822                 currentSection.value=new nas.AnimationCamerawork(null,detectName);//setValueToCurrentSection;
823             }else{
824                 currentSection.duration --;
825                 if(lastBracketsId == (fix-1)) currentSection.tailMargin = -1; 
826                 if(currentSection.duration < 1) myCollection.pop();
827                 //if(currentSection.value) currentSection.value.parseContent();
828                 currentSection = myCollection.addSection(new nas.AnimationCamerawork(null,detectName));//changeCurrent
829                 currentSection.duration = 1;
830 //先行セクションが[値]セルであった場合のみ
831 //                if((lastBracketsId == (fix-1))&&(currentSymbol.type != "composite")&&(currentSymbol.type != "transition")){}
832                 if(lastBracketsId == (fix-1)){
833                     //if(currentSymbol.type != "geometry"){
834                     //    currentSymbol = nas.cameraworkDescriptions.get('SL');
835                     //    currentSection.value=new nas.AnimationCamerawork(null,currentSymbol.name);
836                     //}
837                     currentSection.value.prefix = this[lastBracketsId];
838                     currentSection.headMargin = 1;
839                 }
840             }
841             //スタートノードに対応するエンドノードが予約語内にあればそちらを優先
842             if (endNodes[this[startNodeId]]){
843                 endNode = endNodes[this[startNodeId]];
844             } else if((currentSymbol)&&(currentSymbol.nodeSigns.length > 1)){
845                 endNode = currentSymbol.nodeSigns[currentSymbol.nodeSigns.length-1]
846             } else {
847                 endNode = this[startNodeId];
848             }
849 //console.log(currentSection.value.type.join(':'))
850 //            continue;
851         }else if(startNodeId == fix){
852 //セルエントリが開始ノードであった場合のみ終了ノードだけを設定する            
853             //スタートノードに対応するエンドノードが予約語内にあればそちらを優先
854             if (endNodes[this[startNodeId]]){
855                 endNode = endNodes[this[startNodeId]];
856             } else if((currentSymbol)&&(currentSymbol.nodeSigns.length > 1)){
857                 endNode = currentSymbol.nodeSigns[currentSymbol.nodeSigns.length-1]
858             }
859         }
860 //<name>エントリまたはタイプ識別可能エントリ
861 //          当該エントリの前に//セクションが閉じているか否か//セクションが確定しているか否か//の判定が必要
862         
863         var ckSymbol = nas.cameraworkDescriptions.get(this[fix]);
864         if(
865             (String(this[fix]).match(/^<([^>]+)>$/))||(ckSymbol)
866         ){
867             var detectedName = ( ckSymbol )? this[fix] : RegExp.$1;
868             if(! ckSymbol){
869                   ckSymbol = nas.cameraworkDescriptions.get(detectedName); 
870             }
871 //console.log(fix + ' : '+ this[fix]);
872 //console.log(ckSymbol);
873 //console.log(this[startNodeId]);
874 /*
875                 (currentSection.value.type[0]=="transition")||
876                 (currentSection.value.type[1]=="fadeIn")||
877 */
878             if(
879                 (currentSection.value)&&((currentSection.value.name=="")||
880                 (currentSection.value.name==this[startNodeId]))||
881                 ((ckSymbol) && (
882                     ((ckSymbol.type == currentSection.value.type[0]) && (ckSymbol.name == currentSection.value.type[1]))||
883                     ((ckSymbol.nodeSigns.length>1) && (ckSymbol.nodeSigns[1]==this[startNodeId]))
884                 ))
885             ){
886                 currentSection.value.name = detectedName;
887                 currentSymbol = ( ckSymbol )? ckSymbol : nas.cameraworkDescriptions.get(currentSection.value.name);
888                 if(!currentSymbol){ currentSymbol = nas.cameraworkDescriptions.get('unknown')}
889                 currentSection.value.type=[currentSymbol.type,currentSymbol.name];
890 //console.log(fix +': set section value');
891             }else{
892                 currentSection.duration --;
893                 if(lastBracketsId == (fix-1)) currentSection.tailMargin = -1 ; 
894                 if(currentSection.duration < 1) myCollection.pop();
895                 //if(currentSection.value) currentSection.value.parseContent();
896                 currentSection = myCollection.addSection(new nas.AnimationCamerawork(null,detectedName));//changeCurrent
897                 currentSection.duration = 1;
898                 currentSymbol = ( ckSymbol )? ckSymbol : nas.cameraworkDescriptions.get(currentSection.value.name);
899                 if(!currentSymbol){ currentSymbol = nas.cameraworkDescriptions.get('unknown')}
900 //console.log(fix +': start section');
901             }
902 //先行セクションが[値]セルであった場合
903                 if(lastBracketsId == (fix-1)){
904                     currentSection.value.prefix = this[lastBracketsId];
905                     currentSection.headMargin = 1;
906                 };
907             if(!(endNode)){
908                 endNode = (currentSymbol.nodeSigns.length>2)?currentSymbol.nodeSigns[2]:currentSymbol.nodeSigns[1];
909 //&&(this[startNodeId]==currentSymbol.nodeSigns[1])
910             }else if(
911                 (currentSymbol.nodeSigns.length > 1)
912             ){
913                 endNode = currentSymbol.nodeSigns[currentSymbol.nodeSigns.length-1];
914             }
915 //console.log(currentSection.value.type.join(':'))
916 //console.log(currentSymbol)
917 //console.log(endNode);
918             continue;           
919         }
920 //コメントエントリ
921         if( String(this[fix]).match(/^\(([^\)]+)\)$/) ){
922             currentSection.value.comments.push(RegExp.$1);
923         }
924 //interp,start,end以外のエントリーはattributesに積む
925     }
926 
927     this.sections=myCollection;
928 //console.log(this.sections)
929     return this.sections;
930 }
931 
932 /**
933  *  ジオメトリタイムラインの(区間)値
934  *  カメラワーク
935  基本的なサイズは、トラックに設定されたデフォルト値から継承する
936  
937  
938 要素名は[ブラケット]で囲む
939 プロパティの値はブラケットを払ったもの
940  */
941 nas.AnimationGeometry =function(myParent,myContent){
942     this.parent = (myParent)? myParent : null   ;//xMapElementGroup or null
943     this.contentText=(myContent)?myContent:''   ;//xMapのソースを保存する 自動で再構築が行なわれるタイミングがある
944 
945     this.name                                   ;//素材名
946     this.source                                 ;//参照画像データソース 存在する場合は、type="still-reference"で初期化される
947     this.comment=""                             ;//コメント文字列
948     this.extended = false                       ;//拡張表示フラグ
949 
950     this.formGeometry = new nas.AnimationField();//nas.AnimationFieldオブジェクト
951     this.position     = new nas.Position()      ;//要素を配置する位置
952     this.offset       = new nas.Offset()        ;//要素の原点オフセット
953     this.scale        = new nas.Scale()         ;//要素スケール
954     this.t            = new nas.TimingCurve();
955     this.c            = new nas.Curve();
956     this.x = this.position.x;
957     this.y = this.position.y;
958     this.z = this.position.z;
959     
960     this.parseContent();
961 }
962 
963 nas.AnimationGeometry.prototype.constractor=nas.AnimationField.constractor
964 
965 
966 /**
967     文字列化して返す
968     exportForm
969     basic
970 source+
971     extend
972 */
973 nas.AnimationGeometry.prototype.toString=function(exportForm){
974     if(! this.name) return '';//無名オブジェクトは空リターン
975 //return this.contentText;//動作確認用ダミー行
976     if(exportForm == 'extend'){
977         var resultArray=[];
978         if(this.position)   resultArray.push('\tposition = "'+ this.position.toString(true)+'"');
979         if(this.source)     resultArray.push('\tfile = "'    + this.source.toString(true)+'"');
980         if(this.size)       resultArray.push('\tsize = '     + this.size.toString());
981         if(this.offset)     resultArray.push(this.offset.toString());
982 //        if(this.offset)   resultArray.push('\toffset = '   + this.offset.toString());
983         if(this.rotation)   resultArray.push(this.rotation.toString(true));
984         if(this.comment)    resultArray.push('\tcomment = '  + this.comment);
985         return resultArray.join("\n");
986     }else if ((arguments.length==0)||((arguments.length==1)&&(! arguments[0]))||(exportForm == 'basic')){
987         var resultArray=[];
988         
989         if(this.source)   resultArray.push('"'+this.source.toString()+'"');
990         if(this.size)     resultArray.push(this.size.toString());
991         if(this.offset)   resultArray.push(this.offset.toString());
992         if(this.rotation) resultArray.push(this.rotation.toString());
993         resultArray = [resultArray.join(",")];
994         if(this.comment) resultArray.push(this.comment);
995         return ([this.parent.name,this.name,resultArray.join("\t")]).join('\t');
996     }
997 
998 
999     if(exportForm=='extended'){
1000         var resultData=[];
1001         if(this.source)     resultData.push(this.source.toString(true));   
1002         if(this.size)       resultData.push(this.size.toString(true));
1003         if(this.position)   resultData.push(this.position.toString(true));
1004     }else{
1005     }
1006     return this.contentText;
1007 }
1008 /**
1009     コンテンツを与えてパースする
1010     引数がない場合は自身のコンテンツデータを再パースする
1011 */
1012 nas.AnimationGeometry.prototype.parseContent=function(myContent){
1013 //引数がなければ現在のコンテンツを再パース
1014     if(typeof myContent == 'undefined'){
1015         myContent = this.contentText;
1016     }else{
1017         this.contentText = myContent;
1018     }
1019 
1020     var isGroup = (myContent.indexOf('[')==0)? true:false;
1021 //第一形式グループ ^[\<group>\t<typeName>[\t<option-text>[\t<comment>]]\]$
1022 //第二形式エントリ ^<group>\t<name>[\t<option-text>[\t<comment>]]$
1023 
1024     myContent = String(myContent).split('\n');
1025     for ( var line = 0 ; line < myContent.length ; line++){
1026 
1027     if((isGroup)&&(myContent[line].indexOf('[')==0)) myContent[line] = myContent[line].slice(1,-1);//ブラケット削除
1028 
1029         if(myContent[line].match(/^\t(\S+)\s*=\s*(.+)\s*$/)){
1030             //第二形式(タブ開始)でプロパティ別のデータ更新を行う
1031             this.extended=true;
1032 
1033             var myProp=RegExp.$1;var valueArray=csvSimple.parse(RegExp.$2)[0];
1034 
1035             switch(myProp){
1036             case "file":
1037                 this.file = new nas.AnimationElementSource(valueArray[0]);
1038             break;
1039             case "position":
1040                 this.position = new nas.Position(valueArray[0],valueArray[1]);
1041             break;
1042             case "position.X":
1043                 this.position.x = new nas.UnitValue(valueArray[0]);
1044             break;
1045             case "position.Y":
1046                 this.position.y = new nas.UnitValue(valueArray[0]);
1047             break;
1048             case "offset":
1049                 this.offset = (valueArray.length<3)?
1050                     new nas.Offset(valueArray[0],valueArray[1]):new nas.Offset(valueArray[0],valueArray[1],valueArray[2]);
1051             break;
1052             case "offset.X":
1053                 this.offset.x = new nas.UnitValue(valueArray[0]);
1054             break;
1055             case "offset.Y":
1056                 this.offset.y = new nas.UnitValue(valueArray[0]);
1057             break;
1058             case "offset.R":
1059                 this.offset.r = new nas.UnitAngle(valueArray[0]);
1060             break;
1061             case "scale":
1062                 this.scale = (valueArray.length<3)?
1063                     new nas.Scale(valueArray[0],valueArray[1]):new nas.Offset(valueArray[0],valueArray[1],valueArray[2]);
1064             break;
1065             case "scale.X":
1066                 this.scale.x=new nas.UnitValue(valueArray[0]);
1067             break;
1068             case "scale.Y":
1069                 this.scale.y=new nas.UnitValue(valueArray[0]);
1070             break;
1071             case "scale.Z":
1072                 this.scale.z=new nas.UnitAngle(valueArray[0]);
1073             break;
1074            default:
1075                 this[myProp]=valueArray[0];
1076             }
1077         } else if(myContent[line].match(/^(\S+)\t?(\S+)\t?([^\t]+)?\t?(.*)$/)){
1078         // 第一形式の再パース
1079 //console.log(myContent[line]);
1080             var myGroup=RegExp.$1; //グループの再パースは行われない
1081             var myName =RegExp.$2;
1082             var myComment=RegExp.$4;
1083             var valueArray=nas.parseDataChank(RegExp.$3);
1084             var numeProps =[["size","x"],["size","y"],["offset","x"],["offset","y"]];
1085 //console.log(myComment);console.log(valueArray);
1086 //console.log(this);
1087 /*
1088     フィールド文字列であった場合の判定が必要 2018 10 09
1089 */
1090             if((this.parent instanceof nas.xMapGroup)&&(myGroup == this.parent.name)){
1091                 if(! isGroup) this.name=([myGroup,myName.replace(new RegExp('^'+myGroup+'\-'),"")]).join('-');
1092                 var numCount=0;
1093                 for(var vix=0;vix<valueArray.length;vix++){
1094                     switch(valueArray[vix].type){
1095                     case "numeric":
1096                     case "unitValue":
1097                         if(numCount<numeProps.length){
1098                             if(! this[numeProps[numCount][0]]){
1099                                 this[numeProps[numCount][0]] = ([numeProps[numCount][0]]=='size')? new nas.Size():new nas.Offset();
1100                             }
1101                             this[numeProps[numCount][0]][numeProps[numCount][1]] = new nas.UnitValue(valueArray[vix].value);
1102                             numCount++;
1103                         }
1104                     break;
1105                     case "unitAngle":
1106                         if(! this.offset) this.offset = new nas.Offset();
1107                         this.offset.r==new nas.UnitAngle(valueArray[vix].value);            
1108                     break;
1109                     case "unitResolution":
1110                         this.resolution=new nas.Resolution(valueArray[vix].value);            
1111                     break;
1112                     case "source":
1113                         this.source=new nas.AnimationElementSource(valueArray[vix].value);            
1114                     break;
1115                     default:
1116                         continue;
1117                 }
1118             }
1119                 if(myComment) this.comment = myComment;
1120             }
1121         }
1122 
1123     }
1124     return this;    
1125 }
1126 
1127 nas.AnimationGeometry.prototype.interpolate= function(endValue,indexCount,indexOffset,frameCount,frameOffset,props){
1128     return this;//置きかえタイムラインの中間値は前方値で代表される
1129     /* オプション状態で中間タイミングで後方値に切り替える(時間で) return endValue;
1130       又はブランク状態のオブジェクトを返す return new nas.newAnimationReplacement("blank");
1131     */
1132 }
1133 
1134 /** 指定フレーム数に内容を展開して配列で返す
1135  * @params {Number} cellCount
1136  * @returns {Array} 配列
1137 */
1138 /*
1139 値セクションと補完セクションで出力を分ける
1140 空配列を作成
1141 値セクションは値を冒頭または末尾に表示
1142 表示条件
1143     冒頭 セクションIDがである場合を除き先行セクションが補完セクションであった場合に表示
1144     末尾 後続セクションが補完セクションであった場合に表示
1145 補完セクション
1146     継続長1フレーム・2フレーム バーサインのみ
1147     それ以上は、
1148     開始サイン1,バーサイン 継続長-2,終了サイン1
1149 
1150 最少セクション長は 1
1151 最少セクション長を割ることは認められない セクション削除は可能
1152 
1153 ユーザ記述の文字列は可能な限り保存したいが、その仕組は後から 2019.02
1154  */
1155 nas.AnimationGeometry.prototype.getStream=function(cellCounts){
1156     if(isNaN(cellCounts)) cellCounts = 1;//1  > minimumCount
1157 
1158     var minCount = 1 ;//name
1159 //    if(this.prefix)  minCount++;
1160 //    if(this.postfix) minCount++;
1161 
1162 //    var myResult=new Array(cellCounts);
1163 
1164     if(cellCounts<0) cellCounts=Math.abs(cellCounts);//?
1165     if(cellCounts >= minCount){
1166 //        var myName = (mySymbol.nodeSigns.length == 1) ?mySymbol.nodeSigns[0]:'<'+this.name+'>';
1167         var myResult = new Array(cellCounts);
1168         for (var ix = 0 ; ix < cellCounts ;ix ++){
1169             /*if(ix == Math.floor((cellCounts-(1+this.comments.length))/2)){
1170                 myResult[ix] = "<center>";
1171                 if(this.comments.length){
1172                     for (var cx = 0 ;cx<this.comments.length;cx++){
1173                         myResult[ix+cx+1] = '('+this.comments[cx]+')';
1174                     }
1175                     ix += this.comments.length;
1176                 }
1177                continue;
1178             }// */
1179         }
1180         if(this.prefix)  myResult = [this.prefix].concat(myResult);
1181         if(this.postfix) myResult = myResult.concat([this.postfix]); 
1182   }
1183 
1184     return myResult;
1185 }
1186 /*
1187 
1188 ジオメトリ要素、コンポジット要素 では、第三フィールド内の各値は、書式による自動判定をおこなう(順序によらない)
1189 
1190 %付き数値判定(strength または scale)
1191 インチフィールド文字列
1192 フィールド文字列
1193 ジオメトリデータ配列
1194     単位値と単位角度の組み合わせ
1195 
1196 これらを判定して、判定から外れたデータをファイルパス(素材識別データ)とみなす
1197 スケール以外の単位省略は不可
1198 
1199 [PAN	geometry	,12FLD-10]
1200 
1201 [FI-1	effect]
1202 [TU	geometry]
1203 [透過光	effect]
1204 
1205 	field = 10FLD
1206 PAN	[A]	10FLD2S3W12 Quick
1207 
1208 
1209 [FI-A	effect	"",,,	コメントですです]
1210 
1211 
1212 	geometry
1213 [FLDString][,"file-path"]
1214 	1,2
1215 [FLDString[,left,top[,rotation]]][,"file-path"]
1216 	1,2,3,4,5
1217 [width,height[,left,top[,rotation]]][,"file-path"]
1218 	1,2,3,4,5,6
1219 
1220 Target.match(/^[\d]+\.?[\d]*FLD()?$/i)
1221 
1222 
1223 	effect
1224 [strength[,blendingMode]][,file-path]
1225 	1,2,3
1226 
1227 (Target).match(/^[+-]?[\d]+\.?[\d]*\%?$/);//%付き数値判定
1228 (new nas.BlendingMode[Target]);//ブレンドモード判定
1229 上記以外はファイルパス
1230 50%,normal
1231 50%,"/path/file-name.ext"
1232 
1233 
1234 [WXP	effect	50%,normal	カットいっぱい]
1235 
1236 [FI	effect	0%]
1237 FI	<10%>	normal
1238 FI	<0.01>		
1239 */
1240 /* TEST
1241 var A=new nas.AnimationGeometry(null,
1242 `[PAN	GEOMETRY]
1243 	size=252mm,142.875mm
1244 	position=0mm,0mm,0mm
1245 	offset=0mm,104.875mm
1246 	rotation=0d
1247 	comment=10in/StanderdFrame/16:9/HDTV
1248 # 作品データの継承があるのでこのサンプルでは本来は記述不要
1249 `);
1250 A.toString();
1251 */
1252 /*
1253     カメラワークトラックをパースしてセクションコレクションを返す
1254     option:(geometry|stagework)
1255     セクションの状態は
1256     値:
1257         あり>有値セクション
1258             何らかの値オブジェクトを持つ値セクション この継続時間中トラックの持つ値は変化しない最短で1フレーム
1259         なし>中間値補間セクション
1260             valueプロパティが空で値オブジェクトを持たない
1261             中間値補間サブセクションコレクションを持つ
1262     geometryタイムライントラックセクションの開始、終了判定
1263     セクションは「値区間(セクション)」と「中間値補間区間(セクション)」の2種に分類される
1264     中間値セクションは必ず前後に値セクションを持つ
1265     値区間は連続することが可能
1266     値区間は最低でも1フレームの継続時間を持ち、そのトラックの返す値nas.AnimationGeometryオブジェクトを保持する
1267 
1268     補間区間は、値オブジェクトを持たず、サブセクションコレクションを持ち 前後の値区間の中間値を補間して戻す
1269     サブセクションは値としてnas.ValueInterpolatorオブジェクトを持つ
1270     
1271     補間区間は補間区間開始ノードで開始され終了ノードで閉じる
1272     
1273     入力としては開始ノードと終了ノードはそれぞれ対応するサインを対で使用することが求められる
1274     特定の開始ノードで初期化された補間区間は、明示的に開始ノードと対の終了ノードで閉じられるか又は
1275     後続の値エントリが宣言されて値区間が開始されるまでの間継続される
1276     中間値補間区間はその区間が閉じられるまでの間 基本的にすべての空白以外のエントリが副補間区間を初期化する。
1277     開始ノードは必ず副補間区間を開始するが、終了ノードは副補間区間を開始するとは限らない。
1278         
1279     終了ノードが中間値補間ノードとなるかならないかの判定
1280    
1281    区間内の終了ノードを除く中間値生成ノードの数がdurationの整数分の1である(割り切れる)場合(= 均等フレーミング)の場合
1282    終了ノードは中間値を初期化しない。
1283    
1284    タイミングが乱れ打ちの中間値補間を行う場合は、終了ノードを利用せずにタイミング指定を行うものとする
1285    実際に開始ノードと終了ノードのみの区間があった場合は、中間値指定ノードでシートセルを埋めるように促すほうが良い
1286 */
1287 _parseGeometryTrack= function(){
1288     var myCollection      = new XpsTimelineSectionCollection(this);//自分自身を親としてセクションコレクションを新作
1289     var currentSection    = myCollection.addSection(null);//開始セクションを作成 継続時間0 値は保留
1290     var currentSubSection = null;//操作サブセクションへの参照 値はカラ 処理中は操作対象オブジェクトへの参照
1291 //    var currentValue      = new nas.AnimationGeometry(null,"");//コンテンツはカラで初期化も保留
1292 //初期コンテンツは、継承のためにトラックに関連するxMapGroup.contentを求めて利用する。
1293     var trackGroup        = this.xParent.parentXps.xMap.getElementByName(this.id);
1294     if(!trackGroup)
1295         trackGroup        = new_xMapElement(
1296             this.id,
1297             'geometry',
1298             this.xParent.parentXps.currentJob
1299         );
1300     var currentValue      = trackGroup.content;
1301     var currentNodeSign   = false;//否で初期化(確認用)
1302     var valueDetect       = false;//否で初期化(確認用)
1303     var startNodeRegex    = new RegExp("^[▼▽●◯◎◆◇★☆]$");
1304     var endNodes={
1305         "▼":"▲",
1306         "▽":"△",
1307         "●":"●",
1308         "○":"◯",
1309         "◎":"◎",
1310         "◆":"◆",
1311         "◇":"◇",
1312         "☆":"☆",
1313         "★":"★"
1314     };
1315     for (var fix=0;fix<this.length;fix++){
1316         currentSection.duration ++;//currentセクションの継続長を加算
1317         if( currentSubSection ) currentSubSection.duration ++;//currentセクションの継続長を加算
1318 //未記入データ これが一番多いので最初に処理しておく
1319         if(this[fix]=="") continue;
1320 //中間値補間セクション終了ノード(対で処理する方)
1321         if(this[fix]==currentNodeSign){
1322             //補間サブセクションを初期化するかどうかを判定
1323             if( currentSection.duration % currentSection.subSections.length ) {
1324                 currentSubSection = currentSection.subSections.addSection();//割り切れない場合サブセクションを初期化
1325                 currentSubSection.duration = 1;//必ず1
1326             }
1327             currentNodeSign=false;//補間区間終了ノードクリア
1328             currentSection=myCollection.addSection(false); // 新規値セクション追加
1329             continue;
1330         } else
1331 /* この正規表現は仮でハードコーディング あとで設定ファイルからの反映に変更予定*/
1332         if(this[fix].match(startNodeRegex)){
1333 /*
1334     予約開始ノードサイン検出
1335 予約語の開始ノードサインを検出したので対応する終了ノードをセットする
1336 第一区間が補間区間であった場合、トラックのデフォルト値を先行区間の値とする。
1337 第一区間は、値区間 補間区間のいずれでも良いので初期区間の値は保留されている
1338 検出したサインがカレントノードサインと一致していたら補間区間終了それ以外は副補間区間のエントリ初期化
1339 セクションノードサイン
1340 予約語
1341     /^[▼▽↑●○◎◆◇★☆]$/
1342     特殊ノードとして中間値補間区間を開き、同じサインで当該の区間を閉じる
1343     予約語以外の中間値指定ノードには閉鎖機能がない
1344     値指定ノード以外は基本的にすべて中間値指定ノードとする
1345     空白エントリ・予約語以外の記述は値を指定するノードか否かを判定する。
1346     明示的に値を生成するノードを切り分け 残るエントリはxMapに問い合わせを行い値を持たないエントリを中間値発生ノードとして扱う
1347 */
1348             if(currentNodeSign==false){
1349                 currentNodeSign=endNodes[this[fix]];//予約語で開いたので終了ノードを設定する
1350                 if(fix == 0){
1351                     currentSection.subSections=new XpsTimelineSectionCollection(currentSection);//第一フレームだった場合のみ第一セクションを補間区間に変換
1352                     currentSubSection=currentSection.subSections.addSection();//同時に第一サブセクションを初期化
1353                     currentSubSection.duration = 1;
1354                 }else{
1355                     currentSection.duration --;
1356                     currentSection = myCollection.addSection("interpolation"); //それ以外は新規補間セクション追加
1357                     currentSection.duration = 1;
1358                     currentSubSection = currentSection.subSections.addSection();
1359                     currentSubSection.duration = 1;
1360                 }
1361             } else {
1362                 currentSubSection = currentSection.subSections.addSection();
1363             }
1364             currentSubSection.duration = 1;
1365         } else {
1366 //予約ノードサイン外
1367 /**
1368 valueDetect = fale;
1369 値指定ノード\[[^\]]+\]を検出した場合、セルエントリーの角括弧を払って評価値を得る かつ フラグを立てる (valueDetect = true)
1370 それ以外はセルエントリーを評価値とする
1371     xMapで評価値をエントリ検索
1372     マップエントリがない場合でかつ valueDetect == true なら エントリを作成してそれを値として使用
1373     エントリがあれば valueDetect = true なければ false
1374 valueDetect==true
1375     カレントセクションが中間値補間セクションだった場合はカレントセクションをクロースして検出した値をもつ値セクションを初期化する
1376     カレントセクションの値が未設定の場合、カレントセクションの値を設定
1377     カレントセクションに値がある場合は新規の値セクションを初期化
1378 valueDetect==false
1379     エントリがない場合は中間値指定ノードとなる
1380     カレントセクションが中間値補間セクションだった場合は新規に副補間区間を初期化
1381     値区間だった場合は新規に中間値補間セクションを初期化して第一副補間区間を初期化する
1382     トラック内無効記述(コメント)は現在許可されない。
1383 */
1384     valueDetect = false;
1385     if(this[fix].match(/^\[([^\]])\]$/)){
1386         var checkValue=RegExp.$1;
1387         valueDetect=true;
1388     }else{
1389         var checkValue= this[fix];
1390     }
1391     var currentElement = this.xParent.parentXps.xMap.getElementByName([this.id,checkValue].join('-'));//グループIDを加える
1392     if((! currentElement) && (valueDetect)){
1393        currentElement=this.xParent.parentXps.xMap.new_xMapElement(
1394             checkValue,
1395             'geometry',
1396             this.xParent.parentXps.currentJob,
1397             [this.id,checkValue].join('-')
1398         );
1399     }else{
1400         valueDetect=(currentElement)?true:false;
1401     }
1402             if(currentElement){
1403                 if(currentNodeSign){
1404                     currentSection.duration--;//閉鎖ノード無しで前セクションを閉じるので加算したdurationをキャンセル
1405                     currentNodeSign = false;//補間区間終了ノードクリア
1406                     currentSection = myCollection.addSection(currentElement);//新規セクション追加
1407                     currentSubSection = null;
1408                 } else {
1409                     if (currentSection.value){
1410                         currentSection.duration--;//閉鎖ノード無しで前セクションを閉じるので加算したdurationをキャンセル
1411                         currentSection = myCollection.addSection(currentElement);//新規セクション追加
1412                         currentSubSection = null;
1413                     }else{
1414                         currentSection.value=currentElement.content;//値を遅延設定
1415                     }
1416                 }               
1417             } else if(currentNodeSign) {
1418 //               console.log("fix:"+fix);
1419             currentSubSection = currentSection.subSections.addSection();
1420             currentSubSection.duration = 1;
1421             }
1422         }
1423     }
1424     this.sections=myCollection;
1425     return this.sections;
1426 }
1427 
1428 /**
1429  *  コンポジットタイムラインの(区間)値
1430  *  エフェクト
1431  要素名は、可能な限り[name]角括弧で囲む 囲まれていた場合括弧は払って記録する
1432 要素名が数値 または  %つき数値であった場合は strength の値として使用する
1433 1.0                 基数1 浮動小数点値
1434 100%    100/100     100分率値
1435 1000‰  1000/1000   1000分率値
1436 
1437 要素名が指定されない場合は、[START],[01],[02]…[END]を自動で割り付ける
1438 
14391440 [WXP    composite   50%]
1441 WXP [75%]   
1442 
1443 
1444  */
1445 nas.AnimationComposite =function(myParent,myContent){
1446     this.parent = (myParent)? myParent : null   ;//xMapElementGroup or null
1447     this.contentText=(myContent)?myContent:''   ;//xMapのソースを保存する 自動で再構築が行なわれるタイミングがある
1448 
1449     this.name                                   ;//xMap素材名
1450     this.source                                 ;//参照画像データソース nas.AnimationElementSource
1451     this.comment=""                             ;//コメント文字列 xMap attribute
1452     this.extended = false                       ;//拡張表示フラグ
1453 
1454     this.effect                                 ;
1455     this.blendingMode                           ;
1456     this.strength                               ;// ? 
1457     this.t = new nas.TimingCurve()              ;
1458     this.c = new nas.Curve()                    ;
1459 
1460     this.parseContent();
1461 }
1462 /**
1463     中間点取得
1464 自身の値とターゲット値の中間の値を求める
1465 
1466 引数
1467     endValue        ターゲット値
1468     indexCount      
1469     indexOffset
1470     frameCount
1471     frameOffset
1472     props    
1473 */
1474 nas.AnimationComposite.prototype.interpolate= function(endValue,indexCount,indexOffset,frameCount,frameOffset,props){
1475     myResult=Object.create(this);
1476     myResult.strength=(this.strength+endValue.strength)*(indexCount/indexCount);// 仮値リニア補間
1477     return myResult;//コンポジットタイムラインの中間値は濃度値のみ
1478 
1479 }
1480 /**
1481     xMapデータのために文字列化して返す 予定だが
1482     今はダミー
1483 */
1484 nas.AnimationComposite.prototype.toString=function(exportForm){
1485 return this.contentText;//動作確認用ダミー行
1486     
1487     var props=['effect','blendingMode','strength','t','c','comment'];
1488     var myResult = '';
1489     for (var pid=0;pid<props.length;pid++){
1490         if(this[props[pid]]){
1491             myResult += '\t'+props[pid]+' = '+this[props[pid]]
1492         }
1493     }
1494 
1495     if(exportForm == 'extend'){
1496         var resultArray=[];
1497         if(this.source)         resultArray.push('\tfile = "'    + this.source.toString(true)+'"');
1498         if(this.effect)         resultArray.push('\teffect = '     + this.effect);
1499         if(this.blendingMode)   resultArray.push('\tblendingMode = '   + this.blendingMode);
1500         if(this.strength)       resultArray.push('\tstrength = ' + this.strength);
1501         if(this.t)              resultArray.push('\tT = '  + this.t.toString(true));
1502         if(this.c)              resultArray.push('\tC = '  + this.c.toString(true));
1503         if(this.comment)        resultArray.push('\tcomment = '  + this.comment);
1504         return resultArray.join("\n");
1505     }else if ((arguments.length==0)||((arguments.length==1)&&(! arguments[0]))||(exportForm == 'basic')){
1506         var resultArray=[];
1507         
1508         if(this.source) {
1509             resultArray.push('"'+this.source.toString()+'"');
1510         }else{
1511             resultArray.push("");
1512         }
1513         if(this.size)     resultArray.push(this.size.toString());
1514         if(this.offset)   resultArray.push(this.offset.toString());
1515         if(this.rotation) resultArray.push(this.rotation.toString());
1516         resultArray = [resultArray.join(",")];
1517         if(this.comment) resultArray.push(this.comment);
1518         return ([this.parent.name,this.name,resultArray.join("\t")]).join('\t');
1519     }
1520 
1521 }
1522 /**
1523     コンテンツを与えてパースする
1524     引数がない場合は自身のコンテンツデータを再パースする
1525 [FI COMPOSITE]
1526 FI  100%    
1527 
1528 */
1529 nas.AnimationComposite.prototype.parseContent=function(myContent){
1530     if(typeof myContent == 'undefined'){
1531         myContent = this.contentText ;
1532     }
1533     this.contentText = (myContent)? String(myContent):"";
1534     
1535     
1536     
1537     
1538     
1539     this.contentText = this.toString();
1540     return this;
1541 }
1542 nas.AnimationComposite.prototype.getStream=function(cellCounts){
1543     var myResult=new Array(cellCounts);
1544     myResult[0] = this.name;
1545 
1546     if (myResult.length > 6 )myResult[myResult.length-1] = this.name
1547 
1548     return myResult;
1549 }
1550 /**
1551     コンポジットトラックをパースしてセクションコレクションを返す
1552     option:(effect|sfx|composite)
1553     セクションの状態は
1554     値:
1555         あり>有値セクション
1556             何らかの値オブジェクトを持つ値セクション この継続時間中トラックの持つ値は変化しない最短で1フレーム
1557         なし>中間値補間セクション
1558             valueプロパティが空で値オブジェクトを持たない
1559             中間値補間サブセクションコレクションを持つ
1560     compositeタイムライントラックセクションの開始、終了判定
1561     セクションは「値区間(セクション)」と「中間値補間区間(セクション)」の2種に分類される
1562     中間値セクションは必ず前後に値セクションを持つ
1563     値区間は連続することが可能
1564     値区間は最低でも1フレームの継続時間を持ち、そのトラックの返す値を保持する
1565     補間区間は、値オブジェクトを持たず、サブセクションコレクションを持ち 前後の値区間の中間値を補間して戻す
1566     補間区間は補間区間開始セパレータで開始され終了セパレータで閉じる
1567     入力としては開始セパレータと終了セパレータが同一のエントリを対で使用することが求められる
1568     開始セパレータで宣言された補間区間は、明示的に開始セパレータと対の終了セパレータで閉じられるか又は
1569     後続の値エントリを宣言して値区間を開始されくまでの間継続される
1570     補間区間はその区間が閉じられるまでの間 すべての空白以外のエントリが副補間区間を開始する。
1571     補間区間中すべてのエントリが空白であった場合に限り、空白区間がすべて副補間区間のエントリとなる
1572     (=補間区間に何も間に置かなかったトラックは1コマ撮りの補間区間となる)
1573 */
1574 _parseCompositeTrack=function(){
1575     var myCollection    = new XpsTimelineSectionCollection(this);//自分自身を親としてセクションコレクションを新作
1576     var currentSection  = myCollection.addSection(false);//開始セクションを作成 継続時間0 値は保留
1577     var currentSubSection  = null;//操作サブセクションへの参照 値はカラ 処理中は操作対象オブジェクトへの参照
1578     var currentComposite   = new nas.AnimationComposite(null);//コンテンツはカラで初期化も保留
1579     var currentNodeSign    = false;//否で初期化(確認用)
1580     var valueDetect        = false;//否で初期化(確認用)
1581     
1582     for (var fix=0;fix<this.length;fix++){
1583         currentSection.duration ++;//currentセクションの継続長を加算
1584         //未記入データ これが一番多いので最初に処理しておく
1585         if(this[fix]==""){
1586             continue;
1587         }
1588         //区間の値
1589         //中間値補間セクション開始セパレータ(対で処理する方)
1590         
1591 /** この正規表現は仮でハードコーディング あとで設定ファイルからの反映に変更予定*/
1592         if(this[fix].match(/^[▼▲▽△●○◎◆◇☆★]$|^\][^\]]+\[$|^\)[^\(]+\($/)){
1593 /**
1594     ノードサイン検出
1595 第一区間が補間区間であった場合、トラックのデフォルト値を先行区間の値とする。
1596 第一区間は、値区間 補間区間のいずれでも良いので初期区間の値は保留されている
1597 currentNodeSignがfalseであった場合はセクション開始
1598 それ以外の場合、補間区間のエントリ中でのサイン検出
1599 検出したサインがカレントノードサインと一致していたら補間区間終了それ以外は副補間区間のエントリ初期化
1600 セクションノードサイン
1601 予約語
1602     /^[▼▲▽△●○◎◆◇☆★]$|^\][^\]+]\[$|^\)[^\(+]\($/
1603     特殊ノードとして中間値補間区間を開き、同じサインで当該の区間を閉じる
1604     予約語以外の中間値指定ノードには閉鎖機能がない
1605     値指定ノード以外は基本的にすべて中間値指定ノードとする
1606     空白エントリ・予約語以外の記述は値を指定するノードか否かを判定する。
1607     明示的に値を生成するノードを切り分け 残るエントリはxMapに問い合わせを行い値を持たないエントリを中間値発生ノードとして扱う
1608 */
1609             if(currentNodeSign==false){
1610                 currentNodeSign=this[fix];//予約語で開いたのでノードを控える
1611                 if(fix==0){
1612                     currentSection.subSections=new XpsTimelineSectionCollection(currentSection);//第一フレームだった場合のみ第一セクションを補間区間に変換
1613                     currentSubSection=currentSection.subSections.addSection();//同時に第一サブセクションを初期化
1614                     currentSubSection.duration = 1;
1615                 }else{
1616                     currentSection.duration --;
1617                     currentSection = myCollection.addSection("interpolation"); //それ以外は新規補間セクション追加
1618                     currentSection.duration = 1;
1619                     currentSubSection = currentSection.subSections.addSection();
1620                     currentSubSection.duration = 1;
1621                 }
1622                 currentSection.subSections.addSection();//オープンと同時に第一サブセクションを初期化
1623             } else if (currentNodeSign==this[fix]){
1624                 //開始ノードと一致
1625                 if( currentSection.duration % currentSection.subSections.length ) {
1626                     currentSection.subSections.addSection();//割り切れない場合サブセクションを初期化
1627                 }
1628                 currentNodeSign=false;//補間区間終了ノードクリア
1629                 currentSection = myCollection.addSection(false); // 新規セクション追加 終了ノードで閉じたので加算はなし
1630             } else {
1631                 currentSection.subSections.addSection();
1632             }
1633         } else {
1634 //予約ノードサイン外
1635 /**
1636 valueDetect = fale;
1637 値指定ノード[値]を検出した場合、セルエントリーからBracketsを払って評価値を得る かつ フラグを立てる (valueDetect = true)
1638 それ以外はセルエントリーを評価値とする
1639     xMapで評価値をエントリ検索
1640     マップエントリがない場合でかつ valueDetect == true なら エントリを作成してそれを値として使用
1641     エントリがあれば valueDetect = true なければ false
1642 valueDetect==true
1643     カレントセクションが中間値補間セクションだった場合はカレントセクションをクロースして検出した値をもつ値セクションを初期化する
1644     カレントセクションの値が未設定の場合、カレントセクションの値を設定
1645     カレントセクションに値がある場合は新規の値セクションを初期化
1646 valueDetect==false
1647     エントリがない場合は中間値指定ノードとなる
1648     カレントセクションが中間値補間セクションだった場合は新規に副補間区間を初期化
1649     値区間だった場合は新規に中間値補間セクションを初期化して第一副補間区間を初期化する
1650     トラック内無効記述(コメント)は現在許可されない。
1651 */
1652     valueDetect = false;
1653     if(this[fix].match(/^\[([^\]]+)\]$/)){
1654         var checkValue=RegExp.$1;
1655         valueDetect=true;
1656     }else{
1657         var checkValue= this[fix];
1658     }
1659     var currentEntry = this.xParent.parentXps.xMap.getElementByName(checkValue);
1660     if((! currentEntry) && (valueDetect)){
1661         //new_MapElement(name,Object xMapGroup,Object Job)
1662 //        currentEntry=xMap.new_xMapElement(checkValue,MAP.getElementByName(this.id),this.xParent.parentXps.currentJob);
1663         currentEntry=checkValue;
1664     }else{
1665         valueDetect=(currentEntry)?true:false;
1666     }
1667             if(currentEntry){
1668                 if(currentNodeSign){
1669                     currentSection.duration--;//閉鎖ノード無しで前セクションを閉じるので加算したdurationをキャンセル
1670                     currentNodeSign = false;//補間区間終了ノードクリア
1671                     currentSection = myCollection.addSection(currentEntry);//新規セクション追加
1672                     currentSection = myCollection.addSection(new nas.AnimationComposite(null,currentEntry));//新規セクション追加
1673                 } else {
1674                     if (currentSection.value){
1675                         currentSection.duration--;//閉鎖ノード無しで前セクションを閉じるので加算したdurationをキャンセル
1676                         currentSection = myCollection.addSection(currentEntry);//新規セクション追加
1677                     }else{
1678                         currentSection.value=currentEntry;//値を遅延設定
1679                     }
1680                 }               
1681             } else if(currentNodeSign) {
1682             currentSubSection=currentSection.subSections.addSection();
1683             currentSubSection.duration = 1;
1684             }
1685         }
1686     }
1687     this.sections=myCollection;
1688     return this.sections;
1689 }
1690 
1691 /*
1692 簡易オブジェクトで実装
1693 エレメントのラップもしない
1694 
1695 nas.AnimationDialog Object
1696  同名のオブジェクトとの互換はあまり考えない
1697  名前が同じだけと思うが吉
1698  タイムシートサウンドトラックの値となる
1699  外部ファイルリンクはこの際割愛
1700 
1701     現在のプロパティ
1702     Property
1703 
1704     getStream(cellCount);
1705 タイムシート用のストリームを配列で返す(内部利用メソッド)
1706 引数のカウントはデータを配置するオブジェクト継続フレーム数 0〜
1707 (値は継続時間を持たない)
1708 引数0の際はラベルとセパレータ分の配列を返す
1709 
1710     toString(cellCount);
1711 引数のカウントに従ってタイムシート上での利用のためcsvストリームで戻す
1712 それ以外の場合はコンテントテクストを戻す(メソッド)
1713 
1714     contentText;    String
1715 内容テキスト原文 "たぬきさん(off)「ぽん!(SE:ポン)ぽこ!<BGM:開始>りん![光る!]」"
1716     name;    String
1717 ラベルとなる名称    "たぬきさん"
1718 
1719     bodyText;    String
1720 台詞本体のテキスト "ぽん!ぽこ!りん!"
1721 
1722     attributes;    Array
1723 オブジェクト属性の配列 ["(off)"] 
1724 
1725     comments;    Array
1726 ノートコメントコレクション配列 [[3,"(SE:ポン)"],[6,"<BGM:開始>"],[9,"[光る!]"]]
1727 コメントのインデックスはbodyText内の挿入点 シート展開時は、bodyText.length+comments.length のフレームを再配置する
1728 */
1729 nas.AnimationDialog=function(myParent,myContent){
1730     this.parent = (myParent)? myParent : null   ;//xMapElementGroup or null
1731     this.contentText=(myContent)?String(myContent):"";//xMapのソーステキストを保存する 自動で再構築が行なわれるタイミングがある
1732 
1733     this.name =''                               ;//xMap素材名(=話者の名称 *重複あり *空白あり)
1734     this.file                                   ;//nas.AnimationElementSource
1735     this.comment                                ;//
1736     this.extended = true                        ;//必ずtrue
1737 
1738     this.bodyText=""                            ;//セリフ等の本体コメント
1739     this.attributes =[]                         ;
1740     this.comments   =[]                         ;
1741     this.isDialog                               ;//ダイアログセクショングフラグ
1742     
1743     this.parseContent()                         ;//作成時に一回パースする
1744 }
1745 //
1746 /*
1747     初期化時の内容テキスト(シナリオ型式)をパースしてオブジェクト化するメソッド
1748     本来は自動実行だが、今回は必要に従ってコールする
1749     "ダブルクォーテーション",'シングルクォーテーション',「かぎかっこ」で囲まれた文字列はダイアログとして処理する
1750     それ以外はサウンドノード
1751     
1752 */
1753 nas.AnimationDialog.prototype.parseContent=function(myContent){
1754     if(typeof myContent == 'undefined') myContent = this.contentText;
1755 //xMapパーサからのグループエントリーデータなのでコンテンツをクリアして終了
1756     if(myContent.indexOf('[')==0){
1757 console.log('detect GroupEntry :'+myContent);
1758         this.contentText='';
1759         return this;
1760     }
1761     if( (this.parent)&&
1762         (myContent.indexOf(this.parent.name+'\t') == 0)&&
1763         (myContent.match(/^[\S]+\t[\S]+/))
1764     ){
1765 console.log('XXXXXXX entry :'+myContent);
1766         var myContents  = myContent.split('\n')[0].split('\t');
1767 //xMapパーサからのエントリ登録データなのでコンテンツを初期化
1768 //第三エントリが存在した場合source propertyを設定する
1769         this.name = myContents[1];
1770         if(myContents.length>2){this.file = new nas.AnimationElementSource(myContents.slice(2).join(' '));}
1771         myContent = myContent.split('\n').splice(1).join('\n');
1772     }
1773     if(myContent.length){
1774         
1775 //        if(myContent.match(/^([^"'「]*)["'「]([^"'」]*)["'」]?\s$/) ) {};//"
1776 //        if(myContent.match(/^([^「]*)「([^」]*)」?\s$/) ) {}
1777 //        if(myContent.match(/^([^「]*)「(.*)/)){}
1778 if(myContent.match(/^([^「"']*)[「"']([^」"']*)/)){
1779             this.name=RegExp.$1;
1780             this.bodyText=RegExp.$2.replace(/」\s*$/,"");
1781         }else{
1782             this.name="";
1783             this.bodyText=myContent;
1784         }
1785         var myAttributes=nas.normalizeStr(this.name).match(/\(([^)]+)\)/g);
1786 //        var myAttributes=this.name.match(/\(([^)]+)\)/g);
1787         if(myAttributes){
1788             this.attributes=myAttributes;
1789             this.name=this.name.slice(0,nas.normalizeStr(this.name).indexOf('('));
1790         }
1791         //                    本文内からコメントを抽出
1792         var myComments=this.bodyText.match(/(<[^<>]+>|\[[^\[\]]+\]|\([^\(\)]+\))|<[^<]+>|〈[^〈]+〉|([^(]+)|[[^[]+]/g);
1793         if(myComments){
1794             this.comments=[];//newArray 再初期化
1795             var myString=this.bodyText;//修正テキスト
1796             var prevIndex=0;var noteOffset=0;
1797             for (var cix=0;cix<myComments.length;cix++){
1798                 noteOffset=myString.indexOf(myComments[cix]);//修正テキスト内コメント挿入位置
1799                 this.comments.push([prevIndex+noteOffset,myComments[cix]]);
1800                 prevIndex += noteOffset;
1801                 myString=myString.slice(noteOffset+myComments[cix].length);
1802             }
1803             this.bodyText=this.bodyText.replace(/(<[^<>]+>|\[[^\[\]]+\]|\([^\(\)]+\))|<[^<]+>|〈[^〈]+〉|([^(]+)|[[^[]+]/g,"");
1804         }
1805         this.contentText = this.toString();
1806         return this
1807     }else{
1808     //内容テキストが空
1809         return false;
1810     }
1811 }
1812 /*
1813 toStringはプロパティを組み上げてMap記述用のテキストを返す
1814 ダイアログの場合はシナリオ型式のテキスト
1815 
1816 引数に正の数値でセルカウントが与えられた場合は、XPS上への展開配列ストリームで戻す。
1817 展開配列は getStream() メソッドで得る
1818 getStreamメソッドに統一してオフセットつき配列で戻す方式に変更 2018.12
1819 
1820 
1821 
1822 *各Valueの標準形式
1823 
1824 toString メソッドの共通オプションとして
1825 引数
1826     basic         xMap用1行エントリ
1827     なし/extended シナリオ形式
1828     
1829 dialogオブジェクトに関しては、標準形式と拡張形式は同じものとなるので注意
1830 
1831 */
1832 nas.AnimationDialog.prototype.toString=function(exportForm){
1833 //  if((isFinite(exportForm))&&(exportForm > 0)){
1834 //受け渡しをJSON経由にするか否かはペンディング JSONStringの場合はString.split厳禁 
1835 //    return JSON.stringify(this.getStream(exportForm));
1836 //    return (this.getStream(exportForm)).join();
1837 //  }else{}
1838     if(exportForm=='basic'){
1839         var myResult=[this.parent.name,this.name];
1840         if(this.file) myResult.push('"'+this.file.toString(true)+'"');
1841         return myResult.join('\t');
1842     }else{
1843         var myResult=this.name;
1844         myResult+=this.attributes.join("");
1845         myResult+="「";
1846         var startPt=0;
1847         if(this.comments.length){var endPt=this.comments[0][0]}else{var endPt=0};
1848         for(var cix=0;cix<this.comments.length;cix++){
1849             myResult+=this.bodyText.slice(startPt,endPt)+this.comments[cix][1];
1850             startPt=endPt;
1851             if(cix<this.comments.length-1){endPt=this.comments[cix+1][0]};
1852         }
1853         if(startPt<this.bodyText.length){myResult+=this.bodyText.slice(startPt)};
1854         myResult+="」";
1855         if(this.file) myResult+=('\tfile="'+this.file.toString(true)+'"');
1856         if(myResult=='「」') return '';
1857         return myResult;
1858     }
1859 }
1860 /*    test
1861 A=new  nas.AnimationDialog("たぬきさん(off)「ぽん!(SE:ポン)ぽこ!<BGM:開始>りん![光る!]とうりゃぁー!!」");
1862 A.parseContent();
1863 console.log(A)
1864 
1865 */
1866 /** 値を配列でもどす
1867 引数: cellCount
1868 戻値: セルのデータ並び配列+オフセット量
1869 cellCountが与えられることが前提で配列を組む
1870 ダイアログ展開時に限り、与えられた引数に対して 前方側にname,attributes+開始セパレータ 後方側に終了セパレータ分のフレームが追加される
1871 引数が0でもラベルとセパレータ分のデータが戻る
1872 ダイアログに限り指定の継続フレーム数より要素数が増える
1873 これをstartOffsetとして配列のプロパティに追加して戻す
1874 */
1875 nas.AnimationDialog.prototype.getStream=function(cellCounts){
1876     if(isNaN(cellCounts)) cellCounts = (this.contents.length+this.comments.length+this.attributes.length+3);
1877     if(cellCounts<0)cellCounts=Math.abs(cellCounts);
1878   if(cellCounts){
1879     var myResult=[];
1880 //        myResult.startOffset = -(this.attributes.length + 2);//name,attributes,startSign パース時にセクションにストア
1881     if(String(this.name).length) myResult.push(this.name);//ラベルあれば
1882     for(var aid=0;aid<this.attributes.length;aid++){myResult.push(this.attributes[aid])};//アトリビュート
1883     myResult.push('----');//開始セパレータ
1884     var entryCount = this.bodyText.length+this.comments.length;//テキスト文字数とコメント数を加算
1885     var dataCount = 0;//データカウントを0で初期化
1886     var textIndex = 0;//テクストインデックス
1887     var commentIndex = 0;//コメントインデックス
1888     var dataStep = cellCounts/entryCount ;//データステップ
1889     for(var cnt = 0; cnt < cellCounts; cnt ++){
1890         var myIndex = (entryCount >= cellCounts) ? cnt:Math.floor(cnt/dataStep);//配置Index
1891         //挿入点判定
1892         if(dataCount==myIndex){
1893             if((this.comments[commentIndex])&&(this.comments[commentIndex][0]==textIndex)){
1894                 myResult.push(this.comments[commentIndex][1]);
1895                 commentIndex++;
1896             }else{
1897                 myResult.push(this.bodyText.charAt(textIndex));
1898                 textIndex++;
1899             }
1900             dataCount++;
1901         }else{
1902             myResult.push('');
1903         }
1904     } 
1905     myResult.push('----');
1906     return myResult;
1907   }
1908 }
1909 //TEST 
1910 /*
1911         タイムラインをダイアログパースする
1912     タイムライントラックのメソッド
1913     引数なし
1914     音響開始マーカーのために、本来XPSのプロパティを確認しないといけないが、
1915     今回は省略
1916     開始マーカーは省略不可でフレーム0からしか位置できない(=音響の開始は第1フレームから)
1917     後から仕様に合わせて再調整
1918     判定内容は
1919     /^[-_]{3,4}$/    開始・終了マーカー
1920     /^\([^\)]+\)$|^<[^>]+>$|^\[[^\]]+\]$/    インラインコメント
1921     その他は
1922     ブランク中ならばラベル
1923     音響Object区間ならばコンテントテキストに積む 空白は無視する
1924     ⇒セリフ中の空白は消失するので、空白で調整をとっている台詞は不可
1925     オリジナルとの照合が必要な場合は本文中の空白を削除した状態で評価すること
1926     
1927     トラックの内容をパースしてセクションコレクションを構築する機能はトラック自身に持たせる
1928     その際、トラックの種別毎に別のパーサを呼び出すことが必要なのでその調整を行う
1929     
1930         タイムライントラックのメソッドにする
1931         ストリームはトラックの内容を使う
1932         新規にセクションコレクションを作り、正常な処理終了後に先にあるセクションコレクションを上書きする
1933         *作成中に、同じ内容のセクションはキャッシュとして使用する?
1934         戻り値はビルドに成功したセクション数(最低で1セクション)
1935         値として 無音区間の音響オブジェクト(値)を作るか又は現状のままfalse(null)等で処理するかは一考
1936 */
1937 /*
1938 _parseSoundTrack =function(){
1939     var myCollection = new XpsTimelineSectionCollection(this);//自分自身を親としてセクションコレクションを新作
1940     //この実装では開始マーカーが0フレームにしか位置できないので必ずブランクセクションが発生する
1941     //継続時間0で先に作成 同時にカラのサウンドObjectを生成
1942     var currentSection=myCollection.addSection(null);//区間値false
1943     var currentSound=new nas.AnimationDialog("");//第一有値区間の値 コンテンツはカラで初期化も保留
1944     for (var fix=0;fix<this.length;fix++){
1945         currentSection.duration ++;//currentセクションの継続長を加算
1946         //未記入データ 最も多いので最初に判定しておく
1947         if(this[fix]=="") continue;
1948         //括弧でエスケープされたコメント又は属性
1949         if(this[fix].match(/(^\([^\)]+\)$|^<[^>]+>$|^\[[^\]]+\]$)/)){
1950             if(currentSection.value){
1951                 currentSound.comments.push([currentSound.bodyText.length,RegExp.$1]);
1952             }else{
1953                 currentSound.attributes.push(RegExp.$1);
1954             }
1955             continue;
1956         }
1957         //セクションセパレータ 少ない
1958         if(this[fix].match(/^[-_]{3,4}$/)){
1959             if(currentSection.value){
1960 //終了マーカー処理
1961                 currentSection.duration --;//加算した継続長をキャンセル
1962                 currentSection.value.contentText=currentSound.toString();//先の有値セクションをフラッシュして
1963                 currentSection=myCollection.addSection(null);//新規のカラセクションを作る
1964                 currentSection.duration ++;//キャンセル分を後方区間に加算
1965                 currentSound=new nas.AnimationDialog("");//サウンドを新規作成
1966             }else{
1967 //開始マーカー処理
1968 //引数をサウンドオブジェクトでなくxMapElementに変更予定
1969 //                nas.new_MapElement(name,Object xMapGroup,Object Job);
1970                 currentSection=myCollection.addSection(currentSound);//新規有値セクション作成
1971 //                currentSection.value.
1972             }
1973                         continue;
1974         }
1975 //判定を全て抜けたデータは本文又はラベル ラベルは上書きで更新
1976 //ラベル無しの音声オブジェクトは無しのまま保存 必要に従って先行オブジェクトのラベルを引継ぐ
1977         if(currentSection.value){
1978             if(this[fix]=="|") this[fix]="ー";
1979             currentSound.bodyText+=this[fix];
1980         }else{
1981             currentSound.name=this[fix];
1982         }
1983     }
1984     this.sections=myCollection;
1985     return this.sections;
1986 }
1987 */
1988 _parseSoundTrack =function(){
1989     var myCollection = new XpsTimelineSectionCollection(this);//自分自身を親としてセクションコレクションを新作
1990     //この実装では開始マーカーが0フレームにしか位置できないので必ずブランクセクションが発生する
1991     //継続時間0で先に作成 同時にカラのサウンドObjectを生成
1992     var groupName = this.id;
1993     var myGroup = this.xParent.parentXps.xMap.getElementByName(groupName);
1994     if (!myGroup) myGroup = this.xParent.parentXps.xMap.new_xMapElement(
1995         this.id,
1996         'dialog',
1997         this.xParent.parentXps.xMap.currentJob,
1998         ""
1999     ) ;//nas.xMapGroup(groupName,'dialog',null);//new nas.xMapGroup(myName,myOption,myLink);
2000     var currentSection=myCollection.addSection(null);//区間値false
2001     var currentSound=new nas.AnimationDialog(myGroup,"");//第一有値区間の値コンテンツはカラで初期化も保留
2002     for (var fix=0;fix<this.length;fix++){
2003         currentSection.duration ++;//currentセクションの継続長を加算
2004         //未記入データ最も多いので最初に判定しておく
2005         if(this[fix]=="") continue;
2006         //括弧でエスケープされたコメント又は属性
2007         if(this[fix].match(/(^\([^\)]+\)$|^<[^>]+>$|^\[[^\]]+\]$)/)){
2008             if(currentSection.value){
2009                 currentSound.comments.push([currentSound.bodyText.length,RegExp.$1]);
2010             }else{
2011                 currentSound.attributes.push(RegExp.$1);
2012             }
2013             continue;
2014         }
2015         //セクションセパレータ少ない
2016         if(this[fix].match(/^[-_~^〜_ー ̄]{3,4}$/)){
2017             if(currentSection.value){
2018                 currentSection.duration --;//加算した継続長をキャンセル
2019                 currentSection.value.contentText=currentSound.toString();//先の有値セクションをフラッシュして
2020                 currentSection.tailMargin = 1;//-1
2021                 currentSection=myCollection.addSection(null);//新規のブランクセクションを作る
2022                 currentSection.headMargin = -1;
2023                 currentSection.duration ++;//キャンセル分を後方区間に加算
2024                 currentSound=new nas.AnimationDialog(groupName,null);//サウンドを新規作成
2025             }else{
2026 //引数をサウンドオブジェクトでなくxMapElementに変更予定
2027 //                nas.new_MapElement(name,Object xMapGroup,Object Job);
2028 //console.log(currentSound.name);
2029                 var sectionOffset = (currentSound.name)? 2 : 1 ;
2030                 sectionOffset += currentSound.attributes.length;
2031                 currentSection.tailMargin= -sectionOffset;
2032                 currentSection=myCollection.addSection(currentSound);//新規有値セクション作成
2033                 currentSection.headMargin = sectionOffset;
2034 //console.log('ValuedSection offset :'+ sectionOffset)
2035 //                currentSection.value.
2036             }
2037                         continue;
2038         }
2039 //判定を全て抜けたデータは本文又はラベルは上書きで更新
2040 //ラベル無しの音声オブジェクトは無しのまま保存必要に従って先行オブジェクトのラベルを引継ぐ
2041         if(currentSection.value){
2042             if(this[fix]=="|") this[fix]="ー";
2043             currentSound.bodyText+=this[fix];
2044         }else{
2045             currentSound.name=this[fix];
2046         }
2047     }
2048 // 最終セクションは必ずブランクセクションになるのでtailMarginを設定する
2049 // 最終セクションが長さ0の有値セクションになる可能性があるので注意!
2050 //    currentSection.tailMargin = -1;
2051     this.sections=myCollection;
2052     return this.sections;
2053 }
2054 
2055 /** //test
2056 XpsTimelineTrack.prototype.parseSoundTrack=_parseSoundTrack;
2057 XPS.xpsTracks[0].parseSoundTrack();
2058 XPS.xpsTracks[0].sections[1].toString();
2059 
2060 XpsTimelineTrack.prototype.parseSoundTrack=_parseSoundTrack;
2061 //XpsTimelineTrack.prototype.parseDialogTrack=_parseDialogTrack;
2062 
2063 //XpsTimelineTrack.prototype.parseKeyAnimationTrack=_parsekeyAnimationTrack;
2064 //XpsTimelineTrack.prototype.parseAnimationTrack=_parseAnimationTrack;
2065 XpsTimelineTrack.prototype.parseReplacementTrack=_parseReplacementTrack;
2066 
2067 XpsTimelineTrack.prototype.parseCameraWorkTrack=_parseCameraworkTrack;
2068 
2069 XpsTimelineTrack.prototype.parseCompositeTrack=_parseCompositeTrack;//コンポジット
2070 
2071 //XpsTimelineTrack.prototype.parseTrack=_parseTrack;
2072 //XpsTimelineTrack.prototype.parseTrack=_parseTrack;
2073 */
2074 /**
2075 
2076     タイムラインをパースしてセクション及びその値を求めるメソッド
2077     タイムライン種別ごとにパースするオブジェクトが異なるので
2078     各オブジェクトに特化したパーサが必要
2079     別々のパーサを作ってセクションパーサから呼び出して使用する
2080     Sound
2081         parseSoundTrack
2082         *parseDialogTrack
2083     Replacement
2084         parseKyeDrawind(補間区間あり)
2085         parseAnimationCell(確定タイムライン)
2086     Geometry
2087         parseCameraworkTrack
2088     Composite
2089         parseEffectTrack
2090     各々のパーサは、データ配列を入力としてセクションコレクションを返す
2091     各コレクションの要素はタイムラインセクションオブジェクト
2092     値はタイムライン種別ごとに異なるがセクション自体は共通オブジェクトとなる
2093 
2094 XpsTimelineTrack.prototype.parseTimelineTrack = function(){
2095     switch(this.option){
2096         case "dialog":;
2097             return this.parseDialogTrack();
2098         break;
2099         case "sound":;
2100             return this.parseSoundTrack();
2101         break;
2102         case "cell":;
2103         case "timing":;
2104         case "replacement":;
2105             return this.parseReplacementTrack();
2106         break;
2107         case "camerawork":;
2108         case "camera":;
2109             return this.parseCameraworkTrack();
2110         break;
2111         case "effect":;
2112         case "sfx":;
2113         case "composit":;
2114             return this.parseCompositeTrack();
2115         break;
2116     }
2117 }
2118 */
2119 /** Xpsに対するエージェントオブジェクト
2120  *  
2121  *  XpsデータをxMapに対して登録する際の代理オブジェクト
2122  *
2123  * 
2124  *
2125  *
2126  *
2127  *
2128  *
2129  *
2130  */
2131 nas.XpsAgent=function(myParent,myContent){
2132     this.parent = (myParent)? myParent : null     ;
2133     this.contentText=(myContent)?String(myContent):"";//xMapのソースを保存する 自動で再構築が行なわれるタイミングがある
2134 
2135     this.name                                     ;//素材名
2136     this.source                                   ;//nas.AnimationElementSource
2137     this.comment                                  ;//コメント文字列 エレメントの注釈プロパティ-xMap編集UIのみで確認できる
2138     this.extended = false;
2139 
2140     this.attributes=[];
2141     this.comments=[];
2142 
2143     this.parseContent(myContent)
2144 }
2145 /**
2146     文字列化して返す
2147 */
2148 nas.XpsAgent.prototype.toString=function(exportForm){
2149 return this.contentText;//動作確認用ダミー行
2150 }
2151 /**
2152     コンテンツを与えてパースする
2153     引数がない場合は自身のコンテンツデータを再パースする
2154     戻り値はオブジェクト自身
2155 */
2156 nas.XpsAgent.prototype.parseContent=function(myContent){
2157     if(typeof myContent == 'undefined'){
2158         myContent = this.contentText ;
2159     }
2160     this.contentText = (myContent)?String(myContent):"";
2161     return this;
2162 }
2163 /** タイムシートに記述されるカメラワークの抽象化クラス
2164  *
2165  * FI,FO,OL,WIPE
2166  * SL,PAN,TILT,TU,TB
2167  *  等々の実際の処理に展開される抽象化シンボルを扱うクラスオブジェクト
2168  * シンボルデータベースnas.cameraDescriptionsを参照する
2169  *  シンボルを扱うため基本的にはxMapとのリレーションがダイアログと同様にトラックに対する強い接続を持たない
2170  *  (=トラックが単なるキャリアとなる グループ内部のオブジェクト毎に再構成が必要)
2171  * cameraworkトラックのセクション値
2172  *  
2173  * nas.AimationCamerawork
2174  ex.
2175 targets name attributes descriptions comments
2176 symbol:◎
2177     symbol記述は、演出効果等で他の分類に収まらないかまたは複合的な状態を表す記述に対して用いられる分類
2178     例えば
2179     follow:symbol
2180     followSL:geometry
2181 
2182 transition:*
2183      トラジション記述の場合はターゲットの指定が不可欠
2184 ]x[ または ]><[ でトランジションの対象となる素材指定ができる
2185 外ブラケットは解釈しない
2186 対象が複数の場合はカンマで分離
2187 処理シンボルは省略可能 その場合は無名トランジションとして扱う(オーバーラップディゾルブを補う?)
2188     ex.(transition)
2189 s-c12]><[s-c13   <OL> (3+0)
2190 s-c12]><[s-c13   <WIPE>(2+0)
2191 A-1,B-3]><[A-2,B-4 <中OL> (0+18)
2192 
2193 
2194 geometry:☆
2195     name attributes.join('-') comments .join(',')
2196     ex.(geometry)
2197 <PAN> [A]-[B] >2つまで、 これ以上はセクション側で連結する 
2198 <TU> [A]-[B]
2199 A,B,C <slide> [1]-[2]-[3] ([2],[3]間フェアリング)
2200 
2201 <follow> → (stage ← 2mm/k)
2202 
2203     ex.(geometry.zigzag)
2204 
2205 composite:○
2206     ex.(composite.fi fo)
2207 <FI> ▲ (1+12)
2208 <FO> ▼ (time)
2209 
2210 effect:□
2211     ex.(effect)
2212 BG,A,E <透過光> 強 
2213 
2214 ***"effect"は予約タイプ現在(2019時点)使用されていない
2215 
2216 xps description sample
2217 CAM1
2218 [start]  <後続セクション属性として保存
2219 ▼   ┐
2220 |   中間値補完区間が同時にカメラワークのセクションとなる
2221 |   この区間の名称及びサブプロパティは前置の形で前方セクションに置かれる
2222 |   前方セクションは必ずブランクセクションに(セリフと同様に扱う)
2223 PAN     nameは中央配置
2224 |       表示優先順位は name>startNode>endNode>bar
2225 |
2226 |
2227 ▲   ┘
2228 [end]   <先行セクションの属性値として保存
2229 
2230  */
2231 nas.AnimationCameraworkPrefix={
2232     symbol:"◎",
2233     transition:"*",
2234     geometry:"☆",
2235     composite:"○",
2236     effect:"□"
2237 };
2238 nas.AnimationCamerawork=function(myParent,myContent){
2239     this.parent = (myParent)? myParent : null     ;//xMapElementGroup or null
2240     this.contentText=(myContent)?String(myContent):"";//xMapのソースを保存する 自動で再構築が行なわれるタイミングがある
2241 
2242     this.name   = ''                            ;//カメラワークシンボル名 値を識別する名称<矢括弧>でセパレート 正規化が行われた場合のトラック名になる
2243     this.file                                     ;//nas.AnimationElementSource(設定されない)
2244     this.comment                                  ;//コメント文字列 エレメントの注釈プロパティ-xMap編集UIのみで確認できる(設定されない)
2245     this.extended = true                          ;//常にtrue
2246 
2247     this.type         = ['symbol','']             ;//typeStringArray symbol,geometry,compositeをマスタータイプ サブタイプでエフェクトの種類が記録される DBとの対照で決定する
2248     this.attributes   = []                        ;//セパレートされていない文字列のうちnameにならなかったもの 通常は撮影指定コメント
2249     this.comments     = []                        ;//丸かっこでセパレートされたコメントの中身
2250     this.descriptions = []                        ;
2251     this.targets      = []                        ;//ワーク対象素材配列空の場合はカット全体が対象 トランジションの場合は必ず2要素の配列
2252                                                   ;//分割されたコンテンツ冒頭で、トラックIDと一致するもの A,B,BG,BOOK等
2253                                                   ;//トランジションの場合は分離要件を調整する
2254     this.prefix;                                   //セクション冒頭で[ブラケット]で囲まれる表示
2255     this.postfix;                                  //セクション末尾で[ブラケット]で囲まれる表示
2256     
2257     this.parseContent();
2258 }
2259 /**
2260     文字列化して返す
2261     
2262 書式は
2263     対象素材(省略可 省略時はカット全体)
2264     効果・識別名
2265     付属パラメータ(タイプごとに定義)composite,transition,geometry,effect,zigzag,fi,fo,stroboIn,stroboOut 等
2266 symbol:(未分類)
2267 
2268 
2269 連結条件は、トラック内でガードバンドを挟んで同じtarget,type,name のセクションが隣接している場合のみ
2270 カメラワーク(シンボル)トラック内のセクションは、ガードバンドがあってもなくても良い
2271 ジオメトリカメラワークトラック値セクションの前後には最低1フレームのガードバンドが入る
2272 引数:    exportForm   出力書式
2273     basic         :xMap用1行エントリ
2274     ナシ/extend   :タイムシートメモ形式1行エントリ
2275 */
2276 nas.AnimationCamerawork.prototype.toString=function(exportForm){
2277     if(! this.name) return '';//
2278 if(exportForm == 'basic'){
2279         var resultArray=[(this.parent)?this.parent.name:"",this.name];
2280         if(this.file)         resultArray.push('"'+ this.file.toString(true)+'"');
2281         return resultArray.join("\t");
2282     }else{
2283     var descriptionPrefix="";
2284     var myResult=[];
2285 //target
2286     if(this.targets.length){
2287         if(this.type[0]=='transition'){
2288             myResult.push([this.targets[0].join(','),"]><[",this.targets[1].join(',')].join(''));
2289         }else{       
2290             myResult.push(this.targets.join(','));
2291         }
2292     }
2293 //warkName
2294     if(String(this.name).length) myResult.push('<'+this.name+'>');//文字列は<矢括弧>でセパレートする
2295 //attribute
2296     switch(this.type[0]){
2297     case "symbol":
2298         if(this.attributes.length) myResult.push(this.attributes.join(" "));
2299     break;
2300     case "transition":
2301     case "composite":
2302     case "geometry":
2303     default:
2304         if(this.attributes.length) myResult.push(this.attributes.join("-"));        
2305     }
2306     if(this.descriptions.length) myResult.push(this.descriptions.join(' '));
2307     if(this.comments.length) myResult.push('(' + this.comments.join(') (') + ')');
2308     
2309     myResult = myResult.join(' ');
2310     if(this.file)         myResult+=('\n\tfile="'+ this.file.toString(true)+'"');
2311     return nas.AnimationCameraworkPrefix[this.type[0]] +' '+ myResult;
2312     }
2313 }
2314 /*TEST
2315 A = new nas.AnimationCamerawork(null,"A,B,C <FI> ▲ (1+12)");
2316 B = new nas.AnimationCamerawork({name:'CAM1'},"<PAN> [A]-[B]-[C] (2+13) (ラスト早く)");
2317 */
2318 /**
2319     コンテンツを与えてパースする
2320     引数がない場合は自身のコンテンツデータを再パースする
2321     xMapの記述は、基本的にダイアログと同等。入力はメモ欄に記述するテキストとほぼ等価
2322     メモ記述ライン冒頭が段落マーク(◎*○●◇◆☆★等の強調サイン)だった場合はそれを無視して評価する
2323     toStringでえられる文字列を自動でメモ記述欄にカット間トランジションと同様に表示する(ユーザ指定外)
2324     メモ欄にユーザが入力した記述はメモ内容をパースして、カメラワーク記述を認識した場合タイムシートへの挿入を問い合わせる?
2325 
23262327 ★ A,B,C <Slide> ↑ [1]→[2]→[3] 
2328 ☆ クロコマ
2329 ※ pan [A]-[B]
2330 * follow 
2331233223332334 ■ 黒コマ
2335 □ 白コマ
2336 <<
23372338 
2339 等になる
2340 コンマ区切りのフィールド(フレーム)数に関わりなく
2341 name        明示的<シンボル名>・暗示的シンボル名
2342 prefix      コンテンツ頭の[ブラケット]で囲まれた要素
2343 postfix     コンテンツ末尾の[ブラケット]で囲まれた要素
2344 attributes  カッコのないむき出しの要素 基本的に素材ターゲット、transitionターゲットの場合は配列の配列
2345 comments    (丸かっこ)で囲まれた要素 数値指定 尺指定はこの形式で統一
2346 省略サインはすべて無視
2347 
2348 トランジションのセパレータは /\](x|><|.+)\[/
2349 
2350 
2351 xMap上の記述の形式
2352 [CAM1   CAMERAWORK]
2353     グループ(トラック)登録
2354 グループ(トラック)に、記述上の位置を示す以上の意味はない。
2355 デフォルト値には有効な値が存在しない。
2356 空白セクションに対応する「無効値」がデフォルト値となる。
2357 よってグループ記述に対する値のパースは「名前だけを持った無効値」を返す。
2358 */
2359 nas.AnimationCamerawork.prototype.parseContent=function(myContent){
2360     if(typeof myContent == 'undefined'){
2361         myContent = this.contentText ;
2362     }
2363 
2364 //xMapパーサからのグループエントリーデータなのでコンテンツをクリアして終了
2365   if(myContent.indexOf('[')==0){
2366 //console.log('detect GroupEntry :'+myContent);
2367     this.contentText  ='';
2368 //    this.name         = undefined;
2369 //    this.file         = undefined;
2370 //    this.comment      = undefined;
2371 //    this.type         = ['symbol',''];
2372 //    this.attributes   = [];
2373 //    this.comments     = [];
2374 //    this.descriptions = [];
2375 //    this.targets      = [];
2376 //    this.prefix       =undefined;
2377 //    this.postfix      =undefined;
2378         return this;
2379 }
2380     myContent = nas.normalizeStr(myContent);
2381     myContentLines = myContent.split('\n');
2382     this.attributes   = [];
2383     this.comments     = [];
2384     this.descriptions = [];
2385     this.targets      = [];
2386     this.prefix       = undefined;
2387     this.postfix      = undefined;
2388 
2389     var myName        = '';
2390     var myTargets     = [];
2391     var myProps       = [];
2392     var bracketValues = [];
2393 
2394     for (var lid=0;lid<myContentLines.length;lid++){
2395         if(String(myContentLines[lid]).length==0) continue;//カメラワークでは意味を持たないので空白行スキップ
2396 //console.log([myContentLines[lid].indexOf(this.parent.name+'\t')])
2397     if( (this.parent)&&
2398         (myContentLines[lid].indexOf(this.parent.name+'\t') == 0)&&
2399         (myContentLines[lid].match(/^[\S]+\t[\S]+/))
2400     ){
2401 //console.log('XXXXXXX entry :'+myContentLines[lid]);
2402         var myContents  = myContentLines[lid].split('\t');
2403 //xMapパーサからのエントリ登録データなのでコンテンツを初期化
2404 //第三エントリが存在した場合source propertyを設定する
2405         this.name = myContents[1];
2406         if(myContents.length>2){this.file = new nas.AnimationElementSource(myContents.slice(2).join(' '));}
2407         continue;
2408     }else{
2409 //プロパティ単独記述 プロパティ別のパースが必要だが、ここで処理しないほうが良いかも その場合はtoString側も要修正
2410     if(myContentLines[lid].match(/^\t([^=\s]+)=(.+)/)){
2411 //console.log('single propertiy =========================='+ myContent+'+++++');
2412         var myPrp = RegExp.$1; var myVlu = RegExp.$2;
2413         switch(myPrp){
2414         case 'file':this.file = new nas.AnimationElementSource(myVlu);break;
2415         default : this[myPrp]=myVlu;
2416         }
2417         continue;
2418     }
2419     var myContents    = (myContentLines[lid].replace(/^[◎*◯○●・◇◆☆★]/g,"").replace(/\s+/g,'\t')).split('\t');
2420 //console.log(this.parent.name);
2421 //console.log(myContents);
2422 //    var myName        = '';
2423 //    var myTargets     = [];
2424 //    var myProps       = [];
2425 //    var bracketValues = [];
2426 
2427 //name検出
2428     if (myContent.match(/<([^<]+)>/)){
2429         myName = RegExp.$1;
2430     } else if(myContents.length){
2431         var myWord = '';
2432         for( var cix = 0; cix < myContents.length ; cix ++){
2433             //書式上カメラワーク指定外のエントリをスキップ
2434             if(myContents[cix].match(/^\[|^\(|(cell|セル|BG.*|BOOK.*)$|\)$|,/i)) continue;
2435             if(! myWord) myWord = myContents[cix];//最初の候補単語を控える
2436             if(nas.cameraworkDescriptions.get(myContents[cix])){
2437                 myName = myContents[cix];
2438                 myContents.splice(cix,1);
2439                 break;
2440             }
2441         }        
2442         if(! myName) myName = (myWord)? myWord : "";//!注意点!
2443 /*  カメラワークの名称を取得できなかった場合は、遅延解決のため必ず""(空文字列)に設定のこと */
2444     }
2445 // トランジション検出
2446 //  カメラワークタイプがトランジションに固定されて名前はトランジションのサブタイプ(種別)情報となる
2447     var detectTransition = myContent.match(/([^\[\s]+)\]([^\[\-ー→]+)\[([^\]\s]+)/i);
2448 //console.log(detectTransition);
2449     if(detectTransition){
2450         if((myName == detectTransition[0])||(myName == '')) myName = detectTransition[2];
2451         this.targets=[detectTransition[1].split(','),detectTransition[3].split(',')];   
2452         if(myName.match(/x|></i)) myName = 'transition';//noname transition sign
2453     }
2454     this.name = myName;
2455 //検出したシンボルからタイプ
2456     var mySymbol = nas.cameraworkDescriptions.get(this.name);
2457     if (! mySymbol) mySymbol = nas.cameraworkDescriptions.get('unknown')
2458 /*symbol未検出時はユーザ指定を促すか?*/
2459     this.type = [mySymbol.type,mySymbol.name];
2460 
2461 //コメント検出
2462     var commentsGet = myContent.match(/\(([^\)]+)\)/g);
2463 //コメントリダクション
2464     if(commentsGet) {
2465         for (var cix = 0 ;cix < commentsGet.length;cix ++){
2466             commentsGet[cix] = commentsGet[cix].replace(/^\(\s*|\s*\)$/gi,'');
2467             if(! commentsGet[cix]) continue;
2468             this.comments.push(commentsGet[cix]);
2469         }
2470     }
2471 
2472 //タイプ別に残りの属性値を判別
2473 //console.log(myContents);
2474     for(var cix = 0 ; cix < myContents.length ; cix++){
2475 //transition指定エントリをスキップ
2476         if((detectTransition)&&(myContents[cix] == detectTransition[0])){
2477 //console.log(myContents[cix]);
2478             continue;
2479         }
2480 //コメント取得済みなのでスキップ
2481         if(myContents[cix].match(/^\(|\)&/)) continue;
2482 //カメラワーク名スキップ
2483         var checkName = myContents[cix].match(new RegExp('<?'+this.name+'>?','i'));
2484         if((checkName)&&(checkName[0])){
2485 //console.log(checkName);
2486             continue;
2487         }
2488 //ターゲット検出
2489 //この時点ではポストフィックスと空エントリが含まれる
2490         if(myContents[cix].match(/(cell|セル)$|(BG.*|BOOK.*)$|,/i)){
2491 //console.log(myContents[cix]);
2492             if((myContents[cix].indexOf(',') > 0)){
2493                 myTargets = myTargets.concat(myContents[cix].split(','));
2494                 continue;
2495             }else{
2496                 myTargets.push(myContents[cix]);
2497             }
2498             continue;
2499         }
2500 //残りはすべてアトリビュート
2501 //[ブラケット]
2502 //console.log(myContents[cix]);
2503        if( myContents[cix].match(/^(\[[^\]]+\][-ー→]?)+/)){
2504             bracketValues  = bracketValues.concat(myContents[cix].replace(/[-ー→]/g,",").split(','));
2505             continue
2506         }
2507         switch (this.type[0]){
2508         case "composite":
2509             if((mySymbol.nodeSigns)&&(mySymbol.nodeSigns.length > 2)&&(myProps.indexOf(mySymbol.nodeSigns[1]) < 0)){
2510                 myProps.push(mySymbol.nodeSigns[2]);
2511             }
2512         case "geometry":
2513         case "transition":
2514         case "symbol":
2515         default:
2516             myProps.push(myContents[cix]);
2517         }    
2518     }
2519 //myTargetsリダクション
2520         
2521     for (var tix = 0 ;tix < myTargets.length;tix ++){
2522         if(myTargets[tix] instanceof Array){this.targets.push(myTargets[tix]);continue;}
2523         if(! myTargets[tix]) continue;
2524         this.targets.push(myTargets[tix].replace(/(cell|セル)$/gi,''));
2525     }
2526 //bracketValuesリダクション
2527     for (var bix = 0 ;bix < bracketValues.length;bix ++){
2528         if(! bracketValues[bix]) continue;
2529         this.attributes.push(bracketValues[bix]);
2530         if(! this.prefix)                   this.prefix  = bracketValues[bix];
2531     }
2532     if((this.prefix)&&(! this.postfix)) this.postfix = this.attributes[this.attributes.length - 1];
2533 //myPropsリダクション
2534     for (var pix = 0 ;pix < myProps.length;pix ++){
2535         if(! myProps[pix]) continue;
2536         var isGroup=false;
2537         if((this.parent)&&(this.parent instanceof nas.xMapGroup)) isGroup = this.parent.link.stage.line.parent.getElementByName(myProps[pix]);
2538         if((isGroup)&&(isGroup instanceof nas.xMapGroup)){
2539             this.targets.push(myProps[pix]);
2540         }else{
2541             this.descriptions.push(myProps[pix]);
2542         }
2543     }
2544   }
2545     }
2546     this.contentText = this.toString();//(myContent)?String(myContent):"";
2547     return this;
2548 }
2549 /* TEST
2550 new nas.AnimationCamerawork(null,"A,B,Cセル BG BOOK2 BOOK3 SL [A]-[B] (じんわり)");
2551 
2552 new nas.AnimationCamerawork(null,"slide");
2553 new nas.AnimationCamerawork(null,"BOOK3 FI ()");
2554 new nas.AnimationCamerawork(null,"クロコマ");
2555 
2556 */
2557 
2558 
2559 /**
2560 
2561 ストリームの構造
2562 [A] prefix
2563 ▽   StartSign
2564 |       interpSign
2565 |
2566 <PAN>       name
2567 |
2568 |
2569 △   EndSign
2570 [B] postfix
2571 
2572 ブラケット値以外のアトリビュートが記録されないので何らかの処置を取る
2573 コメント表示を行う必要がある
2574 メモ欄に流し込んで、両方を合成処理するか?
2575 
2576 
2577 prfix<postfix<name<StartSign<endSign<interpSign
2578 */
2579 nas.AnimationCamerawork.prototype.getStream=function(cellCounts){
2580     if(isNaN(cellCounts)) cellCounts = 1;//1  > minimumCount
2581 
2582     var minCount = 1 ;//name
2583 //    if(this.prefix)  minCount++;
2584 //    if(this.postfix) minCount++;
2585 
2586 
2587     if(cellCounts<0)cellCounts=Math.abs(cellCounts);
2588     if(cellCounts >= minCount){
2589         var mySymbol = nas.cameraworkDescriptions.get(this.type[1]);
2590         if(! mySymbol) mySymbol = nas.cameraworkDescriptions.get('bar');
2591         var myName = (mySymbol.nodeSigns.length == 1) ?mySymbol.nodeSigns[0]:'<'+this.name+'>';
2592         var myResult = new Array(cellCounts);
2593         for (var ix = 0 ; ix < cellCounts ;ix ++){
2594             if(ix == Math.floor((cellCounts-(1+this.comments.length))/2)){
2595                 myResult[ix] = myName;
2596                 if(this.comments.length){
2597                     for (var cx = 0 ;cx<this.comments.length;cx++){
2598                         myResult[ix+cx+1] = '('+this.comments[cx]+')';
2599                     }
2600                     ix += this.comments.length;
2601                 }
2602                continue;
2603             }
2604             if ((ix == 0)&&(mySymbol.nodeSigns[1])){
2605                 myResult[ix] = mySymbol.nodeSigns[1];
2606                 continue;
2607             }
2608             if ((ix == (cellCounts-1))&&(mySymbol.nodeSigns[1])){
2609                 myResult[ix] = (mySymbol.nodeSigns[2])?mySymbol.nodeSigns[2]:mySymbol.nodeSigns[1];
2610                 break;
2611             }
2612             myResult[ix] = mySymbol.nodeSigns[0];
2613         }
2614         if(this.prefix)  myResult = [this.prefix].concat(myResult);
2615         if(this.postfix) myResult = myResult.concat([this.postfix]);
2616  
2617      return myResult;
2618   }
2619 }
2620 
2621 
2622 /** 単純な記録が必要な場合のオブジェクト
2623  * 基礎的なデータを保持
2624  *  コンテの記述等がこの値で保持される
2625  *  また共通に要求されるメソッドの雛形
2626  *
2627  *  タイムシートのトラックの値として利用されることはない
2628  */
2629 nas.StoryboardDescription=function(myParent,myContent){
2630     this.parent = (myParent)? myParent : null     ;//xMapElementGroup or null
2631     this.contentText=(myContent)?String(myContent):"";//xMapのソースを保存する 自動で再構築が行なわれるタイミングがある
2632 /** ex.
2633 [description   text]
2634 description s-c4
2635 #----------------------------------------------------------------
2636 	カメラ背中側から
2637 	<PAN↑UP>
2638 	立てかけた猟銃 その他 猟師さん風荷物など見える
2639 	
2640 	バタバタとうちわであおぐ
2641 #----------------------------------------------------------------    
2642 絵コンテのト書きに相当する行頭のタブを払って記録される
2643 */
2644 
2645     this.name                                     ;//素材名
2646     this.source                                   ;//nas.AnimationElementSource
2647     this.comment                                  ;//コメント文字列 エレメントの注釈プロパティ-xMap編集UIのみで確認できる
2648     this.extended = false;
2649 
2650     this.type;  //typeString storyBoardText 
2651     this.attributes=[];
2652     this.comments=[];
2653     
2654     this.parseContent();
2655 }
2656 /**
2657     文字列化して返す
2658 */
2659 nas.StoryboardDescription.prototype.toString=function(exportForm){
2660 return this.contentText;//動作確認用ダミー行
2661 }
2662 /**
2663     コンテンツを与えてパースする
2664     引数がない場合は自身のコンテンツデータを再パースする
2665 */
2666 nas.StoryboardDescription.prototype.parseContent=function(myContent){
2667     if(typeof myContent == 'undefined'){
2668         myContent = this.contentText ;
2669     }
2670     this.contentText = (myContent)?String(myContent):"";
2671     return this;
2672 }
2673 
2674 nas.StoryboardDescription.prototype.getStream=function(cellCounts){
2675     if(isNaN(cellCounts)) return this.getContent();//cellCounts = this.getContent().length;?
2676     if(cellCounts<0)cellCounts=Math.abs(cellCounts);
2677   if(cellCounts){
2678     var myResult = new Array(cellCounts);
2679     myResult[0]=(this.name)? this.name:"";
2680     
2681     if(String(this.name).length) myResult.push(this.name);//ラベルあれば
2682     for(var aid=0;aid<this.attributes.length;aid++){myResult.push(this.attributes[aid])};//アトリビュート
2683     myResult.push('----');//開始セパレータ
2684     var entryCount = this.bodyText.length+this.comments.length;//テキスト文字数とコメント数を加算
2685     var dataCount = 0;//データカウントを0で初期化
2686     var textIndex = 0;//テクストインデックス
2687     var commentIndex = 0;//コメントインデックス
2688     var dataStep = cellCounts/entryCount ;//データステップ
2689     for(var cnt = 0; cnt < cellCounts; cnt ++){
2690         var myIndex = (entryCount >= cellCounts) ? cnt:Math.floor(cnt/dataStep);//配置Index
2691         //挿入点判定
2692         if(dataCount==myIndex){
2693             if((this.comments[commentIndex])&&(this.comments[commentIndex][0]==textIndex)){
2694                 myResult.push(this.comments[commentIndex][1]);
2695                 commentIndex++;
2696             }else{
2697                 myResult.push(this.bodyText.charAt(textIndex));
2698                 textIndex++;
2699             }
2700             dataCount++;
2701         }else{
2702             myResult.push('');
2703         }
2704     } 
2705     myResult.push('----');
2706     return myResult;
2707   }
2708 }
2709 
2710 /** nas.AnimationAppearance
2711  *  
2712  *  ブランク(カラセル)管理セクションで使用されるアピアランスに特化した値
2713  * 値は ON-OFF 状態をbooleanで持つ
2714  * ソース等のプロパティは持たない 一時的な値でありxMapに記述されることはない
2715  * コンテントテキスト
2716  *
2717  */
2718 nas.AnimationAppearance=function(myParent,myContent){
2719     this.parent      = (myParent)? myParent : null     ;
2720     this.contentText = (myContent)? myContent : "on"       ;
2721     this.appearance  = false       ;//表示状態を表す
2722 
2723     this.parseContent();
2724 }
2725 /**
2726     文字列化して返す
2727 */
2728 nas.AnimationAppearance.prototype.toString=function(exportForm){
2729 return (this.appearance)?"ON":"OFF";//動作確認用ダミー行
2730 }
2731 /**
2732     コンテンツを与えてパースする
2733     引数がない場合は自身のコンテンツデータを再パースする
2734     xMapのエントリを扱うためCellDescriptionの持つ正規表現オブジェクトを直接使用しない
2735     戻り値はオブジェクト自身
2736 */
2737 nas.AnimationAppearance.prototype.parseContent=function(myContent){
2738     var blankRegex=new RegExp("^(\\b|blank(-cell)?|off|false|empty|"+nas.CellDescription.blankSigns.join("|")+")$","i");
2739     if(typeof myContent == 'undefined'){
2740         myContent = this.contentText ;
2741     }
2742 
2743     this.appearance = (this.contentText.match(blankRegex))? false : true ;
2744 
2745     return this;
2746 }
2747 /*静止画トラックのパース
2748 静止画トラックは基本的に置き換えのない静止画のみを扱う
2749 値は AnimationAppearanceに画像名(AnimationSource)を与えて使用する
2750 認識するセル記述は [on/off][true/false][empty/full][blank/fill][disappearance/appearance][0/1]等の二項記述
2751 
2752 入れ替えが必要な場合は、ReplacementTrackを使用するかまたは複数の静止画トラックを使用すること
2753 */
2754 _parseStillTrack =function(){
2755     var myCollection = new XpsTimelineSectionCollection(this);//自分自身を親としてセクションコレクションを新作
2756     //この実装では開始マーカーが0フレームにしか位置できないので必ずブランクセクションが発生する
2757     //継続時間0で先に作成 同時にカラのサウンドObjectを生成
2758     var groupName = this.id;
2759     var myGroup = this.xParent.parentXps.xMap.getElementByName(groupName);
2760     if (!myGroup) myGroup = this.xParent.parentXps.xMap.new_xMapElement(
2761         this.id,
2762         'CELL',
2763         this.xParent.parentXps.xMap.currentJob,
2764         [this.id,""].join('\t')
2765     ) ;//nas.xMapGroup(groupName,'dialog',null);//new nas.xMapGroup(myName,myOption,myLink);
2766     var currentValue=new nas.AnimationAppearance(myGroup,"");//第一有値区間の値コンテンツはカラで初期化も保留
2767     var currentSection=myCollection.addSection(null);//区間値false
2768     for (var fix=0;fix<this.length;fix++){
2769         currentSection.duration ++;//currentセクションの継続長を加算
2770         //未記入データ最も多いので最初に判定しておく
2771         if(this[fix]=="") continue;
2772         //括弧でエスケープされたコメント又は属性
2773         if(this[fix].match(/(^\([^\)]+\)$|^<[^>]+>$|^\[[^\]]+\]$)/)){
2774             if(currentSection.value){
2775                 currentSound.comments.push([currentSound.bodyText.length,RegExp.$1]);
2776             }else{
2777                 currentSound.attributes.push(RegExp.$1);
2778             }
2779             continue;
2780         }
2781         //セクションセパレータ少ない
2782         if(this[fix].match(/^[-_~^〜_ー ̄]{3,4}$/)){
2783             if(currentSection.value){
2784                 currentSection.duration --;//加算した継続長をキャンセル
2785                 currentSection.value.contentText=currentSound.toString();//先の有値セクションをフラッシュして
2786                 currentSection=myCollection.addSection(null);//新規のカラセクションを作る
2787                 currentSection.duration ++;//キャンセル分を後方区間に加算
2788                 currentSound=new nas.AnimationDialog(groupName,"");//サウンドを新規作成
2789             }else{
2790 //引数をサウンドオブジェクトでなくxMapElementに変更予定
2791 //                nas.new_MapElement(name,Object xMapGroup,Object Job);
2792                 currentSection=myCollection.addSection(currentSound);//新規有値セクション作成
2793 //                currentSection.value.
2794             }
2795                         continue;
2796         }
2797 //判定を全て抜けたデータは本文又はラベルラベルは上書きで更新
2798 //ラベル無しの音声オブジェクトは無しのまま保存必要に従って先行オブジェクトのラベルを引継ぐ
2799         if(currentSection.value){
2800             if(this[fix]=="|") this[fix]="ー";
2801             currentSound.bodyText+=this[fix];
2802         }else{
2803             currentSound.name=this[fix];
2804         }
2805     }
2806     this.sections=myCollection;
2807     return this.sections;
2808 }
2809 //test
2810