1 /*
  2     主にSE及びBGM等のセリフ以外のサウンドを扱うオブジェクト
  3     値にブランクが存在するので、リプレースメントをベースに作成
  4 
  5 初期化引数の(コンテント)形式は、'ラベル"注釈テクスト"'
  6 スポッティング等に使用されるトラック
  7 */
  8 nas.AnimationSound=function(myParent,myContent){
  9     this.parent = (myParent)? myParent : null     ;//xMapElementGroup or null
 10     this.contentText = (myContent)? myContent : '';//xMap上のコンテントソースを保存する 自動で再構築が行なわれるタイミングがある
 11                                                    //myContent undefined で初期化を行った場合の値は blank-cell
 12     this.name                                     ;//要素名(グループ名があればパース時に除く)
 13     this.noteText                                 ;//注釈テキスト 要素区間にマージンがあれば表示される
 14     this.source                                   ;//nas.AnimationElementSource
 15     this.comment                                  ;//コメント文字列 エレメントの注釈プロパティ-xMap編集UIのみで確認できる
 16 
 17     this.parseContent();
 18 }
 19 /*
 20 主に予約ラベルで構成されるが、シートに入力された注釈テキストがあればそれらをxMapに保存する。
 21 注釈テキストは
 22 */
 23 nas.AnimationSound.prototype.toString=function(exportForm){
 24 //return this.contentText;//動作確認用ダミー行
 25 
 26     if(exportForm == 'extend'){
 27         var resultArray=[];
 28         if(this.source)   resultArray.push('\tfile = "'    + this.source.toString(true)+'"');
 29         if(this.size)     resultArray.push('\tsize = '     + this.size.toString());
 30         if(this.offset)   resultArray.push('\toffset = '   + this.offset.toString());
 31         if(this.rotation) resultArray.push('\trotation = ' + this.rotation.toString());
 32         if(this.comment)  resultArray.push('\tcomment = '  + this.comment);
 33         return resultArray.join("\n");
 34     }else if ((arguments.length==0)||((arguments.length==1)&&(! arguments[0]))||(exportForm == 'basic')){
 35         var resultArray=[];
 36         
 37         if(this.source)   resultArray.push('"'+this.source.toString()+'"');
 38         if(this.size)     resultArray.push(this.size.toString());
 39         if(this.offset)   resultArray.push(this.offset.toString());
 40         if(this.rotation) resultArray.push(this.rotation.toString());
 41         resultArray = [resultArray.join(",")];
 42         if(this.comment) resultArray.push(this.comment);
 43         return ([this.parent.name,this.name,resultArray.join("\t")]).join('\t');
 44     }
 45 }
 46 //nas.AnimationSound.prototype.valueOf=function(){
 47 //    return nas.parseNumber(nas.normalizeStr(this.name).replace(/^[^0-9]*/,""))
 48 //valueOfの設定自体にあまり意味が無いのでやめたほうがヨサゲ 
 49 //}
 50 /** 与えられたオブジェクトとプロパティ同士を比較して 変更状態を返す
 51     引数
 52 対照する基準値(オブジェクト)
 53     戻り値
 54 変更状態コード
 55 0   変化なし    最小標準出力に対応
 56 1   標準変更    拡張標準出力に対応
 57 2   重度変更    フルダンプに対応
 58 */
 59 nas.AnimationSound.prototype.compareWith= function(targetValue){
 60     var igunoreProps    =['contentText','source'];
 61     var basicProp       =['size','offset','comment'];
 62     var extendProps     =['pegOffset',];
 63 }
 64 /** タイミングパラメータに従って指定されたフレームのキー間の補完値を返す
 65 
 66    置きかえタイムラインの中間値は前方値で代表されるので基本的に戻り値は自分自身
 67     オプションの状態によって(時間的)中間タイミングで後方値に切り替える
 68     return endValue;
 69     又はブランク状態のオブジェクトを返す
 70    return new nas.newAnimationSound("blank");
 71 */
 72 nas.AnimationSound.prototype.interpolate= function(endValue,indexCount,indexOffset,frameCount,frameOffset,props){
 73     return this;
 74 }
 75 
 76 /** Contentをパースして プロパティを設定する内部メソッド
 77 引数でcontentを与えてオブジェクト全体の値を更新することも可能
 78 引数がAnimationRepalcementであった場合は、全プロパティを継承して引き写す
 79 ただし引数と同じジョブ内のコレクションに追加を行う場合は、失敗するので要注意
 80 
 81 xMap形式のデータをパースする nas.AnimationXXX シリーズオブジェクトの共通メソッド
 82 xMapパーサから呼び出す際に共通でコールされる
 83 引数が与えられない場合は、現在の保持コンテンツを再パースする
 84 */
 85 nas.AnimationSound.prototype.parseContent = function(myContent){
 86 //    var blankRegex  = new RegExp("^[xXxX×〆00]$");//カラ判定 システム変数として分離予定
 87     var interpRegex = new RegExp("^[\-\+=○●*・a-zア-ン]$|^\[[^\]]+\]$");//中間値補間(動画記号)サイン 同上
 88     var valueRegex  = new RegExp("^[\(<]?[0-9]+[>\)]?$");//無条件有効値 同上
 89 
 90 //引数がなければ現在のコンテンツを再パース
 91     if(typeof myContent == 'undefined'){
 92         myContent = this.contentText;
 93     }else{
 94         
 95         this.contentText = myContent;
 96     }
 97 /*
 98     AnimatiopnReplacementの特殊値として
 99     contentText='blank-cell'を設ける
100     AnimationElementSource("")
101     サイズは不問  シンボルとしての「カラセル」
102 
103 */
104     if(myContent == 'blank-cell') return this;
105     var isGroup = (myContent.indexOf('[')==0)? true:false;
106 //第一形式グループ ^[\<group>\t<typeName>[\t<option-text>[\t<comment>]]\]$
107 //第二形式エントリ ^<group>\t<name>[\t<option-text>[\t<comment>]]$
108 
109     myContent = String(myContent).split('\n');
110     for ( var line = 0 ; line < myContent.length ; line++){
111 
112     if((isGroup)&&(myContent[line].indexOf('[')==0)) myContent[line] = myContent[line].slice(1,-1);//ブラケット削除
113 
114         if(myContent[line].match(/^\t(\S+)\s*=\s*(.+)\s*$/)){
115             //第二形式(タブ開始)でプロパティ別のデータ更新を行う
116             this.extended=true;
117 
118             var myProp=RegExp.$1;var valueArray=csvSimple.parse(RegExp.$2)[0];
119 
120             switch(myProp){
121             case "file":
122                 this.file = new nas.AnimationElementSource(valueArray[0]);
123             break;
124             case "resolution":
125                 this.resolution= new nas.Resolution(valueArray.join(','));
126             break;
127             case "resolution.X":
128                 this.resolution.x = new nas.UnitResolution(valueArray[0],this.resolution.type);
129             break;
130             case "resolution.Y":
131                 this.resolution.y = new nas.UnitResolution(valueArray[0],this.resolution.type);
132             break;
133             case "size":
134                 this.size = (valueArray.length<3)?
135                     new nas.Size(valueArray[0],valueArray[1]):new nas.Size(valueArray[0],valueArray[1],valueArray[2]);
136             break;
137             case "size.X":
138                 this.size.x = new nas.UnitValue(valueArray[0]);
139             break;
140             case "size.Y":
141                 this.size.y = new nas.UnitValue(valueArray[0]);
142             break;
143             case "offset":
144                 this.offset = (valueArray.length<3)?
145                     new nas.Offset(valueArray[0],valueArray[1]):new nas.Offset(valueArray[0],valueArray[1],valueArray[2]);
146             break;
147             case "offset.X":
148                 this.offset.x = new nas.UnitValue(valueArray[0]);
149             break;
150             case "offset.Y":
151                 this.offset.y = new nas.UnitValue(valueArray[0]);
152             break;
153             case "offset.R":
154                 this.offset.r = new nas.UnitAngle(valueArray[0]);
155             break;
156             case "pegOffset":
157                 this.offset = (valueArray.length<3)?
158                     new nas.Offset(valueArray[0],valueArray[1]):new nas.Offset(valueArray[0],valueArray[1],valueArray[2]);
159             break;
160             case "pegOffset.X":
161                 this.offset.x=new nas.UnitValue(valueArray[0]);
162             break;
163             case "pegOffset.Y":
164                 this.offset.y=new nas.UnitValue(valueArray[0]);
165             break;
166             case "pegOffset.R":
167                 this.offset.r=new nas.UnitAngle(valueArray[0]);
168             break;
169            default:
170                 this[myProp]=valueArray[0];
171             }
172         } else if(myContent[line].match(/^(\S+)\t?(\S+)\t?([^\t]+)?\t?(.*)$/)){
173         // 第一形式の再パース
174 console.log(myContent[line]);
175             var myGroup=RegExp.$1; //グループの再パースは行われない
176             var myName =RegExp.$2;
177             var myComment=RegExp.$4;
178             var valueArray=nas.parseDataChank(RegExp.$3);
179             var numeProps =[["size","x"],["size","y"],["offset","x"],["offset","y"]];
180 
181 console.log(myComment);
182 console.log(valueArray);
183 console.log(this);
184 /*
185     フィールド文字列であった場合の判定が必要 2018 10 09
186 
187 case :this.parent == null
188 */
189             if((! (this.parent))||(myGroup == this.parent.name)){
190                 if(! isGroup) this.name = myName.replace(new RegExp('^'+myGroup+'\-'),"");
191                 var numCount=0;
192                 for(var vix=0;vix<valueArray.length;vix++){
193                     switch(valueArray[vix].type){
194                     case "numeric":
195                     case "unitValue":
196                         if(numCount<numeProps.length){
197                             if(! this[numeProps[numCount][0]]){
198                                 this[numeProps[numCount][0]] = ([numeProps[numCount][0]]=='size')? new nas.Size():new nas.Offset();
199                             }
200                             this[numeProps[numCount][0]][numeProps[numCount][1]] = new nas.UnitValue(valueArray[vix].value);
201                             numCount++;
202                         }
203                     break;
204                     case "unitAngle":
205                         if(! this.offset) this.offset = new nas.Offset();
206                         this.offset.r==new nas.UnitAngle(valueArray[vix].value);            
207                     break;
208                     case "unitResolution":
209                         this.resolution=new nas.Resolution(valueArray[vix].value);            
210                     break;
211                     case "source":
212                         this.source=new nas.AnimationElementSource(valueArray[vix].value);            
213                     break;
214                     default:
215                         continue;
216                     }
217                 }
218                 if(myComment) this.comment = myComment;
219             }
220         }
221 
222     }
223     return this;    
224 }
225 /** 指定フレーム数に内容を展開して配列で返す
226 引数 :cellCount
227 戻値 :配列 + offset
228 */
229 nas.AnimationSound.prototype.getStream=function(cellCounts){
230     var myResult=new Array(cellCounts);
231     myResult[0]=(this.name)? this.name:"";
232     if (myResult[0].match(/blank(-cell)?/)) myResult[0]="X";
233     return myResult;
234 }
235 /**
236     置きかえタイムライントラックをパースしてセクションコレクションを返す
237     セクションの値を各トラックごとの値オブジェクトからxMapを介したxMapエレメントに変更する
238 
239     パース時にセクションの値判定を行う
240     ・無効記述
241     ・有効記述 値あり(xMap既存エレメント)・なし(新規エレメント)
242     
243  タイムライントラックをパースする際に統一手順としてトラックに対応するxMapエレメントグループの有無を確認する。
244 現行Jobにトラックと同名のエレメントグループが、存在しなかった場合(Stageには存在する可能性あり)は、新規にグループを作成してエントリすること。
245 この処理は、トラックパースの前段階で共通で行うことにする
246 
247 確認手段は xMap.getElementByName(グループ名)を使用
248 //XpsTimelineTrack.parseTimelineTrack() メソッドに置く
249 
250 
251 中間値補間区間の空セルに対応するために全体のブランク処理をサブセクションコレクションに置く
252 置きかえタイムラインのみの処置
253 カラ状態のみを扱うsctionCollectionを併置してセットで扱うので注意
254 各セクションのvalueは on/off(true/false)のみでオブジェクトは使用されない エレメントへのリンクも無い
255 一つのトラックをパースして二つのセクションコレクションを得る
256 値側のコレクションは、従来のカラを含むことができるが、このパーサが書き出すデータ上は従来型のカラが含まれることは無い
257 カラ区間の値は先行区間の値となる
258 カラセル区間コレクションは2つの状態しか持ち得ないので、サブセクションは発生しない
259 
260  */
261 _parseReplacementTrack=function(){
262 //    var blankRegex  = new RegExp("^[xXxX×〆00]$");//カラ判定 システム変数として分離予定
263     var interpRegex = new RegExp("^[\-\+=○◯●*・a-zア-ン]$|^\[[^\]]+\]$");//中間値補間(動画記号)サイン 同上
264     var valueRegex  = new RegExp("^[\(<]?[0-9]+[>\)]?$");//無条件有効値 同上
265     //自分自身(トラック)を親として新規セクションコレクションを作成
266     var myCollectionBlank = new XpsTimelineSectionCollection(this);//ブランクベースコレクション
267     var myCollection      = new XpsTimelineSectionCollection(this);//ベースコレクション
268 
269     var appearance    = new nas.AnimationAppearance(null,'on');
270     var disAppearance = new nas.AnimationAppearance(null,'off');
271 
272     //継続時間0で値未定初期セクションを作成
273     //値を持たないセクションをブランク値のオブジェクトとするか?
274     var currentSection=myCollection.addSection(null);
275     
276     var currentSubSection = null;
277     var currentValue      = this.getDefaultValue();
278     if(! currentValue) currentValue = new nas.AnimationSound('system','blank-cell');
279 //console.log(currentValue)
280     var isInterp = false;
281     var isBlank  = ((! currentValue)||(currentValue.contentText == "blank-cell"))? true:false ;//デフォルトのブランク状態を取得
282 
283 var currentSectionBlank=(isBlank)? myCollectionBlank.addSection(disAppearance):myCollectionBlank.addSection(appearance);
284 
285     var valueDetect = false;
286 /**
287     タイムライントラックのデフォルト値は、以下の手続きで取得
288     タイムラインラベルが指定するグループがあらかじめ存在する場合は、そのグループオブジェクトが保持する値
289     存在しない場合は、新規にグループを作成する。その際にトラックの種別ごとのValueオブジェクトを初期値として登録するのでその値を使用
290     XpsTimelineTrack.getDefeultValue()側で調整
291     Replacementの場合基本はブランクだが、必ずしもブランクとは限らないので要注意
292     トラック上で明示的なブランクが指定された場合は、値にfalse/null/"blank"を与える。
293 */
294     for (var fix=0;fix<this.length;fix++){
295         var currentCell=Xps.sliceReplacementLabel(new String(this[fix]));//記述をラベルとエントリに分解 
296         if( currentCell.length == 1 ){ currentCell.push(this.id); }//エントリにグループ名が含まれないようならばトラックのラベルで補う
297         // ここでデータの形式は [name,groupName] となる
298         currentSection.duration ++; //
299         currentSectionBlank.duration ++;     //セクション長加算
300         if(currentSubSection) currentSubSection.duration ++ ;
301         //未記入データ これが一番多いので最初に処理しておく(処理高速化のため)
302         if(currentCell[0].match(/^([\||;]|\s+)$/)||currentCell.length==0) continue;
303         /*      ブランク判定
304             値処理に先立ってブランク関連の処理をすべて終了する
305             ブランク状態切り替え判定 カレントを切り替えて新規セクションを積む
306         */
307         var valueDetect   = false;//値検出状態初期化
308         var blankDetect   = (String(currentCell[0]).match(nas.CellDescription.blankRegex))?  true:false;//値からブランク状態を検出
309         var interpDetect  = (String(currentCell[0]).match(nas.CellDescription.interpRegex))? true:false;//括弧つきの補間サインも同時検出へ
310 //console.log(fix+":"+this[fix]+" interp:"+interpDetect + "  blank: " + blankDetect);
311         //ブランク処理判定
312         if(blankDetect){
313                 if(! isBlank){
314                     if(fix==0){
315                         currentSectionBlank.value=disAppearance;
316                         currentSection.value = new nas.AnimationSound('system','blank-cell');// *Blank-set
317                     }else{
318                         currentSectionBlank.duration --;
319                         currentSectionBlank=myCollectionBlank.addSection(disAppearance);
320                         currentSectionBlank.duration ++;
321                         currentSection.duration --;// *
322                         currentSection=myCollection.addSection(this.pushEntry('blank-cell','system'));// *
323                         currentSection.duration ++;// *
324                         if(currentSubSection){
325                             currentSubSection.duration --;
326                             currentSubSection = null;
327                         }
328                     }
329                     isBlank=true;
330                 }
331                 continue;
332         }
333 //         else if(fix==0){    currentSectionBlank.value=appearance; }
334         //中間値補間サインを検出したら中間値処理モード
335         //既定値以外の補間サイン検出が必要>> 規定値のみを補完サインと定義する 他の記述はコメントとして利用
336         if(interpDetect){
337               if( isBlank ){
338                  if(fix==0){
339                     currentSectionBlank.value=appearance;
340                  }else{
341                     currentSectionBlank.duration --;
342                     currentSectionBlank=myCollectionBlank.addSection(appearance);
343                     currentSectionBlank.duration ++;
344                  }
345                  isBlank = false;
346               }
347               if(! isInterp ){
348                 //中間値補間区間開始 カレントセクションを切り替え サブセクションを登録
349                 isInterp = true;
350                 if(fix==0){
351                     currentSection.value="interpolation";
352                 }else{
353                     currentSection.duration --;
354                     currentSection=myCollection.addSection("interpolation");
355                     currentSection.duration ++;
356                 }
357                 currentSubSection = currentSection.subSections.addSection(new nas.AnimationSound(null,currentCell.join("-")));
358                 currentSubSection.duration ++;
359                 //新規中間値補間セクションを立てる 以降は、モードを抜けるまでカレント固定
360               }else{
361                 currentSubSection.duration --;
362                 currentSubSection = currentSection.subSections.addSection(new nas.AnimationSound(null,currentCell.join("-")));
363                 currentSubSection.duration ++;
364                 //中間値補間モード内ではサブセクションを登録
365               }
366               continue;
367         }
368         //区間値を処理
369 /**
370     既存エントリがない場合、エントリ文字列が条件を満たせば新規エントリとしてxMapにグループとエントリを登録して使用する
371     それ以外は、無効エントリとなる
372 */
373 //console.log(currentCell.join("-"));
374         var currentElement = this.xParent.parentXps.xMap.getElementByName(currentCell.join("-"));
375         if(currentElement) {
376 //console.log("value detcted in xMap:");
377             valueDetect=true;
378         }else{
379 //console.log("value not detcted in xMap: push Entry "+currentCell.reverse().join("-"));
380             if(String(currentCell[0]).match(valueRegex)){
381                 valueDetect = true;
382                 currentElement=this.pushEntry(currentCell[0],currentCell[1]);
383             }
384         }
385 //console.log(valueDetect);
386 //console.log(currentElement);
387         if(valueDetect){
388                 currentValue = currentElement.content;
389             if(isBlank){
390                 if(fix==0){
391                     currentSectionBlank.value=appearance;
392                 }else{
393                     currentSectionBlank.duration --;
394                     currentSectionBlank=myCollectionBlank.addSection(appearance);
395                     currentSectionBlank.duration ++;
396                 }
397                 isBlank = false;
398             }
399             if(isInterp){
400                 isInterp = false;
401                 currentSubSection.duration --;
402                 currentSubSection = null;
403             }
404             if(fix==0){
405                 currentSection.value = currentValue;
406             }else{
407                 currentSection.duration --;
408                 currentSection = myCollection.addSection(currentValue);
409                 currentSection.duration ++;
410             }
411         }
412         continue
413     }
414 //console.log(myCollection)
415     this.sections       = myCollection;
416     this.sectionsBlank  = myCollectionBlank;
417 //console.log("sections-length:"+myCollection.length +":blank:"+myCollectionBlank.length);
418     return this.sections;//ブランク情報の返し方を考えたほうが良いかも
419 }
420 
421 /*test
422 
423 XpsTimelineTrack.prototype.parseReplacementTrack=_parseReplacementTrack;
424 XPS.xpsTracks[2].parseReplacementTrack();
425 XPS.xpsTracks[2].sections[1].toString();
426 
427 XpsTimelineTrack.prototype.parseReplacementTrack=_parseReplacementTrack;
428 
429 XpsTimelineTrack.prototype.parseCameraWorkTrack=_parseCameraworkTrack;
430 
431 XpsTimelineTrack.prototype.parseCompositeTrack=_parseCompositeTrack;//コンポジット
432 
433 //XpsTimelineTrack.prototype.parseTrack=_parseTrack;
434 //XpsTimelineTrack.prototype.parseTrack=_parseTrack;
435 */