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> 125 例 126 "./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 136 例 137 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 1439 例 1440 [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 2326 例 2327 ★ A,B,C <Slide> ↑ [1]→[2]→[3] 2328 ☆ クロコマ 2329 ※ pan [A]-[B] 2330 * follow 2331 ○ 2332 ◯ 2333 ● 2334 ■ 黒コマ 2335 □ 白コマ 2336 << 2337 < 2338 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