|
|
ちょっと早いクリスマスプレゼントです。
標準の2Dパステキストは曲線上に文字を配置出来ないので,スクリプトを書いてみました。
アクティブレイヤの文字とパス図形を選択して実行します。
パス図形は、多角形に変換できる図形なら何でも構いません。(渦巻き図形もグループ解除す
れば可能です。)
VW11ではDoMenuTextByNameが正常に動作しないので、113〜116行をコメントアウトして、117
行を有効にしてください。
procedure AlignTextOnCurve;
{ パス図形に沿って、文字を均等配列にする(VW8.5〜10.5) }
{ VW11では、113〜116行をコメントアウトして、117行を有効にする }
{ アクティブレイヤの文字とパス図形を選択して実行 }
{$ DEBUG}
const
_MaxIndex = 254;
_LineObj = 2;
_RectObj = 3;
_OvalObj = 4;
_PolyObj = 5;
_ArcObj = 6;
_RRectObj = 13;
_CurveObj = 21;
_TextObj = 10;
_LF = Chr(13);
_
var
_hT, hP, hG_:handle;
_str_:string;
_ch_num_:integer;
_txt_color_:integer;
_txt_vAlign_:integer;
_ch_numByte, ch_font, ch_size, ch_style_:array[0..MaxIndex]
of integer;
_ch_dist, ch_wd, ch_x, ch_y, ch_ang_:array[0..MaxIndex] of
real;
_ch_chars_:array[0..MaxIndex, 1..2] of char;
_ch_isSpace_:array[0..MaxIndex] of boolean;
_ch_hnd_:array[0..MaxIndex] of handle;
_pathLen_:real;
_spc_:real;
_
function Closed(hPoly: handle): boolean;
{多角形が閉じていればTRUEを返します。}
var
_fPat:integer;
begin
_fPat:= GetFPat(hPoly);
_SetFPat(hPoly, 0);
_if HArea(hPoly) = 0 then
__Closed:= false
_else
__Closed:= true;
_SetFPat(hPoly, fPat);
end; {Closed}
function GetNumByte(c:char):integer;
{ 文字のバイト数を返します。 }
var
_result_:integer;
begin
_case Ord(c) of
__129..159, 224..252: result:= 2;
__otherwise result:= 1;
_end;{case}_
_GetNumByte:= result;
end;{GetNumByte}
function GetColorIndex(h:handle):integer;
{ カラー番号を返します。 }
var
_result_:integer;
_r, g, b_:real;
begin
_GetPenFore(h, r, g, b);
_RGBToColorIndex(r, g, b, result);
_GetColorIndex:= result;
end;{GetColorIndex}
procedure GetHandles(var hText, hPath:handle);
{ 図形ハンドルを取得 }
var
_h_:handle;
_x1, y1, x2, y2_:real;
begin
_h:= FSActLayer;
_while (h <> nil) do begin
__if h <> nil then begin
___case GetType(h) of
____LineObj..ArcObj, RRectObj, CurveObj:
_____hPath:= h;
____TextObj:
_____hText:= h;
___end;{case}
___h:= NextSObj(h);
__end;{if}
_end;{while}
end;{GetHandles}
procedure Convert_Curve2Poly(var h:handle);
{ パス図形を多角形に変換 }
var
_x1, y1, x2, y2_:real;
_x, y_:real;
_h0_:handle;
_i_:integer;
_arcDiv_:integer;
begin
_DSelectAll;
_if GetType(h) = LineObj then begin
__GetSegPt1(h, x1, y1);
__GetSegPt2(h, x2, y2);
__OpenPoly;
__Poly(x1, y1, (x1+x2)/2, (y1+y2)/2, x2, y2);
__h:= LNewObj;
_end{if}
_else begin
__arcDiv:= GetPrefInt(55);
__if GetType(h) = ArcObj then
___SetPrefInt(55, 512)
__else
___SetPrefInt(55, 128);
__SetSelect(h);_{VW8.5〜10.5}
__Duplicate(0, 0);_{VW8.5〜10.5}
__h:= LSActLayer;_{VW8.5〜10.5}
__DoMenuTextByName('Convert to Polygons', 0);_{VW8.5〜10.5}
{__h:= MakePolygon(h);_}{ VW11 }
__SetPrefInt(55, arcDiv);
_end;{else}
_if Closed(h) then begin
__h0:= h;
__BeginPoly;
__for i:= 1 to GetVertNum(h) do begin
___GetPolyPt(h, i, x, y);
___AddPoint(x, y);
__end;{for}
__GetPolyPt(h, 1, x, y);
__AddPoint(x, y);
__EndPoly;
__h:= LNewObj;
__DelObject(h0)
_end;
end;{Convert_Curve2Poly}
procedure GetTextInformation;
{ 文字情報を取得 }
var
_i, j, n_:integer;
_c_:char;
begin
_txt_color:= GetColorIndex(hT);
_txt_vAlign:= GetTextVerticalAlign(hT);
_n:= GetTextLength(hT);
_i:= 0;
_j:= 0;
_str:= GetText(hT);
_while (i < n) & (j <= MaxIndex) do begin
__c:= copy(str, i+1, 1);
__ch_chars[j, 1]:= c;
__ch_font[j]:= GetTextFont(hT, i);
__ch_size[j]:= GetTextSize(hT, i);
__ch_style[j]:= GetTextStyle(hT, i);
__ch_numByte[j]:= GetNumByte(c);
__ch_chars[j, 1]:= copy(str, i+1, 1);
__if ch_numByte[j] = 2 then
___ch_chars[j, 2]:= copy(str, i+2, 1);
__c:= ch_chars[j, 1];
__if c = ' ' then begin
___ch_chars[j, 1]:= '.';{
WinのVW10で空白の幅がゼロになる為(Macは未確認) }
___ch_isSpace[j]:= true;
__end
__else begin
___ch_isSpace[j]:= false;
__end;{if}
__i:= i + ch_numByte[j];
__j:= j + 1;
_end;{while}
_ClrMessage;
_if (MaxIndex < j) then
__Message(MaxIndex+1, '文字以上は無視されます。');
_ch_num:= j;
end;{GetTextInformation}
procedure CreateChars;
{ 文字を生成 }
var
_x, y_:real;
_i_:integer;
begin
_TextJust(2);_{Center}
_TextVerticalAlign(txt_vAlign);
_PenFore(txt_color);
_HCenter(hP, x, y);
_for i:= 0 to ch_num-1 do begin
__TextFont(ch_font[i]);
__Textsize(ch_size[i]);
__TextOrigin(x, y);
__if ch_numByte[i] = 2 then
___CreateText(Concat(ch_chars[i, 1], ch_chars[i,
2]))
__else {ch_numByte[i] = 1}
___CreateText(ch_chars[i, 1]);
__ch_hnd[i]:= LNewObj;
__SetTextStyle(ch_hnd[i], 0, ch_numByte[i], 0);
__SetTextStyle(ch_hnd[i], 0, ch_numByte[i],
ch_style[i]);
_end;{for}
end;{CreateChars}
function GetSpaceDistance(numText:integer; lng:real):real;
{ 文字間距離を取得 }
var
_result_:real;
_wd_:real;
_numSpc_:integer;
_i_:integer;
_x1, y1, x2, y2_:real;
begin
_numSpc:= 0;
_wd:= 0;
_for i:= 0 to numText-1 do begin
__GetBBox(ch_hnd[i], x1, y1, x2, y2);
__ch_wd[i]:= x2 - x1;
__if (0 < i) & (i < (lng-1)) then begin
___numSpc:= numSpc + 2*ch_numByte[i];
__end
__else begin
___numSpc:= numSpc + ch_numByte[i];
__end;
__wd:= wd + x2 - x1;
_end;{for}
_GetSpaceDistance:=(pathLen - wd) / numSpc;
end;{GetSpaceDistance}
procedure SetDistOnCurve(num:integer; lng0, spc:real);
{ 始点から文字基点までの距離を計算 }
var
_i_:integer;
begin
_ch_dist[0]:= ch_wd[0] / 2;
_for i:= 1 to num-1 do begin
__ch_dist[i]:= ch_dist[i-1] + (ch_wd[i-1] +
ch_wd[i]) / 2 + spc * (ch_numByte[i-1] +
ch_numByte[i]);
_end;{for}
end;{SetDistOnCurve}
procedure SetTextOrientationOnCurve(num:integer);
{ 多角形上の文字基点座標と角度を計算 }
var
_i, j, n_:integer;
_d, dd_:real;
_x0, y0, x, y_:real;
_v_:vector;
begin
_dd:= 0;
_j:= 1;
_n:= GetVertNum(hP);
_GetPolyPt(hP, j, x0, y0);
_for i:= 0 to num-1 do begin
__while (dd < ch_dist[i]) & (j < n) do begin
___j:= j + 1;
___GetPolyPt(hP, j, x, y);
___d:= Distance(x0, y0, x, y);
___dd:= dd + d;
___v[1]:= x - x0;
___v[2]:= y - y0;
___x0:= x; y0:= y;
__end;{while}
__ch_ang[i]:= Vec2Ang(v);
__ch_x[i]:= x - v[1] * (dd-ch_dist[i]) /
d;
__ch_y[i]:= y - v[2] * (dd-ch_dist[i]) /
d;
_{_ReDraw;_}
_end;{for}
end;{SetTextOrientationOnCurve}
procedure ArrangeChars(num:integer);
{ 文字を配置 }
var
_i_:integer;
begin
_for i:= 0 to num-1 do begin
__SetTextOrientation(ch_hnd[i], ch_x[i],
ch_y[i], ch_ang[i], false);
_end;{for}
end;{ArrangeChars}
procedure ResetSpace(num:integer);
{ 「.」を空白に戻す }
var
_i_:integer;
begin
_for i:= 0 to num-1 do begin
__if ch_isSpace[i] then
___SetText(ch_hnd[i], ' ');
_end;
end;{ResetSpace}
begin{main}
_PushAttrs;
_GetHandles(hT, hP);
_if (hP = nil) | (hT = nil) then begin
__AlrtDialog(Concat('アクティブレイヤで、', LF,
___'文字と曲線を選択して実行してください。'));
_end{if}
_else begin
__GetTextInformation;
__Convert_Curve2Poly(hP);
__BeginGroup;
___CreateChars;
__EndGroup;
__hG:= LNewObj;
__pathLen:= HPerim(hP);
__spc:= GetSpaceDistance(ch_num, pathLen);
__SetDistOnCurve(ch_num, pathLen, spc);
__SetTextOrientationOnCurve(ch_num);
__ArrangeChars(ch_num);
__ResetSpace(ch_num);
__DelObject(hP);
__ResetBBox(hG);
_end;{if}
_PopAttrs;
end;{main}
Run(AlignTextOnCurve);
文字を各々の文字基点で回転します。
「文字の角度を設定するスクリプト」では対応できないときに使います。
絶対角度指定と相対角度(回転角)指定の違い、という意味ではなく、
角度が異なる文字を同じだけ回転させるような場合です。
procedure RotText;
{ 文字を回転する。 }
{ アクティブレイヤの文字(グループでも可)を選択して、実行する。
}
const
_TextObj = 10;
_GroupObj = 11;
var
_numText_:integer;
_angRot_:real;
_countMode_:boolean;
_
procedure DoText(h:handle);
var
_x, y, a_:real;
_flip_:boolean;
begin
_if countMode then begin
__numText:= numText + 1;
_end{if}
_else begin
__GetTextOrientation(h, x, y, a, flip);
__SetTextOrientation(h, x, y, angRot + a, flip);
_end;{else}
end;{DoText}
procedure DoInGroup(hP:handle);
var
_h_:handle;
begin
_h:= FInGroup(hP);
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextObj(h);
_end;
end;{DoInGroup}
procedure DoInLayer;
var
_h_:handle;
begin
_h:= FSActLayer;
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextSObj(h);
_end;
end;{DoInLayer}
begin
_countMode:= true;
_numText:= 0;
_DoInLayer;
__
_if numText = 0 then begin
__AlrtDialog('文字を選択してください。');
_end{if}
_else begin
__angRot:= AngDialog('文字の回転角度(dA) = ', '0.00°');
__if not DidCancel then begin
___countMode:= false;
___DoInLayer;
__end;{if}
_end;{else}
end;
Run(RotText);
>文字属性(スタイル)が一文字置きにしか設定されません...
スタイルを設定する前にリセットする必要があるようです。
SetTextStyle(hT, st, lng, GetTextStyle(hC, 0));
の前に、
SetTextStyle(hT, st, lng, 0);
を入れれば良いようです。
文字属性(スタイル)が一文字置きにしか設定されません...残念!
文字の角度を設定するスクリプトを、少し直しただけです。
procedure MoveTextVertical;
{ 文字を高さ方向に移動する。 }
{ アクティブレイヤの文字(グループでも可)を選択して、実行する。
}
const
_TextObj = 10;
_GroupObj = 11;
var
_numText_:integer;
_dH_:real;
_countMode_:boolean;
_
procedure DoText(h:handle);
var
_x, y, a_:real;
_v_:vector;
_flip_:boolean;
begin
_if countMode then begin
__numText:= numText + 1;
_end{if}
_else begin
__GetTextOrientation(h, x, y, a, flip);
__v:= Ang2Vec(a+90, dH);
__x:= x + v[1]; y:= y + v[2];
__SetTextOrientation(h, x, y, a, flip);
_end;{else}
end;{DoText}
procedure DoInGroup(hP:handle);
var
_h_:handle;
begin
_h:= FInGroup(hP);
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextObj(h);
_end;
end;{DoInGroup}
procedure DoInLayer;
var
_h_:handle;
begin
_h:= FSActLayer;
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextSObj(h);
_end;
end;{DoInLayer}
begin{main}
_countMode:= true;
_numText:= 0;
_DoInLayer;
__
_if numText = 0 then begin
__AlrtDialog('文字を選択してください。');
_end{if}
_else begin
__dH:= AngDialog('文字の移動距離(dH) = ', '0.00');
__if not DidCancel then begin
___countMode:= false;
___DoInLayer;
__end;{if}
_end;{else}
end;{main}
Run(MoveTextVertical);
>与太郎さん
あっけないぐらい短時間で組み直せました。実際の仕事の中でテストしていきます。
どうもでした。
>これを10.3と10.4てな具合にしていきたいのです。
おお、間違いました...。3.3と3.4です。
一度、整数化して計算して、その後に戻せばいいんですね。そうすれば余りの計算も出
来ますね。再考してみます。
やってはいけない割り算、はゼロ除算ですが、
>10を3で割って3.3333...となりますが、
>これを10.3と10.4てな具合にしていきたいのです。
これは意味がわかりません...
3.3と3.4の間違いだったら、
1. Int(10.0/3 * 10)/10 → 3.3、余り=6.7
2. Int( 6.7/2 * 10)/10 → 3.3、余り=3.4
3. Int( 3.4/1 * 10)/10 → 3.4、余り=0
という考え方でどうでしょうか?
グループ図形の中の文字を全て連結して、一つの文字図形にしています。
procedure Group2Text;
{ 均等割付文字(グループ図形)から、文字を抽出する }
{$ DEBUG}
const
_TextObj = 10;
_GroupObj = 11;
var
_hG, hC, hT_:handle;
_x, y_:real;
_st, ed_:integer;
_s, ss_:string;
_
function GetColorIndex(h:handle):integer;
{ カラー番号を返します。 }
var
_result_:integer;
_r, g, b_:real;
begin
_GetPenFore(h, r, g, b);
_RGBToColorIndex(r, g, b, result);
_GetColorIndex:= result;
end;{GetColorIndex}
function CountText(hG:handle):integer;
{ グループ図形の中の文字図形を数える }
var
_n_:integer;
_h_:handle;
begin
_n:= 0;
_h:= FInGroup(hG);
_while h <> nil do begin
__if GetType(h) = TextObj then
___n:= n + 1;
__h:= NextObj(h);
_end;{while}
_CountText:= n;
end;{CountText}
procedure DupTextAtrrs(hT, hC:handle; st, ed:integer);
var
_lng_:integer;
begin
_lng:= ed - st + 1;
_SetTextFont(hT, st, lng, GetTextFont(hC, 0));
_SetTextSize(hT, st, lng, GetTextSize(hC, 0));
_SetTextStyle(hT, st, lng, GetTextStyle(hC, 0));
end;{DupTextAtrrs}
begin{main}
_hG:= FSActLayer;
_if (hG <> nil) & (GetType(hG) = GroupObj) & (0 <
CountText(hG)) then begin
__DSelectAll;
__ss:= '';
__st:= 0;
__hT:= nil;
__hC:= FInGroup(hG);
__while hC <> nil do begin
___if GetType(hC) = TextObj then begin
____ed:= st + GetTextLength(hC) - 1;
____s:= GetText(hC);
____if hT = nil then begin
_____ss:= s;
_____GetVCenter(x, y);
_____TextOrigin(x, y);
_____CreateText(ss);
_____hT:= LNewObj;
_____SetPenFore(hT, GetColorIndex(hC));
_____SetTextJust(hT, 2);
____end{if}
____else begin
_____ss:= Concat(ss, GetText(hC));
_____SetText(hT, ss);
____end;{else}
____DupTextAtrrs(hT, hc, st, ed);
____st:= ed + 1;
___end;{if}
___hC:= NextObj(hC);
__end;{while}
_end{if}
_else begin
__AlrtDialog('均等割付文字を選択してください。');
_end;{else}
end;{main}
Run(Group2Text);
どうしても割付けプログラムを考えたいのですが、これで避けては通れない除算なんで
すが、一番の問題の余りの処理!10を3で割って3.3333...となりますが、これを10.3と
10.4てな具合にしていきたいのです。なんか、ヒントがないですか?
構造体をやめたので、VW8.5でも動きます。
if ch_chars[j, 1] = ' ' だとVW9で落ちるので、一旦 c
に代入して、
if c = ' ' then としました。
procedure AlignText;
{ 文字を直線の長さで均等配列にする(VW8.5以降) }
{ アクティブレイヤの文字と直線を選択して実行 }
{$ DEBUG}
const
_MaxIndex = 254;
_LineObj = 2;
_TextObj = 10;
_LF = Chr(13);
_
var
_ch_numByte_:array[0..MaxIndex] of integer;
_ch_chars_:array[0..MaxIndex, 1..2] of char;
_ch_font,
_ch_size,
_ch_style_:array[0..MaxIndex] of integer;
_ch_wd_:array[0..MaxIndex] of real;
_ch_hnd_:array[0..MaxIndex] of handle;
_ch_isSpace_:array[0..MaxIndex] of boolean;
_
_txtLen_:integer;
_txtVAlign_:integer;
_txtColor_:integer;
_r, g, b_:real;
_i, j, n_:integer;
_c_:char;
_s_:string;
_h, hL, hT, hG_:handle;
_rot, lnLen_:real;
_x0, y0, x, y_:real;
_x1, y1, x2, y2_:real;
_spc, wd_:real;
_numSpc_:integer;
_
function GetNumByte(c:char):integer;
var
_result_:integer;
begin
_case Ord(c) of
__129..159, 224..252: result:= 2;
__otherwise result:= 1;
_end;{case}_
_GetNumByte:= result;
end;{GetNumByte}
begin{main}
_PushAttrs;
_{ 図形ハンドルを取得 }
_h:= FSActLayer;
_while (h <> nil) do begin
__if h <> nil then begin
___if GetType(h) = LineObj then
____hL:= h
___else if GetType(h) = TextObj then
____hT:= h;
___h:= NextSObj(h);
__end;{if}
_end;{while}
_h:= nil;
_
_DSelectAll;
_
_if (hL = nil) | (hT = nil) then begin
__AlrtDialog(Concat('アクティブレイヤで、', LF,
___'文字と直線を選択して実行してください。'));
_end{if}
_else begin
_{ 文字情報を取得 }
__GetPenFore(hT, r, g, b);
__RGBToColorIndex(r, g, b, txtColor);
__txtVAlign:= GetTextVerticalAlign(hT);
__n:= GetTextLength(hT);
__i:= 0;
__j:= 0;
__s:= GetText(hT);
__while (i < n) do begin
___c:= copy(s, i+1, 1);
___ch_chars[j, 1]:= c;
___ch_font[j]:= GetTextFont(hT, i);
___ch_size[j]:= GetTextSize(hT, i);
___ch_style[j]:= GetTextStyle(hT, i);
___ch_numByte[j]:= GetNumByte(c);
___if ch_numByte[j] = 2 then
____ch_chars[j, 2]:= copy(s, i+2, 1);
___c:= ch_chars[j, 1];
___if c = ' ' then begin{ if ch_chars[j, 1] = ' '
だとVW9で落ちる }
____ch_chars[j, 1]:= '.';{
WinのVW10で空白の幅がゼロになる為(Macは未確認) }
____ch_isSpace[j]:= true;
___end
___else begin
____ch_isSpace[i]:= false;
___end;{if}
___i:= i + ch_numByte[j];
___j:= j + 1;
__end;{while}
__txtLen:= j;
__
__{ 線情報を取得 }
__GetSegPt1(hL, x0, y0);
__GetSegPt2(hL, x, y);
__lnLen:= HLength(hL);
__rot:= HAngle(hL);
__
__{ 文字を生成 }
__TextJust(2);_{Center}
__TextVerticalAlign(txtVAlign);
__PenFore(txtColor);
__TextOrigin(x0, y0);
__BeginGroup;
__for i:= 0 to txtLen - 1 do begin
___TextFont(ch_font[i]);
___Textsize(ch_size[i]);
___if ch_numByte[i] = 2 then
____CreateText(Concat(ch_chars[i, 1], ch_chars[i,
2]))
___else {ch_numByte[i] = 1}
____CreateText(ch_chars[i, 1]);
___ch_hnd[i]:= LNewObj;
___SetTextStyle(ch_hnd[i], 0, ch_numByte[i],
ch_style[i]);
__end;{for}
__EndGroup;
__hG:= LNewObj;
__
__{ 文字間距離を取得 }
__numSpc:= 0;
__wd:= 0;
__for i:= 0 to txtLen - 1 do begin
___GetBBox(ch_hnd[i], x1, y1, x2, y2);
___if (0 < i) & (i < (txtLen-1)) then begin
____numSpc:= numSpc + 2*ch_numByte[i];
___end
___else begin
____numSpc:= numSpc + ch_numByte[i];
___end;
___ch_wd[i]:= x2 - x1;
___wd:= wd + ch_wd[i];
__end;{for}
__spc:=(lnLen - wd) / numSpc;
__
__{ 文字を再配置 }
__x:= x0 + ch_wd[0]/2;
__SetTextOrientation(ch_hnd[0], x, y0, 0, false);
__for i:= 1 to txtLen - 1 do begin___
___x:= x + spc * (ch_numByte[i-1] + ch_numByte[i])
+ (ch_wd[i-1]+ch_wd[i])/2;
___SetTextOrientation(ch_hnd[i], x, y0, 0, false);
__end;{for}
__
__{ 文字を回転 }
__HRotate(hG, x0, y0, rot);
__
__{ 「.」を空白に戻す }
__for i:= 0 to txtLen - 1 do begin
___if ch_isSpace[i] then
____SetText(ch_hnd[i], ' ');
__end;
_end;{if}
_PopAttrs;
end;{main}
Run(AlignText);
文字を均等配列にするスクリプトと合わせて使えば、Macでも縦書きが出来ます。
procedure SetTextRot;
{ 文字の回転角を設定する。 }
{ アクティブレイヤの文字(グループでも可)を選択して、実行する。
}
const
_TextObj = 10;
_GroupObj = 11;
var
_numText_:integer;
_angText_:real;
_countMode_:boolean;
_
procedure DoText(h:handle);
var
_x, y, a_:real;
_flip_:boolean;
begin
_if countMode then begin
__numText:= numText + 1;
_end{if}
_else begin
__GetTextOrientation(h, x, y, a, flip);
__SetTextOrientation(h, x, y, angText, flip);
_end;{else}
end;{DoText}
procedure DoInGroup(hP:handle);
var
_h_:handle;
begin
_h:= FInGroup(hP);
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextObj(h);
_end;
end;{DoInGroup}
procedure DoInLayer;
var
_h_:handle;
begin
_h:= FSActLayer;
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextSObj(h);
_end;
end;{DoInLayer}
begin
_countMode:= true;
_numText:= 0;
_DoInLayer;
__
_if numText = 0 then begin
__AlrtDialog('文字を選択してください。');
_end{if}
_else begin
__angText:= AngDialog('文字の角度(A) = ', '0.00°');
__if not DidCancel then begin
___countMode:= false;
___DoInLayer;
__end;{if}
_end;{else}
end;
Run(SetTextRot);
>与太郎さん
あらら、本当ですね、スクリプト終了後には文字化けこそしませんが、テキストツールで
キャレットを入れた途端に文字化けするようです。
厳密には文字属性が変更されている位置の前や途中に1Byte文字を奇数個入れると発生する
ようですね。
しかし、文字属性を残したまま SetText
を迂回してコーディングするのは現実的でない
ように思います。
他の開発ツールで同様の現象が発生した場合でも、不可能ではないですが、それでもあま
りやりたくない修正ですね
>与太郎さん
やはり、文字はやっかいですね。通りでフォント等の指定の出来ないエディタがある訳
ですね、無理もない...。
>陰陽師さん
カスタマイズしていると見えない壁が存在していますね...。
なかなか情報が出てこないし、少ない情報も英語だし...。
>陰陽師さん
SetTextで文字列を変えた時、文字属性が全部同じなら問題ないですが、
文字ごとに属性を変えてる場合、文字の挿入や削除で、文字と属性の関係がずれてしまいます。
2バイト文字が化けることもあります。
例をあげると、全部2バイト文字で、途中で属性が変化している状態で、「Text編集ダイアログ」
で先頭に1バイト文字を挿入すると、属性が2バイト文字の前半と後半で変わってしまい、その
位置の文字は化けてしまいます。属性が違うので、1バイト目と2バイト目が別の文字と認識さ
れるのが原因です。
これは、VW標準の「文字検索/置換」コマンドでも起こります。
>石男さん
僕は Win VW10 ですが、縦スクロール○ 横スクロール× タブ入力×
です。
スクロールについてはバグはバグでも TextEditBox
コンポーネントのプロパティの設定
忘れでしょうね...ここいら辺はユーザーが設定できるというのが本来の姿ですが...
何でもかんでもパラメータで設定というのも無理があります。
そろそろVector Script の言語仕様もObject化の時期にきているのでは?
と思うのですが...
でないと近い将来、他のCADに遅れをとることになるでしょう。
そしてSDKもいいですが、いっそのことVWがOLE対応になれば他の言語からでもVector
Scriptを
使うことができ、MacのToolBox やWinのAPIも利用できるんです(^-^)
>どうもです、CreateEditTextBoxにはスクロール機能がついているんですが、VW11の
>Macではこのスクロールが出てきません。また、これもMac
OS10.3がらみのバグかもし
>れません。それとTab入力は出来ない模様です、これは仕様かな。
>石男さん
おはようございます、昨日はありがとうございました。
他の言語を長い間使っていて、久しぶりにVector
Scriptoに触れると非常に窮屈に感じます。
でも反対に窮屈だからこそ、何とかしょうと工夫が生まれ、皆はまって行くのかも知れませんネ。(^o^)
それとText編集ダイアログのコードは、下のままでは、コマンド実行の度にセレクション
ポインタに制御が戻るので連続して編集するのに不便です。
最終行から 4行目の SetTool(-128);
を2行上に上げて下記のようにして下さい。
Warning(' 文字列が大きすぎます!');
SetTool(-128);
end;
SetLayerOptions(Option);
end;
Run(TextEdit);
>陰陽師さん
どうもです、CreateEditTextBoxにはスクロール機能がついているんですが、VW11の
Macではこのスクロールが出てきません。また、これもMac
OS10.3がらみのバグかもし
れません。それとTab入力は出来ない模様です、これは仕様かな。
>与太郎さん
>GetPolylineVertex(h, i, x, y, tp, R);
そう、これを言ってました。頂点タイプが円弧なら円弧の半径を取れるみたいな感じ
だったので試したのですが、0しか返ってきません。SDKにも似たものがあるんですが
これは確認出来ていません...。
こんばんわ陰陽師です。
石男さんに モダンダイアログの CreateEditTextBox( )
の使い方をご教授頂きました。
ありがとうございました。
VectorWorks
のテキストツールは配置済みの文字列を編集する際、カーソルが狙った位置
に入らずいらいらします。
下のScriptは、配置済みの文字列をクリックして編集ダイアログに読込み同じ縮尺なら、
異なるレイヤへもジャンプして編集することができます。
皆さんにも、お使い頂ければ幸いです。
Procedure TextEdit;
const
MaxLen = 32000;
var
TextLen,Option: Integer;
ObjH: Handle;
PickedText,TextObj: DynArray[] of Char;
Result: Real;
IsText,NilHandle: Boolean;
procedure GetPickedText;
var
x,y: Real;
begin
GetPt(x,y);
ObjH := PickObject(x,y);
if ObjH<>Nil then
begin
NilHandle := False;
if GetType(ObjH) = 10 then
begin
IsText := True;
PickedText := GetText(ObjH);
TextLen := Len(PickedText);
end else
IsText := False;
end else
NilHandle := True;
end;
procedure EditDilg;
const
WChara = 60;
HChara = 15;
TextBoxID = 3;
var
DialogID: LongInt;
DlgJust: Boolean;
procedure DlgCallback(var Item,Value: Longint);
begin
Case Item of
SetupDialogC: SetField(TextBoxID,PickedText);
1: TextObj := GetField(TextBoxID);
end;
end;
begin
DialogID := CreateLayout(' テキスト 編集',False,'O K','Cancel');
CreateEditTextBox(DialogID,TextBoxID,'',WChara,HChara);
SetFirstLayoutItem(DialogID,TextBoxID);
DlgJust:=VerifyLayout(DialogID);
if DlgJust then
Result := RunLayoutDialog(DialogID,DlgCallback);
end;
procedure Warning(S: String);
begin
SysBeep;
AlrtDialog(Concat(Chr(32),Chr(10),Chr(32),Chr(10),S));
end;
begin
Option := GetLayerOptions;
SetLayerOptions(5);
GetPickedText;
if IsText & (NilHandle=False) & (TextLen<=MaxLen) then
begin
EditDilg;
if Result = 1 then
begin
SetText(ObjH,TextObj);
ReDrawAll;
end;
end else
begin
if (IsText=False) & (NilHandle=False) then
Warning(' 文字列を指示してください!');
if (NilHandle=False)&(TextLen>MaxLen) then
Warning(' 文字列が大きすぎます!');
end;
SetTool(-128);
SetLayerOptions(Option);
end;
Run(TextEdit);
石男さん、
>本日スクリプト三昧です...。
各所で大活躍ですね。
>曲線の円弧情報もとれない...。
GetPolylineVertex(h, i, x, y, tp,
R);で返ってくるRは設定値で、実際にその半径か
どうか判りません(これはバグではないから、新しい別の関数でないと無理でしょう。)
データパレットの「フィレット設定」では正しい半径が出るんですから、なにか方法が
あるんでしょうけど...
曲線を線分に分解して、円弧のハンドルを取って出来ないかなあ。
図面承認貰えず、本日スクリプト三昧です...。いいのか悪いのか?
>VS関数にないSKD関数を、全部PIL化してもらえたら有難いのですが...
はい、確かにそうです。その前に、古くからある関数で引数のおかしいやつを直して
欲しいです。曲線の円弧情報もとれない...。
>めんどくさいですね。
かなり面倒です...。
石男さん、ありがとうございます。
勉強不足でした。
>PlugInLibraryRoutines:HScale2D();
VW10のデモ版には入ってないので、VW10.5からで間違いないようです。
小出しにせずに、VS関数にないSKD関数を、全部PIL化してもらえたら有難いのですが...
>四角形、多角形、曲線で図面を書いてGetBBoxで最小の縦横寸法をレコードに書き出します
曲線でもなんでも計算前に多角形に変換すればいいんでしょうけど、
多角形の各辺を基準にして(辺の回数だけ)回転しないと、最小高さは得られませんね。
もしも形状が凹だったら、基準線の下に頂点があるかどうかも調べて、その点と基準線の一端を結
んだ線を基準にして多角形を回転させて...
めんどくさいですね。
「文字を均等配列にするスクリプト」は、
VW9でも動くはずだったのですが、そのままではダメなようです。
VW9.5(Mac)、VW9デモ(Win)共に、VWが落ちてしまいました。
VW10.5以降で確認したところ、PlugInLibraryRoutinesの中にこんな関数を見つけまし
た。これをつかうと大丈夫そうです。
HScale2D(h: HANDLE; centerX: REAL; centerY: REAL; scaleX: REAL;
scaleY: REAL; scaleText: BOOLEAN);
ハンドル図形に対して拡大縮小をさせます。最後の引数scaleText:
BOOLEANは文字に対
して実行するかということなので、これをfalseにしておいてグループ図形に対して実
行すれば均等配列が出来ますよ。
どうも思いつきません。
>何処へ?
四角形、多角形、曲線で図面を書いてGetBBoxで最小の縦横寸法をレコードに書き出し
ます。この時、それぞれの図形が傾いていないならOKなのですが、傾いていると意味の
ない数字になってしまいます。それぞれの図形タイプ毎に条件を付けていくと...。
それで、何処へ?行ってしまいました...。
下の書き込みの均等文字列(グループ図形)の幅だけを、スクリプトで簡単に変えられないでしょうか?
手動なら問題ないのですが...
Scale()でやると、文字サイズまで変わってしまいます。
>陰陽師さん
太っ腹!
ときどきWinのNotePadでスクリプトを書いてましたが、オートインデントすらないので不便でした。
Vector Script専用 Editor、ありがたく使わせていただきます。
みなさんに成りすましまして、お礼申し上げます。
>石男さん
何処へ?
四角形の傾きについて、先日のは律儀に計算しましたが、多角形を水平に回転すれば四角形かどうかの
鑑定が簡単になるような気がしました。
>ARcoatingさん
おひさです!
>A&Bさん
どうもです。
>陰陽師さん
すごい物を作りましたね。そのパワーには脱帽です。残念ながら私はMacなので使えな
いのですが...。
そんなMacな人にはやはり「mi」がお勧めです。A+AさんがVectorScriptモードを提供
してくれました。数年前から「mi」を愛用していますが、これで鬼に金棒です。
AppleScriptを少し分かれば「mi」のドキュメントをVectorScriptをVWで実行させるこ
とも簡単です。またテンプレートを利用するとかなり便利です。
そんな「mi」は...
http://www.mimikaki.net/
与太郎さん、石男さん、陰陽師さん。
ただ、ただ、感謝です。ありがとうございます。
>与太郎さん
いつも、すみません。2Dも条件を与えていくと段々奥が深くなっていきますね。
どうも考えているところまで行けない気がしてきました。
全部の辺の長さと角度をしらべて、幅、高さ、角度を返す関数です。
procedure test;
{$ DEBUG}
var
h:handle;
wd, ht, a:real;
function Closed(hPoly: handle): boolean;
{多角形が閉じていればTRUEを返します。}
var
fPat:integer;
begin
fPat:= GetFPat(hPoly);
SetFPat(hPoly, 0);
if HArea(hPoly) = 0 then
Closed:= false
else
Closed:= true;
SetFPat(hPoly, fPat);
end; {Closed}
function IsRectangle(h:handle; var wd, ht, ang:real):boolean;
{ 長方形の情報を返します。 }
const
PolyObj = 5;
dA = 0.0001;{degree}
var
result:boolean;
i:integer;
x, y:array[0..4] of real;
d, a:array[1..4] of real;
v:vector;
aa:real;
begin
result:= false;
if GetType(h) = PolyObj then begin
if GetVertNum(h) = 4 then begin
{if IsPolyClosed(h) then begin}
if Closed(h) then begin
for i:= 1 to 4 do
GetPolyPt(h, i, x[i], y[i]);
x[0]:= x[4]; y[0]:= y[4];
for i:= 1 to 4 do begin
d[i]:= Distance(x[i], y[i], x[i-1],
y[i-1]);
v[1]:= x[i] - x[i-1]; v[2]:=
y[i] - y[i-1];
a[i]:= Vec2Ang(v);
if (i = 3) | (i = 4) then begin
a[i]:= a[i] + 180;
if 180 < a[i] then
a[i]:= a[i] - 360;
end;{if}
end;{for}
if ((d[1]) = (d[3])) & ((a[1]) =
(a[3])) then begin
result:= true;
aa:= a[2] - a[1] + 90;
while (180-dA) < aa do
aa:= aa - 180;
if Abs(aa) < dA then begin
wd:= d[1];
ht:= d[2];
ang:= a[2];
end;{iF}
end;{if}
end;{if}
end;{if}
end;{if}
IsRectangle:= result;
end;{IsRectangle}
begin{test}
h:= FSActLayer;
if IsRectangle(h, wd, ht, a) then
Message('Width=', wd, ' / Height=', ht, ' / Angle=', a)
else
Message('長方形ではござらん!');
end;
Run(test);
IsPolyClosed
は、使えない場合もあるので、代わりにClosedを使いました。
距離の比較に「=」は、まずいかも。(誤差を考慮しないと)
1年ぶりに書き込みさせていただきます。
Vector Script専用 Editorなるものを作ってみました...
Windows版 のみなのですが Win な人は下のURLを覗いて見てください。
http://www.eonet.ne.jp/~onmyouji/VWEditor.html
四角形を傾かせると多角形になってしまいますが、それなら傾いた多角形の角度を取得
する方法ってあるんでしょうか?もしかしたら、四角形のPIOを作って...という方法し
かないんですかね?
>0,0,1とは思ってもみませんでした、、、。
マニュアルに書かれている通りにやったのでは絶対に分かりません。
たまたま、NNAのMLで見つけただけです。ホントは書き直してもらいたいところです。
こんにちは石男さん。
情報ありがとうございます!
SetViewVectorはこうやってやれば使えるのですね!!
0,0,1とは思ってもみませんでした、、、。
石男さんのご想像通り、SetViewVectorが使えなくて、
SetViewにしました、、SetViewはほんとわけわかりません、、、。
おかげさまで、視点を自由に変えられそうです!
ありがとうございました!
>ARcoatingさん
SetViewを使うと一生懸命座標計算をしなくてはならないと思いますが、SetViewVector
を使うと楽出来ます。きっとSetViewVectorが使えず、SetViewを使うはめになったので
しょうけど...。
SetViewVector( locationX , locationY , locationZ , targetX , targetY
, targetZ , upX , upY , upZ ) ;
locationカメラの座標
targetview target視点の座標
up視線角度
となっていますが、upの引数を0,0,1にしないと駄目なようです。
以下参考になれば
Procedure Test ;
Var
gCamera , gTarget : Vector ;
gLenz : Real ;
gSave : Boolean ;
{--------------------Sub-------------------}
{-------------------------Set_Projection------------------------}
Procedure Set_Projection( Lenz_Dist : Real ) ;
Var
p1X, p1Y, p2X, p2Y , Real_Offset : Real;
Begin
GetDrawingSizeRect( p1X, p1Y, p2X, p2Y );
Real_Offset := ( 25.413 * GetLScale( ActLayer ) ) * Lenz_Dist ;
Projection( 1 , 0 , Real_Offset , p1X, p1Y, p2X, p2Y );
End ;
{=================Main===================}
Begin
gLenz := 8.5 ;
gSave := false ;
GetPt( gCamera.x , gCamera.y ) ;
GetPtL( gCamera.x , gCamera.y , gTarget.x , gTarget.y ) ;
PtDialog( 'カメラとターゲットの高さを入力 X:カメラ Y:ターゲット' ,
'0' , '0' , gCamera.z , gTarget.z )
;{-----------カメラとターゲットの一致には同じ高さ-------------}
If Not DidCancel Then
Begin
Locus3D( gCamera.x , gCamera.y , gCamera.z ) ;
Locus3D( gTarget.x , gTarget.y , gTarget.z ) ;
Set_Projection( gLenz ) ;
SetViewVector( gCamera.x , gCamera.y , gCamera.z , gTarget.x ,
gTarget.y , gTarget.z , 0, 0 , 1 ) ;
{---------画面登録----------}
If ( gSave = true ) Then
Begin
SaveSheet( 'TestView' , true, true, true ) ;
End ;
End ;
End ;
Run( Test ) ;
こんばんわ。おひさしぶりです。
ちょっと来てない間に与太郎さんすごいですね!!
大変貴重で有用なツールがたくさん!!
さっそく、使わせて頂きます!
私も、ツールではありませんが、スクリプトを書きましたので
書込みさせて頂きます。
内容はロジスティック方程式を解いて、それを図形化、
そして、作成過程をカメラを回して表示するものです。
QT書出しもついでにしますが、時間がかかるので
コメントアウトしました。
procedure fearful_symmetry;
const
_Pai=3.141592653589793;
var
_cA,cB,cC,cD,cK,cGyou,bairitu,copy2:real;
_cCount,zukeiiti,copy1 : integer;
_x,y,z,z_sita,drawX,drawY :real;
_draw2X,draw2Y :real;
_n,nVTR,nnVTR : integer;
_kirimu_n1,kirimu_n2 : integer;
_hn1,wsh : HANDLE;
_ZArray: ARRAY[0..100,0..100] OF real;
_{以下ビデオ用}
_filename :string;
_refa,abc :INTEGER;
_frameRate :REAL;
_keyframeRate :LONGINT;
_xAngleR, yAngelR, zAngleR, offsetX, offsetY, offsetZ:REAL;
_FrameCutNo :INTEGER;
_
{__/__/__/__/__/__/__/__/__/__/ 座標計算
__/__/__/__/__/__/__/__/__/}
PROCEDURE Logistic_Equation(var xx:real; var yy:real);
var
_x1,y1 :real;
begin
_x1:=cA*sin(2*Pai*xx)+cB*sin(2*Pai*xx)*cos(2*Pai*yy)+cC*sin(4*Pai*xx)+cD*sin(6*Pai*xx)*cos(4*Pai*yy)+cK*xx;
_if xx>=0 then
__x1:=x1-trunc(x1)
__else
__x1:=x1-trunc(x1)+1;
_y1:=cA*sin(2*Pai*yy)+cB*sin(2*Pai*yy)*cos(2*Pai*xx)+cC*sin(4*Pai*yy)+cD*sin(6*Pai*yy)*cos(4*Pai*xx)+cK*yy;
_if yy>=0 then
__y1:=y1-trunc(y1)
__else
__y1:=y1-trunc(y1)+1;
_xx:=(x1+1)*50;
_yy:=(y1+1)*50;
end;
{__/__/__/__/__/__/__/__/__/__/ 高さ(z)算出
__/__/__/__/__/__/__/__/}
PROCEDURE Z_Maker(ax,ay:LONGINT; var az:real; var bz:real);
var
_sukima: Real;
begin
_sukima := 0.1;
_IF ZArray[ax,ay]<>0 THEN
__begin
__bz := ZArray[ax,ay]+sukima;
__az := bz*bairitu+0.3;
__ZArray[ax,ay] := az;
_end else
__begin
__bz := sukima;
__az := bz+0.3;
__ZArray[ax,ay] := az;
_end;
end;
{__/__/__/__/__/__/__/__/__/__/ 3D図形を作る
__/__/__/__/__/__/__/__/}
PROCEDURE Objects3D_Maker(ax,ay:LONGINT; az,bz:real);
_{__/__/__/__/__/__/__/ 色づけ __/__/__/__/__/__/__/__/__/__/}
_function Fcolor(aaz:real):LONGINT;
_var
__aa: LONGINT;
_begin
__IF aaz<0.5 THEN
___begin
___aa := round(random*191)+48;{48-239=191}
___Fcolor := aa;
__END
__ELSE BEGIN
__IF (aaz>=0.50) and (aaz<1) THEN
___begin
___aa := round(random*95)+80;
___Fcolor := aa;
__END
__ELSE BEGIN
__IF (aaz>=1) and (aaz<7) THEN
___begin
___aa := round(random*95)+112;
___Fcolor := aa;
__END
__ELSE BEGIN
___aa := round(random*95)+144;
___Fcolor := aa;
__end;
__end;
__end;
_end;
begin
_FillBack (Fcolor(az));
_PenFore (Fcolor(az));
_BeginXtrd(bz, az);
_rect(ax-0.4,ay+0.4,ax+0.4,ay-0.4);
_EndXtrd;
end;
{__/__/__/__/__/__/__/__/__/__/ カメラの動き
__/__/__/__/__/__/__/__/}
procedure Camera_Move(FcNo:INTEGER; var ARx:real; var ARy:real; var
ARz:real; var OSx:real; var OSy:real; var OSz:real);
_begin
__IF (FcNo>0) and (FcNo<=30) THEN
__BEGIN
___ARx := ARx+0;
___ARy := ARy+0;
___ARz := ARz+0;
___OSx := OSx+1.267;
___OSy := OSy+0.2;
___OSz := OSz-0.167;
__END
__ELSE BEGIN
__IF (FcNo>30) and (FcNo<=31) THEN
__BEGIN
___ARx := ARx+43;
___ARy := ARy+0;
___ARz := ARz+0;
___OSx := OSx+11;
___OSy := OSy-18;
___OSz := OSz+23;
__END
__ELSE BEGIN
__IF (FcNo>31) and (FcNo<=200) THEN
__BEGIN
___ARx := ARx+0;
___ARy := ARy+0;
___ARz := ARz+0;
___OSx := OSx+0;
___OSy := OSy+0;
___OSz := OSz-0.355;
__END
__ELSE BEGIN
__END;
__END;
__END;
_END;
{__/__/__/__/__/__/__/__/__/__/ メイン
__/__/__/__/__/__/__/__/__/__/}
begin
_wsh := ActSSheet ;
_cGyou:=GetCellNum(wsh,28,5);
_cA:=-0.59;
_cB:=0.2;
_cC:=0.1;
_cD:=0;
_cK:=0;
_bairitu:=1.2;
_zukeiiti:=1;
_CASE zukeiiti OF
__1: begin copy1:=1; copy2:=50; cCount:=10000; nnVTR:=50; end;
_END;
_{ビデオ設定}
_xAngleR:=-43;
_yAngelR:=0;
_zAngleR:=0;
_offsetX:=-99;
_offsetY:=-38;
_offsetZ:=-8;
_{QT設定}
{_filename := Concat('C:\Program
Files\VectorWorks10J',cGyou,'.mov');}
{_refa := 122;}
{_abc := QTInitialize;}
{_refa := QTOpenMovieFile(filename);}
{_QTSetMovieOptions(refa, 12, 12, TRUE, TRUE);}
_{Message(abc,' start_time_',Date(2,2));}
{_LoadCell(2,1,Date(2,2));}{レンダ時間計測用}
_x:=0.1;
_y:=0.3;
_for n:=1 to 20 do
_begin
__Logistic_Equation(x,y);
_end;
_QTWriteFrame(refa);
_for n:=1 to cCount do
_begin
__nVTR := nVTR+1;
__Logistic_Equation(x, y);
__drawX := round(x);
__drawY := round(y);
__for kirimu_n1:=1 to copy1 do
__begin
___CASE kirimu_n1 OF
____1: draw2X:=drawX;
____2: draw2X:=drawX+copy2;
___END;
___for kirimu_n2:=1 to copy1 do
___begin
____CASE kirimu_n2 OF
_____1: draw2Y:=drawY;
_____2: draw2Y:=drawY+copy2;
____END;
____if (draw2X>100) or (draw2Y>100) then
____begin end
____else begin
____Z_Maker(draw2X, draw2Y, z, z_sita);
____Objects3D_Maker (draw2X, draw2Y, z, z_sita);
____hn1 := LNewObj;
____SetDSelect(hn1);
____end;
___end;
__end;
__if nVTR=nnVTR then
___begin
___FrameCutNo := FrameCutNo+1;
___Camera_Move (FrameCutNo, xAngleR, yAngelR, zAngleR, offsetX,
offsetY, offsetZ);
___SetView (xAngleR, yAngelR, zAngleR, offsetX, offsetY,
offsetZ);
___ReDrawAll;
{___QTWriteFrame(refa);}{QT設定中間}
___nVTR := 0;
__END
__ELSE BEGIN
__end;
__{Message(n);}
_end;
{_QTCloseMovieFile(refa);} {QT設定中間}
{_QTTerminate;}
{_LoadCell(2,3,Date(2,2));}{レンダ時間計測用}
_{ClrMessage;}
end;
run(fearful_symmetry);
アクティブレイヤの文字と直線を選択して実行します。
直線を基準線にした均等配列文字(グループ図形)が出来ます。
procedure AlignText;
{ 文字を直線の長さで均等配列にする(VW9以降) }
{ アクティブレイヤの文字と直線を選択して実行 }
{$ DEBUG}
const
_LineObj = 2;
_TextObj = 10;
_LF = Chr(13);
_
type
_charInfo = structure
__numByte_:integer;
__chars_:array[1..2] of char;
__font, size, style_:integer;
__x1, x2_:real;
__hnd_:handle;
__isSpace_:boolean;
_end;
_
var
_txt_:array[0..254] of charInfo;
_txtLen_:integer;
_txtVAlign_:integer;
_txtColor_:integer;
_r, g, b_:real;
_i, j, n_:integer;
_c_:char;
_s_:string;
_h, hL, hT, hG_:handle;
_rot, lnLen_:real;
_x0, y0, x, y_:real;
_x1, y1, x2, y2_:real;
_spc, wd_:real;
_numSpc_:integer;
_
function GetNumByte(c:char):integer;
var
_result_:integer;
begin
_case Ord(c) of
__129..159, 224..252: result:= 2;
__otherwise result:= 1;
_end;{case}_
_GetNumByte:= result;
end;{GetNumByte}
begin{main}
_PushAttrs;
_{ 図形ハンドルを取得 }
_h:= FSActLayer;
_while (h <> nil) do begin
__if h <> nil then begin
___if GetType(h) = LineObj then
____hL:= h
___else if GetType(h) = TextObj then
____hT:= h;
___h:= NextSObj(h);
__end;{if}
_end;{while}
_h:= nil;
_
_if (hL = nil) | (hT = nil) then begin
__AlrtDialog(Concat('アクティブレイヤで、', LF,
___'文字と直線を選択して実行してください。'));
_end{if}
_else begin
_{ 文字情報を取得 }
__GetPenFore(hT, r, g, b);
__RGBToColorIndex(r, g, b, txtColor);
__txtVAlign:= GetTextVerticalAlign(hT);
__n:= GetTextLength(hT);
__i:= 0;
__j:= 0;
__s:= GetText(hT);
__while (i < n) do begin
___c:= copy(s, i+1, 1);
___txt[j].chars[1]:= c;
___txt[j].font:= GetTextFont(hT, i);
___txt[j].size:= GetTextSize(hT, i);
___txt[j].style:= GetTextStyle(hT, i);
___txt[j].numByte:= GetNumByte(c);
___txt[j].chars[1]:= copy(s, i+1, 1);
___if txt[j].numByte = 2 then
____txt[j].chars[2]:= copy(s, i+2, 1);
___if txt[j].chars[1] = ' ' then begin
____txt[j].chars[1]:= '.';{
空白の幅がゼロになる為(WinのVW10で、Macは未確認) }
____txt[j].isSpace:= true;
___end
___else begin
____txt[j].isSpace:= false;
___end;{if}
___i:= i + txt[j].numByte;
___j:= j + 1;
__end;{while}
__txtLen:= j;
__
__{ 線情報を取得 }
__GetSegPt1(hL, x0, y0);
__GetSegPt2(hL, x, y);
__lnLen:= HLength(hL);
__rot:= HAngle(hL);
__
__{ 文字を生成 }
__TextJust(2);_{Center}
__TextVerticalAlign(txtVAlign);
__PenFore(txtColor);
__BeginGroup;
__for i:= 0 to txtLen - 1 do begin
___TextFont(txt[i].font);
___Textsize(txt[i].size);
___x:= x0 + lnLen/txtLen*(i+0.5);
___TextOrigin(x, y0);
___if txt[i].numByte = 2 then
____CreateText(Concat(txt[i].chars[1],
txt[i].chars[2]))
___else {txt[i].numByte = 1}
____CreateText(txt[i].chars[1]);
___txt[i].hnd:= LNewObj;
___SetTextStyle(txt[i].hnd, 0, txt[i].numByte,
txt[i].style);
__end;{for}
__EndGroup;
__hG:= LNewObj;
__
__{ 文字間距離を取得 }
__numSpc:= 0;
__wd:= 0;
__for i:= 0 to txtLen - 1 do begin
___GetBBox(txt[i].hnd, txt[i].x1, y1,
txt[i].x2, y2);
___if (0 < i) & (i < (txtLen-1)) then begin
____numSpc:= numSpc + 2*txt[i].numByte;
___end
___else begin
____numSpc:= numSpc + txt[i].numByte;
___end;
___wd:= wd + txt[i].x2 - txt[i].x1;
__end;{for}
__spc:=(lnLen - wd) / numSpc;
__
__{ 文字を再配置 }
__HMove(txt[0].hnd, x0 - txt[0].x1, 0);
__for i:= 1 to txtLen - 1 do begin
___GetBBox(txt[i-1].hnd, x1, y1, x2, y2);
___x:= x2 + spc * (txt[i-1].numByte +
txt[i].numByte);
___HMove(txt[i].hnd, x - txt[i].x1, 0);
__end;{for}
__
__{ 文字を回転 }
__HRotate(hG, x0, y0, rot);
__
__{ 「.」を空白に戻す }
__for i:= 0 to txtLen - 1 do begin
___if txt[i].isSpace then
____SetText(txt[i].hnd, ' ');
__end;
_end;{if}
_PopAttrs;
end;{main}
Run(AlignText);
普通の文字図形と違って、幅を変えると文字間隔が変わります。
斜めの場合は,基準線といっしょに選択すれば、ドラッグで幅を変えられます。
環境設定で、「文字を反転禁止」にして水平反転すると、文字が逆順になります。
(意味があるか判りませんが...)
グループの中身は一文字ずつに分解されているので、文字の編集は無理です。
プラグインオブジェクトにすれば、文字の編集は出来るようになりますが、
属性(フォント、サイズ,スタイル)を文字ごとに変えられなくなります。
名前と図形タイプを、ワークシートに書き出します。
procedure ObjNameList;
{ VWの書類で使われてる名前をワークシートに書き出す。 }
{$ DEBUG}
const
_WSName = 'Name List';
_WSheet = 18;
_MaxRow = 4094;
_Clm_Name = 1;
_Clm_TypeID = 2;
_Clm_TypeNm = 3;
_SQ = Chr(39);{ ' }
_LF = Chr(13);{ 改行 }
var
_h, hWS_:handle;
_name_:string;
_numRow, numClm_:integer;
_i, numName_:integer;
_formula_:string;
function GetTypeName(i:integer):string;
var
_result_:string;
begin
_case i of
__2: result:= '直線';
__3: result:= '四角形';
__4: result:= '長円';
__5: result:= '多角形';
__6: result:= '円/円弧';
__8: result:= 'フリーハンド';
__9: result:= '3D 基準点';
__10: result:= '文字列';
__11: result:= 'グループ';
__12: result:= '四分円';
__13: result:= '隅の丸い四角形';
__14: result:= 'ビットマップ';
__15: result:= 'シンボル';
__16: result:= 'シンボル定義';
__17: result:= '2D 基準点';
__18: result:= 'ワークシート';
__21: result:= '曲線';
__22: result:= 'PICT';
__24: result:= '柱状体';
__25: result:= '3D 多角形';
__29: result:= 'リンク図形';
__31: result:= 'レイヤ';
__34: result:= '回転体';
__38: result:= '多段柱状体';
__40: result:= 'メッシュ';
__41: result:= 'メッシュの頂点';
__47: result:= 'レコード定義';
__48: result:= 'レコード';
__49: result:= 'ドキュメントスクリプト';
__51: result:= 'スクリプトパレット';
__56: result:= 'ワークシート図形';
__63: result:= '寸法線';
__66: result:= 'ハッチング定義';
__68: result:= '壁';
__71: result:= '柱、床、屋根';
__81: result:= '光源';
__82: result:= '屋根';
__83: result:= '屋根';
__84: result:= 'ソリッドモデラー';
__86: result:= 'プラグインオブジェクト';
__87: result:= 'ドーマー、スカイライト';
__89: result:= '円弧壁';
__92: result:= 'シンボルフォルダ';
__93: result:= 'テクスチャ';
__94: result:= 'クラス定義';
__97: result:= 'テクスチャ定義';
__95: result:= '球、半球、円錐';
__111: result:= 'NURBS曲線';
__113: result:= 'NURBS曲面';
__119: result:= 'イメージ定義';
__120: result:= 'グラデーション定義';
__121: result:= 'フィル空間';
__otherwise result:= '未定義';
_end;{case}
_GetTypeName:= result;
end;{GetTypeName}
begin{main}
_numName:= NameNum;
_if (MaxRow-1) < numName then begin
__AlrtDialog(Concat('名前が多すぎます。 ', LF, MaxRow-1,
'個以上は表示出来ません。'));
__numName:=MaxRow - 1;
_end;{if}
_
_{ WSを選択/作成 }
_hWS:= GetObject(WSName);
_if (hWS <> nil) & (GetType(hWS) = WSheet) then begin
__GetWSRowColumnCount(hWS, numRow, numClm);
__if (numName+1) < numRow then
___DeleteWSRows(hWS, numRow, numRow-numName-1)
__else if numRow < (numName+1) then
___InsertWSRows(hWS, numRow, numName+1-numRow);
_end{if}
_else begin
__name:= WSName;
__i:= 0;
__while (hWS <> nil) do begin
___i:= i + 1;
___name:= Concat(WSName, '-', Num2Str(0, i));
___hWS:= GetObject(name);
__end;{while}
__if hWS = nil then
___hWS:= CreateWS(name, numName+1, Clm_TypeNm);
__SetWSCellFormula(hWS, 1, Clm_Name, 1, Clm_Name, '名前');
__SetWSCellFormula(hWS, 1, Clm_TypeID, 1, Clm_TypeID,
'図形タイプ');
_end;{else}
_
_{ WSに記入 }
_for i:= 1 to numName do begin
__name:= Index2Name(i);
__formula:= Concat('=', SQ, name, SQ);
__SetWSCellFormula(hWS, i+1, Clm_Name, i+1, Clm_Name, formula);
__h:= GetObject(name);
__formula:= Num2Str(0, GetType(h));
__SetWSCellFormula(hWS, i+1, Clm_TypeID, i+1, Clm_TypeID,
formula);
__formula:= Concat(':', GetTypeName(GetType(h)));
__SetWSCellFormula(hWS, i+1, Clm_TypeNm, i+1, Clm_TypeNm,
formula);
_end;{for}
_ShowWS(hWS, true);
end;{main}
Run(ObjNameList);
ファイル名とレイヤ名は別扱いのようで、名前のリストには入っていません。
でも、クラス名は入っています。(入ってなくてもいいと思うんですが)
仕事で作ったファイルだと、名前がたくさん付いてるのが判ります。
あと、名前を消すと、そのindexは新しく名前が付けられたときのために空い
たままになるようです。
「ワークシートの文字を(図面に)描く」の逆バージョンです。
図面上でクリックした文字を、ワークシートの選択セルにコピーします。
文字属性はコピーしません。
SetWSSelection
で警告を出さなくする方法がわからなかったので、SetPref(21, false);
で
環境設定の「VectorScriptの警告を表示」をOFFにしています。
というか、実行中にわざと警告を出すようなスクリプトもあるので、デバッグ中でなければ
「VectorScriptの警告を表示」させないほうが良いようです。
procedure CopyText2SelCell;{
選択セルに、クリックした文字をコピーします。(VW9以降対応) }
{$ DEBUG}
const
_TextObj = 10;
var
_hWS, hTx, h, h0_:handle;
_row, maxRow, row0,
_clm, maxClm, clm0,
_top, left,
_topSub, bottom, right, botSub_:integer;
_x, y_:real;
_str_:string;
begin
_hWS:= ActSSheet;
_if hWS = nil then begin
__AlrtDialog('ワークシートを開いてください。');
_end{if}
_else begin
__SetPref(21, false);{
環境設定の「VectorScriptの警告を表示」をOFFにする }
__DSelectAll;
__GetWSRowColumnCount(hWS, maxRow, MaxClm);
__GetWSSelection(hWS, row, clm, top, left, topSub, bottom, right,
botSub);
__row0:= row;
__clm0:= clm;
__Message('文字をクリックしてください。 空クリックで終了します。');
__GetPt(x, y); h:= PickObject(x, y);
__h0:= h;
__if (h = nil) | (GetType(h) <> TextObj) then begin
___AlrtDialog('文字をクリックしてください。');
__end{if}
__else begin
___if (top = bottom) & (left = right) then begin
____top:= 1; Left:= 1; bottom:= maxRow; right:= maxClm;
____SetWSSelection(hWS, row, clm, top, left, topSub, bottom,
right, botSub);
___end;
___repeat
____str:= GetText(h);
____SetWSCellFormula(hWS, row, clm, row, clm, str);
____clm:= clm + 1;
____if clm > right then begin
_____clm:= left;
_____row:= row + 1;
_____if row >bottom then begin
______row:= top;
_____end;{if}
____end;{if}
____SetWSSelection(hWS, row, clm, top, left, topSub, bottom,
right, botSub);
____DSelectObj(h0);
____h0:= h;
____SetSelect(h);
____ReDraw;
____if (row = row0) & (clm = clm0) then begin
_____h:= nil;
____end{if}
____else begin
_____GetPt(x, y);
_____h:= PickObject(x, y);
____end;{else}
___until (h = nil) | (GetType(h) <> TextObj);
__end;{else}
__ClrMessage;
_end;{else}
end;
Run(CopyText2SelCell);
これで「図面の中の表をワークシート化するスクリプト」の何パーセントかは実現したかなぁ?
このスクリプトを作るには、Excelで座標計算をして結果をスクリプトにするのと、
普通にスクリプトを書くのと、2つの方法があります。
1. Excelでスクリプト(3D多角形生成文)を書く方法です。
3D多角形を作るスクリプトは、Poly(X1, Y1, Z1, X2, Y2, Z3...Xn, Yn,
Zn); です。
まずはExcelに下のようなデータを打ち込みます。
角度 R H
0 0 60
30 2 55
60 4 50
90 6 45
120 8 40
150 10 35
180 12 30
210 14 25
240 16 20
270 18 15
300 20 10
330 22 5
360 24 0
上のデータから、座標を計算して下のスクリプトを作ります。(度とラジアンに注意)
Excelなら簡単に出来ます。VWのワークシートでも可能です。
Poly3D(
0.00 , 0.00 , 60.00 ,
1.73 , 1.00 , 55.00 ,
2.00 , 3.46 , 50.00 ,
0.00 , 6.00 , 45.00 ,
-4.00 , 6.93 , 40.00 ,
-8.66 , 5.00 , 35.00 ,
-12.00 , 0.00 , 30.00 ,
-12.12 , -7.00 , 25.00 ,
-8.00 , -13.86 , 20.00 ,
0.00 , -18.00 , 15.00 ,
10.00 , -17.32 , 10.00 ,
19.05 , -11.00 , 5.00 ,
24.00 , 0.00 , 0.00 );
2. 普通にPascal形式のスクリプトを書きます。
ダイアログやワークシートでパラメータを設定するスクリプトは長くなるので、
ここではスクリプトの定数を直接書き換えて設定を変えます。
Procedure Spiral;
{ 螺旋形の3D多角形を作ります }
{ パラメータはconstで設定します }
const{ ここでパラメータを設定します }
StartA = 0; { 開始角度 }
EndA = 360; { 終了角度 }
StartR = 0; { 開始半径 }
EndR = 24; { 終了半径 }
StartH = 60; { 開始高さ }
EndH = 0; { 終了高さ }
N = 12; { 分割数 }
var
x, y, z:real;
dA, a:real;
dR, r:real;
dH:real;
i:integer;
begin
dA:= (EndA - StartA) / N;
dR:= (EndR - StartR) / N;
dH:= (EndH - StartH) / N;
BeginPoly3D;
for i:= 0 to N do begin
a:= Deg2Rad(StartA + i * dA);
r:= StartR + i * dR;
x:= r * Cos(a);
y:= r * Sin(a);
z:= StartH + i * dH;
Add3DPt(x, y, z);
end;{while}
EndPoly3D;
end;
Run(Spiral);
スクリプトが出来たら、VWのリソースパレット/プラウザでVectorScriptコマンドを作って、
VectorScriptエディタにスクリプトを貼り付けます。
上の右側にあるコンパイル・ボタンを押して、エラーが出なければOKです。
定数を変えたりスクリプトを貼りかえるときは、コマンドパレット上のコマンドを、Alt/option
キーを押してダブルクリックします。VectorScriptエディタが開きます。
下の書き込みのスクリプトでWSを作って、線幅の数字を変えてから実行してください。
procedure SetClassLW;
{ クラスの線幅をワークシートで設定した値に設定します。 }
{$ DEBUG}
const
_WSName = 'Class LW List';
_WSheet = 18;
_ClmCls = 1;
_ClmLW = 2;
_LF = Chr(13);{ 改行 }
var
_hWS_:handle;
_name_:string;
_maxRow, maxClm_:integer;
_i, wd_:integer;
begin{main}
_hWS:= GetObject(WSName);
_if (hWS = nil) | (GetType(hWS) <> 18) then begin
__AlrtDialog(Concat('「', WSName, 'というWSがありません。',
___ LF,
'WSの名前を変えるか、新しいWSを作ってください。'));
_end{if}
_else begin
__GetWSRowColumnCount(hWS, maxRow, maxClm);
__for i:= 2 to maxRow do begin
___GetWSCellString(hWS, i, ClmCls, name);
___wd:= Round(GetCellNum(hWS, i, ClmLW));
___SetClLW(name, wd);
__end;{for}
__ShowWS(hWS, true);
_end;{else}
_
end;{main}
Run(SetClassLW);
クラスの線色や面属性を再設定するように修正するのも簡単そうです。
VW談話室より。
>壁や柱とかのクラスごとに線の太さをそのつど変更しています。
スクリプトで一度に変更してみましょうか。
まず、クラスごとの線幅をWSに書き出してみます。
procedure CreateClassLWList;
{ クラスの線幅をワークシートに書き出します。 }
{$ DEBUG}
const
_WSName = 'Class LW List';
_WSheet = 18;
_ClmCls = 1;
_ClmLW = 2;
_SQ = Chr(39);{ ' }
var
_hWS_:handle;
_name_:string;
_maxRow, maxClm_:integer;
_i, nC_:integer;
_formula_:string;
begin{main}
_nC:= ClassNum;
_
_{ WSを選択/作成 }
_hWS:= GetObject(WSName);
_if (hWS <> nil) & (GetType(hWS) = 18) then begin
__GetWSRowColumnCount(hWS, maxRow, maxClm);
__if (nC+1) < maxRow then
___DeleteWSRows(hWS, maxRow, maxRow-nC-1)
__else if maxRow < (nC+1) then
___InsertWSRows(hWS, maxRow, nC+1-maxRow);
_end{if}
_else begin
__name:= WSName;
__i:= 0;
__while (hWS <> nil) do begin
___i:= i + 1;
___name:= Concat(WSName, '-', Num2Str(0, i));
___hWS:= GetObject(name);
__end;{while}
__if hWS = nil then
___hWS:= CreateWS(name, nC+1, 2);
__SetWSCellFormula(hWS, 1, ClmCls, 1, ClmCls, 'Class名');
__SetWSCellFormula(hWS, 1, ClmLW, 1, ClmLW, '線幅');
_end;{else}
_
_{ WSに記入 }
_for i:= 1 to nC do begin
__name:= ClassList(i);
__formula:= Concat('=', SQ, name, SQ);
__SetWSCellFormula(hWS, i+1, ClmCls, i+1, ClmCls, formula);
__formula:= Num2Str(0, GetClLW(name));
__SetWSCellFormula(hWS, i+1, ClmLW, i+1, ClmLW, formula);
_end;{for}
_ShowWS(hWS, true);
end;{main}
Run(CreateClassLWList);
他の図形と同じように、レイヤもスクリプトで削除できます。
procedure DelLayer;
{ アクティブレイヤを(空なら)削除します。 }
{
アクティブレイヤが空でないか、レイヤがひとつしかない場合は削除しません。
}
var
hAL, hL:handle;
name:string;
begin
hAL:= ActLayer;
name:= GetLName(hAL);
hL:= FLayer;
while (hL <> nil) & (hL = hAL) do
hL:= NextLayer(hL);
if hL <> nil then begin
if NumObj(hAL) = 0 then begin
Layer(GetLName(hL));
DelObject(hAL);
AlrtDialog(Concat('レイヤ「', name, '」を削除しました。'));
end{if}
else begin
AlrtDialog(Concat('レイヤ「', name,
'」は空でないので削除しません。'));
end;{else}
end{if}
else begin
AlrtDialog(Concat('他にレイヤがないので、レイヤ「', name,
'」は削除出来ません。'));
end;{else}
end;
Run(DelLayer);
アクティブレイヤの情報を表示します。
procedure MsgLayerInfo;
{ メッセージウインドウにアクティブレイヤの情報を表示します。 }
var
_hL_:handle;
_vis_:integer;
_lVis_:string;
_ht, dHt_:real;
_xA, yA, zA_:real;
_xD, yD, zD_:real;
begin
_hL:= ActLayer;
_vis:= GetLVis(hL);
_case vis of
__0: lVis:= 'ShowLayer';
__2: lVis:= 'GrayLayer';{ ※注意 }
__-1: lVis:= 'HideLayer';{ ※注意 }
_end;{case}
_GetZVals(ht, dHt);
_GetView(xA, yA, zA, xD, yD, zD);
_Message(GetLScale(hL), ' : S=1/', GetLScale(hL),
__' (', lVis, ') : H=', ht, ' : dH=', dHt,
__' : xA=', xA, ' : yA=', yA, ' : zA=', zA,
__' : xD=', xD, ' : yD=', yD, ' : zD=', zD);
end;
Run( MsgLayerInfo);
残念ながら、レイヤの表示モードとカラー属性はVSでは取得できません。
※注意:GetLVisの返り値が、VW9までのマニュアルでは間違っています。
マニュアル→ 表示:0 /グレイ表示:1 /非表示:2
正しくは → 表示:0 /グレイ表示:2 /非表示:-1
VW10でも、スクリプトエディタの「手続き/関数...」の中の説明は間違っています。
つぎに、レイヤ情報をファイルに書き出してみます。
書き出すだけでは芸がないので、他のファイルで読み込んで同じレイヤを作れるようにします。
procedure GetLayerInfoAsScript;
{ VWフォルダの「Output.txt」にレイヤ生成のスクリプトを書き出します。
}
const
_SQ = Chr(39);
var
_hL, hAL_:handle;
_name_:string;
_scale_:real;
_vis_:integer;
_ht, dHt_:real;
_xA, yA, zA_:real;
_xD, yD, zD_:real;
{ AddSQ関数は、ここに書いてください。前の書き込みにあります。 }
begin{main}
_hAL:= ActLayer;
_hL:= FLayer;
_while hL <> nil do begin
__{ レイヤ情報を取得する。 }
__name:= GetLName(hL);{ 必要なら name:= AddSQ(GetLName(hL));
に書き換えてください。 }
__scale:= GetLScale(hL);
__vis:= GetLVis(hL);
__Layer(name);
__GetZVals(ht, dHt);
__GetView(xA, yA, zA, xD, yD, zD);
__
__{ スクリプトを書き出す。 }
__WriteLn('Layer(', SQ, name, SQ, ');');
__WriteLn('SetScale(', Scale, ');');
__case vis of
___0: WriteLn('ShowLayer;');
___2: WriteLn('GrayLayer;');
___-1: WriteLn('HideLayer;');
__end;{case}
__WriteLn('SetView(', xA, ', ', yA, ', ', zA, ', ', xD, ', ', yD,
', ', zD, ');');
__if (xA = 0) & (yA = 0) & (zA = 0) then
___WriteLn('DoMenuTextByName(''Standard Views'', 1);');{
ビューが「真上から」の場合は2D表示に設定 }
__WriteLn;
__
__hL:= NextLayer(hL);
_end;{while}
_
_{ アクティブレイヤを元にもどす。 }
_Layer(GetLName(hAL));
_name:= GetLName(hAL);
_WriteLn('Layer(', SQ, name, SQ, ');');
end;{main}
Run(GetLayerInfoAsScript);
「Output.txt」の中身はスクリプトになっていますので、VectorScriptとして取り込むか、
コマンドを作って貼り付ければ、別のファイルに同じ名前/縮尺/高さ/ビューのレイヤが
作れます。
書いてて思ったのですが,チャンクメニューの選択項目をVSから調べる方法はないですかね?
アクティブレイヤだけなら、こんな風にできます。
Message(GetLName(ActLayer), ' : Objects = ', NumObj(ActLayer));
グループ内の図形もカウントするなら、下のようになります。
procedure MsgObjNum;
var
name:string;
begin
name:= GetLName(ActLayer);
Message(GetLName(ActLayer), ' : Objects = ', Count(L=name));
end;
Run(MsgObjNum);
各レイヤの図形数を調べます。何かの役には立つでしょう。
procedure GetObjNum;
{ 各レイヤの図形数を「Output.txt」に書き出します。 }
{ グループ図形の中の図形はカウントされません。 }
var
_hL_:handle;
begin
_Write('Layer'); Tab(1);
_WriteLn('Objects');
_hL:= FLayer;
_while hL <> nil do begin
__Write(GetLName(hL)); Tab(1);
__WriteLn(NumObj(hL));
__hL:= NextLayer(h);
_end;{while}
end;
Run(GetObjNum);
procedure ObjNumList;
{ 各レイヤの図形数をワークシートに書き出します。 }
{ グループ図形の中の図形もカウントされます。 }
{ WSメニューの「再計算」で表示を更新できます。 }
{$DEBUG}
const
_WSName = 'Object Num List';
_WSheet = 18;
_ClmLyr = 1;
_ClmNum = 2;
_SQ = Chr(39);{ ' }
var
_hWS, hL_:handle;
_name_:string;
_row, clm_:integer;
_i, nL_:integer;
_formula_:string;
function AddSQ(s:string):string;
{ 名前の中の「'」を「'」+「'」 に直します。 }
var
_result_:string;
_i, j, lng_:integer;
begin
_result:= s;
_lng:= Len(result);
_i:= 1;
_while (i <= lng) do begin
__if Copy(result, i, 1) = SQ then begin
___result:= Concat(Copy(result, 1, i), SQ, Copy(result, i+1,
lng-i));
___lng:= lng + 1;
___i:= i + 2;
__end{if}
__else begin
___i:= i + 1;
__end;{else}
_end;{while}
_AddSQ:= result;
end;{AddSQ}
begin{main}
_nL:= NumLayers;
_
_{ WSを選択/作成 }
_hWS:= GetObject(WSName);
_if (hWS <> nil) & (GetType(hWS) = 18) then begin
__GetWSRowColumnCount(hWS, row, clm);
__if (nL+1) < row then
___DeleteWSRows(hWS, nL+1, row-nL-1)
__else if row < (nL+1) then
___InsertWSRows(hWS, row, nL+1-row);
_end{if}
_else begin
__name:= WSName;
__i:= 0;
__while (hWS <> nil) do begin
___i:= i + 1;
___name:= Concat(WSName, '-', Num2Str(0, i));
___hWS:= GetObject(name);
__end;{while}
__hWS:= CreateWS(name, nL+1, 2);
__SetWSCellFormula(hWS, 1, ClmLyr, 1, ClmLyr, 'Layer');
__SetWSCellFormula(hWS, 1, ClmNum, 1, ClmNum, 'Objects');
_end;{else}
_
_{ WSに記入 }
_i:= 0;
_hL:= FLayer;
_while hL <> nil do begin
__i:= i + 1;
__name:= GetLName(hL);{ ※注意 }
__formula:= Concat('=', SQ, name, SQ);
__SetWSCellFormula(hWS, i+1, ClmLyr, i+1, ClmLyr, formula);
__formula:= Concat('=Count(L=', SQ, name, SQ, ')');
__SetWSCellFormula(hWS, i+1, ClmNum, i+1, ClmNum, formula);
__hL:= NextLayer(hL);
_end;{while}
_ShowWS(hWS, true);
end;{main}
Run(ObjNumList);
※注意:レイヤ名に「'」が含まれているときは、下のようにしないと表示できません。
__name:= GetLName(hL);{ ※注意 }
__ ↓
__name:= AddSQ(GetLName(hL));
>石男さん
クラシック(環境)はダメですか?
与太郎はResEdit、Resorcererはクラシック環境です。
>Mac OS9でResEditを使うのも最近は嫌気がさしてきました
Mac
OS9で起動し直すのが嫌で嫌で...、ResFoolは編集するにはいいのだけど...。
結局、Mac OS9でResEditがベストなのかな〜。Resorcererは高過ぎ!
>リソース編集をみなさんは何を使っているのでしょうか?
ResEditとResorcerer2.0(古!)ですが、
最近ほとんど使ってなくて、ResEditでファイルタイプを直したり、VWのダイアログを広げる程度。
>Mac OS9でResEditを使うのも最近は嫌気がさしてきました
OS9とResEditのどちらがイヤでしょうか?
'STR#'リソースとかを大量に作るのなら、リソースエディタよりリソースコンパイラのほうが楽
かもしれません。(どこで入手するかが問題ですが)
最近SDKについて調べてましたが、Plug-in
Libraryを作れば、SDKの関数をVSから使えるようです。
例のIsPolyClosedは、SDKのGetPolyShapeCloseを呼んでるだけのような気がします。
GetProjection、GetDashPatというSDK関数を呼ぶPlug-in
Libraryを作れば、VSの中でレイヤの表
示状態(2D or 3D)や破線間隔を知ることができるのですが、
CodeWarriorは古いのしか持ってないし...
CodeWarriorの新しいの高価いし!!
年貢の納め時ですし...
というわけで、今まで粘ってみましたが、来週V-Upしますよ。
リソース編集をみなさんは何を使っているのでしょうか?
MacWinでは違うはずですが、Mac
OS9でResEditを使うのも最近は嫌気がさしてきました
Mac OSXでリソースラとなるんでしょうが、リソースラは高いし...。
OSXで使えるResFoolっていうこともあるんですが、これはイマイチです。
>MacOS9の環境とResEdit使いなら
古いリソースラで直接Excelに(50回くらい)コピペして、マクロの自動記録/実行で
説明文をB列に移動&1行削除。バージョン情報のテーブルを別のシートに作って、
VLOOKUPで参照しました。
コピペよりスクリプトのほうが楽そうですね。
>このPDFの大元は、与太郎が使ったのとおなじものかも。
MacOS9の環境とResEdit使いなら、分かります...。
コピーしたrsrcファイルをPlugInsに入れておき、GetResourceStringでリソースを取り
出しtxtファイルに項目毎吐き出します。それでtxtファイルをpdfにしたらまとめる。
ついでにVersion毎の関数も1つのtxtファイルにしておき、検索しながら...っていう感
じで作りました。
こうやれば1日程度で出来ます...、ただ2、3日考えましたが。
以前自作しようと思ってファイル形式の情報を探したのですが、結局見つけられません
でした。でも、バイナリ形式で単精度浮動小数点データを書き出さないといけないとし
たら、VSでは難しいですね。どちらかといえばSDK向きでしょうか。VSだと破線間隔を
得る方法がないのもネックです。
その辺をクリアすれば、書き出す図形の種類は直線、円弧、文字くらいなので、不可能
ではないと思いましたが。
石男さん、毎度ありがとうございます。m(_._)m
このPDFの大元は、与太郎が使ったのとおなじものかも。
>使い慣れたExcelで作ってみます
ひとつの関数がExcelの1行に収まるようにしたら、セル内で改行してるので、テンプ
レートがうまく選択できないPDFになってしまいました(セル内の複数行をいっしょに
選択できない、隣のセルの同じ行が選択範囲になる)。単語の途中に改行があると、そ
の語も検索も完全ではないし。これはExcelのままか、印刷して使ったほうがよさそう。
あと、PDFマニュアルってA4縦のレイアウトが多いのですが、画面で見るときは(モニ
タが1024x768だと)都合が悪いので、A4横にしています。
>スクリプト・エディタの関数/手続きの一覧みたいなものがPDF
を作ってみました、各関数の初出バージョン付きです。一応、カテゴリ分けもしてあり
ます。以下のところからDLしてください。各自の判断でお使いください。
http://ric.shokokai.or.jp/tochigi/Html/0940710086/index.htm
なお、Macでのみ確認しています。
>JW取り出し
は日本仕様でしょうから、カスタマイズは無理です。基本的に「××××取り出し」は
VSのみでの制御は不可です。AppleScriptを併用しないと制御は出来ません。
今のところVWにVisualBasicが対応していませんのでWinでは無理です。
となると、自力でJWが読めるファイルを作る...ってなりますが。現実的ではないで
しょう...。
はじめてスクリプトを勉強しようと思うのですが、
JW取り出しコマンドをカスタムできるものでしょうか?
具体的に、、
@取り出しについての各変換設定(色・線種等)を保存できるようにする。
AVW側図形の色(寸法・文字含む)をそのまま変換できるようにする。
、、上記の事はできそうでしょうか?
よろしければどなたか道筋があれば教えてもらいたく書き込みました。
どこから手をつけてよいものか、、、困った今日この頃です。
>html
にして、ついでにテスト結果や、気が付いた事を追加して使っています。
マニュアルが上書き可能なら、そういう使い方も出来ますね。
使い慣れたExcelで作ってみます。
PDFレフェレンスは日本仕様だったため、今後は出てこない可能性がありますよ。
わたしも皆さん同様にhtml〜PDFに変換したりしていましたが、もう最近はあきらめて
htmlでやっています。しかも、翻訳を当てにしないで原文の方で...。
同感です。今のマニュアルは関数の内容が理解できていなければ、とても利用できません。
私は個別に分けられた html の Rederence を全て合体して1つの html
にして、ついでにテスト
結果や、気が付いた事を追加して使っています。
編集に手間がかかり、ファイル容量は 2.43MB
と大きくなりましたが「こんな事ができないか?」
ってな時に、以前のように簡単に単語で検索が出来てとても便利です。
でも、検索する時に間違えて「編集」→「すべて選択」と実行した時は大変です。すべて選択する
まで数分間待たされます(泣)。
また、バージョンアップの度に新規に増えた関数分を編集(合体)しなければならないので、
これも苦の種です。
エーアンドエーさん、全体から検索できる機能をつけて下さい。それが出来なければもとのリファ
レンスに戻してください。お願いします。
VW9.5までのVS
ReferenceマニュアルはPDFなので、OS10.3のPreviewで快適に
検索できて良いのですが、VW10からはhtmlマニュアルしかありません。
htmlマニュアルって、ファイルがカテゴリー別に分かれてるので、
マニュアル全体から単語を検索できなくて不便です。
それで、htmlマニュアルをPDF化できないかと、春ごろから暇をみては作って
いたんですが、いつの間にか忘れてました。それを先日あらためて見たら、
改行位置が変だし、文字サイズがばらばらで、見栄えが良くなかったです。
(ページ数も無駄に多かったし...)
詳しい説明はいらないから、もっとコンパクトなマニュアル(というか関数/
手続きの一覧)を、A&Aで作ってもらえれば一番なんですが。
スクリプト・エディタの関数/手続きの一覧みたいなものがPDFになっていれ
ばいいんです。どのバージョンに対応してるかの情報も付いてたら助かります。
VW11に付いてるということはありませんよね?
>石男さん、
データの中でカンマ、スペースを使う(かもしれない)ので、タブ区切りに拘っておりますです。
>masafumiさん、
私も意外でした。思い付く限り、最も簡単で早い方法とは思ってましたが。(^O^)V
条件を同等にするために、関数呼び出しにしてみましたが、ほとんど同じ結果でした。
>タブ区切りファイルの Read、ReadLn
でトラブってしまいました。
私も経験ありです、結局タブ区切りをやめてカンマ区切りに変更していまいました。
>IsPolyClosed() 関数
これはSDKの関数をそのまま利用しているのでかなり違いが出ると思いますよ。
下記は IsPolyClosed()
関数と、与太郎さんに教えて頂いた方法で、実行時間を
比較してみました・・・。こんなに差が有るとは・・・。(脱帽! m(_
_)m)
{*********** 多角形の開閉チェック(その1) **********}
procedure IsPolyClosed_Test;
var
i :Integer;
objH :Handle;
closeFlg :Boolean;
tick1,tick2:Longint;
ret :Longint;
msg :String;
begin
tick1:=GetTickCount;
for i:=1 to 2000 do
begin
closeFlg:=True;
objH:=FSActLayer;
ret:=GetFPat(objH);
SetFPat(objH, 0);
if (HArea(objH)=0) then closeFlg:=False;
SetFPat(objH, ret);
end;
tick2:=GetTickCount;
msg:=Concat('時間= ',(tick2-tick1));
AlrtDialog(msg);
end;
run(IsPolyClosed_Test);
{*********** 多角形の開閉チェック(その2) **********}
procedure IsPolyClosed_Test;
var
i :Integer;
objH :Handle;
closeFlg :Boolean;
tick1,tick2:Longint;
msg :String;
begin
tick1:=GetTickCount;
for i:=1 to 2000 do
begin
objH:=FSActLayer;
closeFlg:=IsPolyClosed(objH);
end;
tick2:=GetTickCount;
msg:=Concat('時間= ',(tick2-tick1));
AlrtDialog(msg);
end;
run(IsPolyClosed_Test);
性懲りもなく、タブ区切りファイルの Read、ReadLn
でトラブってしまいました。
少々手を抜こうとしたら、余計に時間がかかったという、最悪のパターンです。
Read、ReadLn
が、文字列の先頭のスペースを無視してしまうのが原因だったのですが...
「文字列1+タブ+空白+文字列2」の行を読み込んだ場合、
文字列1 と スペース+文字列2 を取得したいのですが、 タブ+スペース
を一つのセパレータと認識するので、
文字列1 と 文字列2 が返ってきます。
また、「文字列1+タブ+タブ+文字列3」を読ませて、文字列1、文字列2(ヌル)、文字列3
を得るつもりでも、
2つのタブが一つのセパレータとなるので、途中で読み込む順番がずれてしまうことも判りました。
行ごとにデータの数が違ってたり、途中に空白データがあったり、スペースで始まる文字列データを含んだ
タブ区切りファイルは、Read、ReadLnでは無理があるようです。
以前書き込んだように、StdReadlnで一行全部読み込んで、自分でタブごとに分割する必要があります。
Read、ReadLn
の仕様を理解せずに使ったため、余計な苦労をしてしまいました。マニュアルに詳しく書いて
あれば良かったのですが...。
>masafumiさん、
多角形の開閉状態は、SetFPat(h, 0);
A:=HArea(h);で面積を調べれば判ります。
図形のロック状態は、GetBBox()で座標を調べて、HMove()の後の座標と比べてみれば判ります。
どちらも調べた後、最初の状態に戻しまときます。
こんな関数は標準で用意してよ、って思います。あと、レイヤが2D表示か3D表示かを調べる関数も。
ところで、
メッシュ図形の頂点の図形タイプ番号が定義されてるのですが、頂点のハンドルを取得して、座標を調べたり、
頂点を移動したり出来るのでしょうか?
>IsPolyClosed(polyHandle: HANDLE) : BOOLEAN;
これってかなり前からあります、実は...。
これらの外部関数はNNAのMLにでも質問しないかぎり説明は出ない気がします。
>VWPluginLibraryRoutines.p
こんな関数も有るんですね。
IsPolyClosed(polyHandle: HANDLE) : BOOLEAN;
ポリラインの開閉状態を知ることができる関数のようです。(^_^)v
変更日時順で表示させると、一番上にありました。 >
VWPluginLibraryRoutines.p
でも、VW起動or終了のたびに更新されてるようで、不思議です。
>さらにvst...なんたらかんたらと言ったものまで...これはわかりません。
NNAが説明出すまでお預けということですね。社内(NNA)用の関数なのかもしれません。
ところで、
古いスクリプト(8.5用)を10.5で使おうとしたら、思ったとおりに動かず、半日悩んでしまいました。
GetClassOptionsの戻り値が変更されてるのが原因でした。(8.5→9で変更)エラーが出ないので,原
因を見つけるのが大変でした。
定数を外部参照ファイルにして、{$INCLUDE
XXX.vss}で参照すれば、バージョンの違いに対処しやすい
と思いますが、エラーが出てうまくいきません。で、結局スクリプト本体に直接書いちゃうんですよね。
Plug-Insフォルダ内にあるVWPluginLibraryRoutines.p(スペル違いの時はご容赦)を
ご覧下さい。テキストエディタで開けます。
ネメチェック、A+Aの隠しVSが登録されています。これを見ると10.5にはvso...といっ
た一連のものはないんですよ。11にはありますが、さらにvst...なんたらかんたらと
言ったものまで...これはわかりません。
>(大層面倒そうだけど)
結構、凝ると面倒です。ただ新機能のサンプルが全然ないし資料もないので...。
やっぱり10.5では無理でしたね。>「PIOのデータパレットにプッシュボタンを付ける」
VW10.5にはPIOでイベントを受け取るオプションはあるのに(機能はしてないのかも知れませんが)、
イベントを受け取る関数がありません。だから出来ないということです。
VW11のVSRefマニュアルにも、SetObjPropVS、VSOGetEventInfo、VSOAppendWidget、VSOInsertWidget、
VSOInsertAllParams等の項目はありませんが、VW11ではそれらの関数はちゃんと使えるんですよね。
追加機能だからマニュアルにないのでしょうか。
そういえば、HiBaseの関数も、マニュアルに載ってませんけど。(一度どこかで見たはずですが...)
仕方がないのでVW11デモ版で試したら、ちゃんと動きました。感想はというと...
ボタンを付けることよりも、ボタンを押して出てくるもの(モダンダイアログに貼り付けたパターン
選択メニュー)のほうに目が行ってしまいました。
モダンダイアログは使ったことがありませんが、色々面白いことが出来そうなので、勉強してみよう
かな。(大層面倒そうだけど)
石男さん、早速ありがとうございます。
眺めましたところ、英語の説明もなんとかならないこともなさそうです。V(^O^)V
これからじっくりと読んでみます。
>書き込んだら長いし、読みづらいですね、
サンプルコードは自分で字下げしながら読みますので、大丈夫です。
長いのは...しかたないですよね。
書き込んだら長いし、読みづらいですね、すみません。
サンプルはProcedure EventEnabledObject;からです。
以下のものは11以降で...、PIOはポイント型で「指定されたイベントで実行」をオンに
してお使いください。
前半はネメチェックが作ったPluginLibraryについての説明です。後半はそれのサンプ
ルです。
{
This file contains the constants necessary to implement extended
properties and events for VectorScript objects. Listed below are
the
properties that can be assigned to objects that have the "Script
Execution
with Script-Specified Events" set. The object script for an event
driven
object must first call the drop-in routine VSOGetEventInfo so the
appropriate
event handling code can be called.
}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\ //\\}
{ //\\ PROPERTY CONSTANTS //\\}
{ //\\ //\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{
Extended Properties are set using the drop-in routines SetObjPropVS
and
SetObjPropCharVS
kObjXPropEditGroup = 1;
This 8 bit 'Char' property holds one of the property values
listed
below in the 'kObjXPropEditGroup Object Property Values' section.
kObjXPropSpecialEdit = 3;
This 'Char' property holds one of the property values listed below in
the
'kObjXPropSpecialEdit Object Property Values' section.
kObjXPropPreference = 4;
This 'Boolean property specifies that the object will be called
with its associated event kOnObjPrefEventID. THe object handles
this event by running a custom preferences dialog.
kObjectHasUIOverrideID= 8;
This 'Boolean property specifies that the object will supply
widgets
that do not map to parameters. They can provide button widgets as
well
as static text using VSOInsertWidget and VSO AppendWidget. Button
widgets
also have the associated object event kOnObjectUIButtonHit. The
application
calls the object when the user presses the button.
}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\ 8 bit "Char' / 'Byte' //\\}
{ //\\ //\\}
{ //\\ PROPERTIY VALUES //\\}
{ //\\ //\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ kObjXPropEditGroup Object Property Values
kObjXPropEditGroupDefault = 0;
kObjXPropEditGroupProfile = 1;
kObjXPropEditGroupPath = 2;
kObjXPropEditGroupCustom = 3;}
{ kObjXPropSpecialEdit Object Property Values
kDefaultSpecialEdit = 0;
kCustomSpecialEdit = 1;
kPropertiesSpecialEdit = 2;
kReshapeSpecialEdit = 3;}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\ Object Definition Procedure //\\}
{ //\\ //\\}
{ //\\ EVENT IDs //\\}
{ //\\ //\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{
kResetEventID= 3;
The state of the object has changed and the application
calls the script to regenerate itself. The application has set
the VectorScript environment so all objects creation goes into
the object container with appropriate defaults.
kOnObjPrefEventID= 4;
The object is being inserted in a drawing for the first time
or the preferences button has been pressed in the objects
insertion
tool. Objects with the kObjXPropPreference property set use
this event to supply a custom dialog to edit object defaults.
kObjOnInitXProperties= 5;
kOnInitPropertiesEventID= 5; an earlier naming of the above -- needs
to be removed
The Application needs to know what extended properties are
present
for this object. It calls the script with a kObjOnInitXProperties
so the script can supply these properties.
kObjOnSpecialEditID= 7;
Objects that have specified a kObjXPropSpecialEdit property value
of kCustomSpecialEdit are called by the application when the user
invokes the Special Edit command from the context menu or from a
cursor tool double-click.
kOnObjectUIButtonHit= 35;
Objects that have specified a kObjectHasUIOverrideID property and
have added a button widget are called with this event when the
user
presses the specified button. Scripts use the eventData and the
script supplied mappingID to distinguish between multiple
buttons.
Buttons should be used to edit object properties NOT to execute a
command.
For example, an object should not supply a button that operates on
any
property that does not belong to this object instance.
}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\ kObjectHasUIOverrideID //\\}
{ //\\ //\\}
{ //\\ Widgets Constants //\\}
{ //\\ //\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{
kFieldLongInt= 1;
kFieldBoolean= 2;
kFieldReal= 3;
kFieldText= 4;
kFieldCalculation= 5;
kFieldHandle = 6;
kFieldCoordDisp= 7; dimension
kFieldPopUp= 8;
kFieldRadio= 9;
kFieldCoordLocX= 10;
kFieldCoordLocY= 11;
kWidgetButton= 12;
kWidgetStaticText= 13;
kWidgetDisclosure= 14; not implemented?}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\ //\\}
{ //\\ Extended Object Properties //\\}
{ //\\ //\\}
{ //\\ Drop-in APIs //\\}
{ //\\ //\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{
SetObjPropVS(propertyID: LONGINT;
propertyVal: BOOLEAN)
: BOOLEAN;
SetObjPropVS is called from the kObjOnInitXProperties event handling
code to
supply boolean properties.
SetObjPropCharVS(propertyID: LONGINT;
propertyVal: CHAR)
: BOOLEAN;
SetObjPropCharVS is called from the kObjOnInitXProperties event
handling code to
supply 8 bit Char/Byte properties.
VSOGetEventInfo(VAR outObjEvent: LONGINT; // the current event
VAR outEventData: LONGINT);// the current event data
Event handling scripts always call VSOGetEventInfo to get the current
event.
VSOAppendWidget(widgetType: LONGINT; // kWidgetButton or
kStaticText
mappingID: LONGINT; // script supplied ID returned supplied with
text: STRING; // The text of the widget
data: LONGINT) // unused
: BOOLEAN;
Objects that have set the kObjectHasUIOverrideID property call
VSOAppendWidget to
add specified widget to the current widget list.
VSOInsertWidget(paramID: LONGINT; // the index of the parameter after
this widget
widgetType: LONGINT; // kWidgetButton or kStaticText
mappingID: LONGINT; // object supplied ID returned supplied with
// kOnObjectUIButtonHit
text: STRING; // The text of the widget
data: LONGINT) // unused
: BOOLEAN;
Objects that have set the kObjectHasUIOverrideID property call
VSOInsertWidget
to specify a widget in the shape pane and properties dialog. See the
Widgets Constants
above for suppoerted widgetType. The Mapping Id is returned in the
outEventData
parameter of VSOGetEventInfo during kOnObjectUIButtonHit events.
VSOInsertAllParams() : BOOLEAN;
Objects that have set the kObjectHasUIOverrideID property call
VSOInsertAllParams
to insert all the parameter widgets defined FOR the OBJECT.}
Procedure EventEnabledObject;
Const
kOnInitPropertiesEventID = 5 ;
kOnObjPrefEventID= 4 ;
kWidgetButton = 12 ;
kObjectHasUIOverrideID = 8 ;
kResetEventID = 3 ;
kOnObjectUIButtonHit = 35 ;
Var
theEvent, theButton : Longint ;
objHand, recHand, wallHand : Handle ;
objName, saveClass, noneClass : String ;
fillPattern :integer;
cnt : Integer ;
int : Integer ;
boo : Boolean ;
str : String ;
Procedure dialog1_Main( Var fillPattern : Integer ) ;
Var
dialog1 : Integer ;
imagePopup4Int : Integer ;
Procedure LoadPatterns( dialogID , controlID : Longint ) ;
Var
garbInt : Integer ;
Begin
If GetObject('System: Pattern Previews') = nil Then Begin
NameObject('System: Pattern Previews');
BeginFolder;
EndFolder;
End ;
If GetObject('Pattern-00') = nil Then Begin
BeginSym(Concat('Pattern-00', str));
Rect(0, 0, 10, 10); SetFPat(LNewObj, 0); SetLW(LNewObj, 1);
SetPenFore(LNewObj, 0, 0, 0);
MoveTo(0, 0); LineTo(10, 10); SetLW(LNewObj, 1); SetPenFore(LNewObj,
0, 0, 0);
MoveTo(10, 0); LineTo(0, 10); SetLW(LNewObj, 1); SetPenFore(LNewObj,
0, 0, 0);
EndSym;
InsertSymbolInFolder(GetObject('System: Pattern Previews'),
GetObject('Pattern-00'));
For cnt := 1 to 71 Do Begin
str := Num2Str(0, cnt);
If Len(str) = 1 Then str := Concat('0', str);
BeginSym(Concat('Pattern-', str));
Rect(0, 0, 10, 10);
SetFPat(LNewObj, cnt);
SetLW(LNewObj, 1);
SetPenFore(LNewObj, 0, 0, 0);
EndSym;
InsertSymbolInFolder(GetObject('System: Pattern Previews'),
GetObject(Concat('Pattern-', str)));
End ;
End ;
RemoveAllImagePopupItems(dialogID, controlID);
For cnt := 0 to 71 Do Begin
str := Num2Str(0, cnt);
If Len(str) = 1 Then str := Concat('0', str);
garbInt := InsertImagePopupObjectItem(dialogID, controlID,
Concat('Pattern-', str));
End ;
SetImagePopupSelectedItem(dialogID, controlID, 1);
End ;
Procedure dialog1_Handler( Var item : Longint ; data : Longint )
;
Begin
Case item of
SetupDialogC :
Begin
LoadPatterns(dialog1, 4);
SetImagePopupSelectedItem(dialog1, 4, fillPattern + 1);
End ;
1: Begin
imagePopup4Int := GetImagePopupSelectedItem(dialog1, 4);
End ;
End ;
End ;
Begin
dialog1 := CreateLayout('Select A Pattern', FALSE, 'OK', '');
CreateControl(dialog1, 4, 10, '', 0);
SetFirstLayoutItem(dialog1, 4);
If RunLayoutDialog(dialog1, dialog1_Handler) = 1 Then fillPattern :=
imagePopup4Int - 1;
End ;
Procedure ResetEventHandler;
Begin
Rect(0, 0, 1, 1);
SetFPat(LNewObj, pPattern_Number);
End ;
{=================Main===================}
Begin
vsoGetEventInfo(theEvent, theButton);
Message( 'theEvent= ' , theEvent , ' theButton= ' , theButton ) ;
Case theEvent of
kOnInitPropertiesEventID:
Begin
boo := SetObjPropVS(kObjectHasUIOverrideID, TRUE);
boo := vsoInsertAllParams;
boo := vsoAppendWidget(kWidgetButton, 1, 'Select Pattern...', 1);
boo := vsoAppendWidget(kWidgetButton, 2, 'Add...', 1);
End ;
kOnObjectUIButtonHit:
Begin
Case theButton of
1 : Begin
boo := GetCustomObjectInfo(objName, objHand, recHand, wallHand);
fillPattern := Str2Num(GetRField(objHand, objName, 'Pattern
Number'));
dialog1_Main(fillPattern);
SetRField(objHand, objName, 'Pattern Number', Num2Str(0,
fillPattern));
ResetObject(objHand);
End ;
2 :Begin
End ;
End ;
End ;
kResetEventID:
Begin
ResetEventHandler;
End ;
End ;
End ;
Run(EventEnabledObject);
下のprocedureでグループ図形を触ると、グループ内の図形の面の色が変わってしまいます。
このままでは危なくて使えません。
グループの属性を変えると、その中の全ての図形の属性も変わってしまうのですね。
いままで、グループ内の個々の図形にアクセスしないといけないと思ってました。
メニューで線種を選択して、線種番号を返すprocedureです。
メニュー外の図形でも選択できてしまいますが、ハンドルをチェックして、
選択しないように修正可能です。
procedure Test_LineStyle;
var
_lnStyle_:integer;
_
procedure GetLineStyle(var lS:integer);
{ メニューで線種を選択して、線種番号を返します。 }
{
注意:環境設定の「VectorScriptの警告を表示」を強制的にOFFにしています。
}
const
_LineLength = 150;
_Pitch = 16;
_FlipCol = 18;
var
_hL, hR_:array[-32..2] of handle;
_h, h0_:handle;
_i_:integer;
_xc, yc, zoom_:real;
_x0, y0, lnLen_:real;
_showLnWt_:boolean;{ 拡大時に線の太さを表示 }
_x, y, k_:real;
_minLnStyle_:integer;{ 線種番号の下限 }
_lnStyle_:integer;{ デフォルトの線種 }
_r, g, b_:real;
_ff, fb_:integer;
_
_function Set_k:real;{ 描画倍率を計算します。 }
_var
__scale, upi_:real;
__fraction, display_:longint;
__format_:integer;
__name, squareName_:string;
_begin
__scale:= GetLScale(ActLayer);
__GetUnits(fraction, display, format, upi, name, squareName);
__Set_k:= upi * scale / 25.4 / 72 * 25.4;
_end;{Set_k}
begin{GetLineStyle}
_SetPref(21, false);
_lnStyle:= FPenPat;
_i:= 0;
_repeat{ 線種の数(線種番号の下限)を調査します。 }
__i:= i - 1;
__PenPat(i);
_until FndError;
_minLnStyle:= i + 1;
_showLnWt:= GetPref(9);
_SetPref(9, false);
_GetVCenter(xc, yc);
_zoom:= GetZoom;
_SetZoom(100);
_k:= Set_k;
_lnLen:= k * LineLength;
_x0:= xc - lnLen/2;
_y0:= yc - k*minLnStyle*Pitch/2;
_y:= y0;
_for i:= 2 downto minLnStyle do begin{ メニュー項目描画ループ }
__if (i = 2) | (i < 0)then begin
___PenPat(i);
___Rect(x0-k*Pitch, y+k*Pitch/2, x0+lnLen+k*Pitch,
y-k*Pitch/2);
___hR[i]:= LNewObj;
___SetDSelect(hR[i]);
___SetFPat(hR[i], 2);
___SetLW(hR[i], 0);
___SetFillFore(hR[i], 0);
___MoveTo(x0, y); LineTo(x0 + lnLen, y);
___hL[i]:= LNewObj;
___SetDSelect(hL[i]);
___y:= y - k*Pitch;
__end;{if}
_end;{for}
_PenPat(2);
_Rect(x0-k*Pitch, y0+k*Pitch/2, x0+lnLen+k*Pitch,
y0-k*Pitch*(1/2-minLnStyle));{ メニュー枠 }
_hL[0]:= LNewObj;
_SetFPat(hL[0], 0);
_SetFillFore(hL[0], 0);
_SetDSelect(hL[0]);
_ReDrawAll;
_h0:= nil;
_ff:= 0;
_fb:= 0;
_while not MouseDown(x, y) do begin{ メニュー項目選択ループ }
__GetMouse(x, y);
__h:= PickObject(x, y);
__for i:= 2 downto minLnStyle do
___if (h <> nil) & (h = hL[i]) then
____h:= hR[i];
__if h <> h0 then begin
___if h0 <> nil then begin
____SetFillFore(h0, ff);
____SetFillBack(h0, fb);
___end;{if}
___GetFillFore(h, r, g, b);
___RGBToColorIndex(r, g, b, ff);
___GetFillBack(h, r, g, b);
___RGBToColorIndex(r, g, b, fb);
___SetFillFore(h, FlipCol);
___SetFillBack(h, FlipCol);
___h0:= h;
___ReDrawAll;
__end;{if}
_end;{while}
_SetFillFore(h0, ff);
_SetFillBack(h0, fb);
_if h = nil then begin
__lS:= 2;
_end{if}
_else begin
__lS:= GetLS(h);
_end;{else}
_for i:= -32 to 2 do begin{ メニュー項目削除ループ }
__if hL[i] <> nil then
___DelObject(hL[i]);
__if hR[i] <> nil then
___DelObject(hR[i]);
_end;{for}
_SetZoom(zoom);
_SetPref(9, showLnWt);
_PenPat(lnStyle);
_ReDraw;
end;{GetLineStyle}
begin{main}
_GetLineStyle(lnStyle);
_Message('LineStyle= ', lnStyle);
end;
Run(Test_LineStyle);
石男さん、要望します、お願いします、披露してくださいませ。m(_._)m
(急ぎませんので、HiBaseが終わってからでかまいませんよ。)
VS Language Guide(11) の第10章の Setting Script Execution Options
の、
With Script-Specified Events
項目が関係ありとみましたが、間違ってますか?
そこから先へは進めませんでしたが。
>ちょっと変えれば色番号や線種を選択するサブルーチンも出来そうです。
ちょっと変えれば模様番号や線種を選択するサブルーチンも出来そうです。
の間違いでした。
白黒表示やカラーレイヤ表示のときは色が判りませんが、一時的にカラー表示に変更すれば、
大丈夫でしょう。
あと、線種を表示するときは、「拡大時に線の太さを表示」させないとか。
与太郎さん
厳密に言えば10.5からいけるはずなんですが、どうも駄目でした。で私的に確認したの
は11ということで...。
そう!バリバリの英語です。要望があればここに出しますが...。
とりあえず使う予定はないんですが、色を選択するprocedureを作ってみました。
procedure GetColIndex がそれです。
ちょっと変えれば色番号や線種を選択するサブルーチンも出来そうです。
procedure Test_ColorPalett;
var
_col_:integer;
procedure GetColIndex(var iCol:integer);
{ カラーパレットを表示して、色番号を返します。 }
{ キャンセル(範囲外)なら-1を返します。 }
const
_BlockSize = 18;
var
_zoom, xc, yc_:real;
_k, kB, kS_:real;
_x, y, x0, y0_:real;
_i, j_:integer;
_h _:handle;
_hB_:array[0..15, 0..15] of handle;
_r, g, b_:real;
_
_function Set_k:real;{ 描画倍率を計算します。 }
_var
__scale, upi_:real;
__fraction, display_:longint;
__format_:integer;
__name, squareName_:string;
__result_:real;
_begin
__scale:= GetLScale(ActLayer);
__GetUnits(fraction, display, format, upi, name, squareName);
__Set_k:= upi * scale / 25.4 / 72 * 25.4;
_end;{Set_k}
_
_function LocToColIndex(iX, iY:integer):integer;
_var
__result_:integer;
__i_:integer;
_begin
__i:= 16 * iY + iX;
__case i of
___1: result:= 255;
___17: result:= 254;
___22: result:= 247;
___23: result:= 252;
___25: result:= 253;
___29: result:= 249;
___34: result:= 251;
___37: result:= 246;
___43: result:= 250;
___45: result:= 245;
___47: result:= 248;
___245: result:= 45;
___246: result:= 37;
___247: result:= 22;
___248: result:= 47;
___249: result:= 29;
___250: result:= 43;
___251: result:= 34;
___252: result:= 23;
___253: result:= 25;
___254: result:= 17;
___255: result:= 1;
___otherwise result:= i;
__end;{case}
__LocToColIndex:= result;
_end;{LocToColIndex}
_
begin{GetColIndex}
_k:= Set_k;
_GetVCenter(xc, yc);
_zoom:= GetZoom;
_kB:= k * BlockSize * 100 / zoom;
_kS:= kB / 6;
_x0:= xc - 8 * kB;
_y0:= yc + 8 * kB;
_for j:= 0 to 15 do begin
__for i:= 0 to 15 do begin
___Rect(x0+i*kB+kS, y0-j*kB-kS, x0+(i+1)*kB-kS,
y0-(j+1)*kB+kS);
___hB[i, j]:= LNewObj;
___SetDSelect(hB[i, j]);
___SetFPat(hB[i, j], 2);
___SetFillFore(hB[i, j], LocToColIndex(i, j));
__end;{for}
_end;{for}
_ReDraw;
_i:= -1; j:= -1;
_GetPt(x, y);
_h:=PickObject(x, y);
_if h = nil then begin
__iCol:= -1;
_end{if}
_else begin
__GetFillFore(h, r, g, b);
__RGBToColorIndex(r, g, b, iCol);
_end;{else}
_for j:= 0 to 15 do
__for i:= 0 to 15 do
___DelObject(hB[i, j]);
end;{GetColIndex}
begin{main}
_GetColIndex(col);
_Message(col);
end;
Run(Test_ColorPalett);
>石男さん
英語ですか〜、VW11ですか〜(泣き)。
やっぱりバージョンアップするべきか。
バグが出尽くすまで待ってみようかと思ってましたが、
これって、早めにバージョンアップor新規購入した人にテストしていただいているということですよね。
>ポイント型のPIOにプッシュボタンを付ける
ネメチェックのVSマニュアルを読むとPIOにイベントが付けられます。実際には11か
らの機能ですが、これを使ってPIOのデータパレットにプッシュボタンが付けられす。
普通、PIOにはダイアログが付けられませんが、プッシュボタンに仕込むことが出来ま
す。後はSetRFieldを使ってダイアログからの贈り物をセットしていくだけです。
でも、サンプルはネメチェックのVS_MLの過去のログに埋没しています。当然ながら
全て英文で書かれています。
石男さん、
>与太郎さんのつっこみにはたじたじです...。
ほっとくと段々増長してきますが、注意していただけたら静かになると思います。
>ポイント型のPIOにプッシュボタンを付ける
イメージできませんでした。
オブジェクトにボタンが付いてるのですか?
ボタンを押したらイベントを送れるのですか?
どうやってイベントを受け取るのですか?
勉強会が終わって暇が出来たら、教えてくださいな。
って、ぜんぜん静かになってませんねえ。
最近、Contorol
Pointというもパラメータのを発見(見逃してただけ)したので、1点、2点、3点型
のPIOでも制御点を増やせることがわかって喜んでおります。2Dパスでやると、変形時に余計な線が
表示されて見苦しいし、文字を自分で回転させないといけないので、ちょっと悩んでおりました。
Contorol
Pointはデータパレットで表示されなくても困らないので、パラメータの下のほうにして
おけばデータパレットの表示領域を圧迫しないのもいいですね。
PIOのパラメータをプラグインの中で書き換える必要があって、バックナンバーを読んでみましたが、
ソースがなかったので,わかりにくかったです。レコードハンドルと図形ハンドルを混同して、一時
間ほど原因を探してしまいました。
ポップアップ型のパラメータで、リストにないサイズをダイアログで入力するルーチンです。
「直接入力...」の項目を選択すると、ダイアログが出るというものです。値が「直接入力...」のま
まだとオブジェクトを変更するたびにダイアログが出るので、書き換える必要がありました。
与太郎さんのつっこみにはたじたじです...。
HiBaseに関しては、マニュアルにある通りの使い方しかわかりません。したがって、現
状では使いにくいものかもしれません...。それでも、発表されてから石男はずーっと
使い続けています。もっと反応があれば善処してくれるはずです...。
その代わりと言ってはなんですが、モダンダイアログ(カスタム)で条件に応じて
アイテムを作りだす技?やポイント型のPIOにプッシュボタンを付けることなどなら、ご希望にお答えできると思います...。
D-Dayまで10日ですね。
外部データベースの使い道、わかりません。(そういう仕事もないし)
でも、興味があるので、(東京クラブの勉強会だけど、)ここで発表していただけたらいいなあ。
あるいは、「From A&A」とかでね。
標準Pascalの IN [ ] ていうのは [
]内は整数型だから、(R IN
['レコード'])のように文字列型が許される
のは変なんですが、内部的にはレコードのインデックス番号みたいなので処理してるのかなと思ってました。
でも違ってました。
実際は、スクリプトを実行するときに検索条件の (
)内の式をインタープリタで処理してるのですね。
よく考えれば、実行してみないとレコードの番号は特定できませんから、当然です。
VW8でインタープリタ方式から(Javaみたいに中間コードを生成する)コンパイラ方式に変更になったけど、
検索条件を評価する部分はインタープリタのままということのようです。
そのこと自体は悪くないんだけど、(R IN [
])というのが、Pascalの集合型と同じ表現だし、
レイヤーの場合は(L=layerName)と、変数でも指定できるので、勘違いしてしまいました。
ところで、レコード名に「'」が含まれてると、スクリプトで厄介なことになりそうです。
>ところで、もしかして、これってHiBaseに関係あります?
かなり、関係があります...。
恐縮です。書き直しですか〜。
思い出すのに半日も掛かかるなんて、カセットテープから(300ボーくらいで)データを読んでるような遅さでした。
ところで、もしかして、これってHiBaseに関係あります?
いや、本当に済みません、与太郎さん。
今、総当たりのScriptを書き終わったところでした...。
もう一度、参考にして書き直します...、与太郎さん。
検索条件を文字列にすれば良かったのを思い出しました。
procedure test1;
const
Rec1 = 'Record-1';
Rec2 = 'Record-2';
SQ = Chr(39);
var
criteria:string;
begin
criteria:= Concat('(R IN [', SQ, Rec1, SQ, ', ', SQ, Rec2, SQ,
'])');
Message(Count(criteria), ' : ', criteria);
end;
Run(test1);
procedure test2;
const
Rec1 = '''Record-1''';
Rec2 = '''Record-2''';
var
criteria:string;
begin
criteria:= Concat('(R IN [', Rec1, ', ',Rec2, '])');
Message(Count(criteria), ' : ', criteria);
end;
Run(test2);
どちらも同じ結果になります。
>図形タイプに47、48とにレコードが定義されているのが不思議です...。
Type47---レコード定義。シンボルフォルダにリンクされてます。
たぶん、シンボル定義と同じ方法でハンドルを取ります。
Type48---レコード。図形にリンクされてます。GetRecord(objHandle,
index)でハンドルを取ります。
いつも、どうもすみません、与太郎さん。
やはり、検索条件に直接レコード名をいれないといけないんですね。
別な手でNameListからやってみましたが、やはりレコードのハンドルは返ってきません
でした...。当然と言えば当然でしたが、そうなるとベタな総当たりで順を追ってやる
方法しかないようですね...。しかし、図形タイプに47、48とにレコードが定義されて
いるのが不思議です...。
[ ]内に直接レコード名を入れないとダメみたいです。
procedure test1;
const
Rec1 = 'Record-1';
Rec2 = 'Record-2';
begin
Message(Count((R IN [Rec1, Rec2])));
end;
Run(test1);
procedure test2;
var
rec1, rec2:string;
begin
rec1:= 'Record-1';
rec2:= 'Record-2';
Message(Count((R IN [rec1, rec2])));
end;
Run(test2);
残念ながら、test1、test2共にコンパイルされますが、カウントされませんでした。
(VW10/Winデモ版にて)
石男さん、
レコードの種類が多いとたいへんですが、
i:= Count(R IN ['Record-1','Record-2']);
でカウント出来ます。
'Record-1'か'Record-2'のどちらかでも付いてればカウントされます。
レコード付き図形の数をカウントしようと思って...
i := Count( T = 47 ) ;もしくは T = 48でやってみたところ
「0」しか返ってきません。当然、レコード付き図形はばらまいています。
やはり、図形のハンドルを取ってからレコードの有無を確認するしかないのでしょうか
与太郎さんご親切にありがとうございます。
>うっかり「コマンド+D」を押したり、複製したのに移動するのを忘れたり、3D図形を2D化して、
>図形が重なってしまうのはよくあることです。ワークシートで集計したりするときには、致命的です。
>「不要情報を除去...」に、「重複図形を削除」のオプションがあると助かるのですがね。
同感です。これがあることでどれだけ仕事が短縮されることか。心置きなくワークシートを使える環境が
整うことを願っています。
>Script談話室のバックナンバーに「重複図形を削除」について、一連のやりとりがあります。
拝見しましたが難しすぎてチンプンカンプンです。やはりスクリプトのハードルは高いですね。
(重複グループ図形を削除するスクリプト)で少しずつ勉強してみます。
>シンボルを並べて配列のパターンをグループ化していたので
普通、グループでなくてシンボルを並べますよね(でないと修正がたいへん)。一応、シンボル版も作ってみまし
たが、グループ版だけ書き込みました。GROUP→SYMBOL
の変更は直感でわかりましたか?
>数百個単位の図形なら同じ図形の重複は下のスクリプトのタイプの部分を変えることでほぼ対応出来る
>のでしょうか?
下のスクリプトは図形のBoundRectを比較しているだけなので、限定された条件でしか正しく動きません。(基本
的に図形が重なることはない、属性を無視できること)
厳密には、直線なら端点同士、多角形なら頂点全部を比較するなど、図形タイプによって、処理の仕方を変えない
といけません。2D図形だと、下のようになります。
基準点----X,Y座標
直線------端点の座標
四角形----BoundRect
多角形----とりあえずBoundRect、そのあと各頂点座標、開/閉
曲線------とりあえずBoundRect、そのあと各頂点座標/タイプ、開/閉、各辺の表示/非表示
円弧------中心座標、半径、開始角、円弧角
円--------中心座標、半径
シンボル--シンボル名、挿入点座標、回転角
グループ--とりあえずBoundRect、そのあと中の図形ごとに比較
文字------基点の座標、角度、反転、文字、フォント,サイズ,スタイル
寸法------基準点座標、オフセット、その他
全ての図形---属性(クラス、線/面の色、パターン、線種、マーカー)、ロック状態
また、図形に名前、レコードが設定されていれば、それも考慮しないといけません。(名前が付いていたら削除し
ないとか、レコードの内容が同じなら削除するとか)
きちんとやると(量的に)たいへんです。
>タイプによってデータが壊れるようなことはないのですか。
きちんと比較しないと、実際には重複していない図形を削除してしまう恐れがあります。
うっかり「コマンド+D」を押したり、複製したのに移動するのを忘れたり、3D図形を2D化して、図形が重なっ
てしまうのはよくあることです。ワークシートで集計したりするときには、致命的です。「不要情報を除去...」に、
「重複図形を削除」のオプションがあると助かるのですがね。
Script談話室のバックナンバーに「重複図形を削除」について、一連のやりとりがあります。
与太郎さんありがとうございます。
説明不足でした。シンボルを並べて配列のパターンをグループ化していたので全て並べた後グループ
を解除することでグループの重複ではなくシンボルが重複していました。
そこで下のスクリプトの(T=GROUP)の部分を(T=SYMBOL)してみたらうまく消えてくれました。
数百個単位の図形なら同じ図形の重複は下のスクリプトのタイプの部分を変えることでほぼ対応出来る
のでしょうか?タイプによってデータが壊れるようなことはないのですか。スクリプトは全然わからず
メニューツールの選択/表示マクロ位しか使っていないのでよくわかりません。
VectorWorks 談話室より
>>