Использование PascalScript совместно с GLScene (написал Снег Север). В этой статье объясняется, как использовать PascalScript совместно с GLScene. Это можно делать разными способами. Самый простой, на мой взгляд – это создания своих классов-«оберток» над объектами GLScene. Именно этот способ я использую в следующих примерах. Создадим новый проект с необходимыми компонентами (glscript00). Затем добавим в проект новый модуль и создадим в нем свой класс: unit MyClassUnit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, GLMisc, GLScene, GLTexture, GLObjects, GLPolyhedron; type TMySceneClass = class protected FSceneObj :TGLCustomSceneObject; function GetSceneObj :TObject; public constructor Create(AParentname :string; AType :string); property SceneObj :TObject read GetSceneObj; procedure SetMaterial(matname :string); procedure SetPosition(x, y, z :single); procedure SetScale(factor :single); procedure Rotate(Axe :byte; Angle :single); end;
implementation uses MainUnit; constructor TMySceneClass.Create(AParentname :string; AType :string); var GraphObj : TGLBaseSceneObject; begin inherited Create; GraphObj := MainForm.GLScene1.FindSceneObject(AParentname); if UpperCase(AType)='TGLDUMMYCUBE' then begin FSceneObj := TGLDummyCube.CreateAsChild(GraphObj); FSceneObj.Name := 'MyDummyCube1'; end; if UpperCase(AType)='TGLCUBE' then begin FSceneObj := TGLCube.CreateAsChild(GraphObj); FSceneObj.Name := 'MyCube1'; end; if UpperCase(AType)='TGLSPHERE' then begin FSceneObj := TGLSphere.CreateAsChild(GraphObj); FSceneObj.Name := 'MySphere1'; end; if UpperCase(AType)='TGLICOSAHEDRON' then begin FSceneObj := TGLIcosahedron.CreateAsChild(GraphObj); FSceneObj.Name := 'MyLIcosahedron1'; end; FSceneObj.Material.MaterialLibrary := MainForm.GLMaterialLibrary1; end;
procedure TMySceneClass.SetMaterial(matname :string); begin FSceneObj.Material.LibMaterialName := matname; end;
procedure TMySceneClass.Rotate(Axe :byte; Angle :single); begin case Axe of 1: FSceneObj.Turn(Angle); 2: FSceneObj.Pitch(Angle); 3: FSceneObj.Turn(Angle); end; end;
procedure TMySceneClass.SetPosition(x, y, z :single); begin FSceneObj.Position.x := x; FSceneObj.Position.y := y; FSceneObj.Position.z := z; end;
procedure TMySceneClass.SetScale(factor :single); begin FSceneObj.Scale.Scale(factor); end;
function TMySceneClass.GetSceneObj :TObject; begin Result := FSceneObj; end; end.
Этот класс позволяет создать объект сцены, как потомка имеющегося объекта (для простоты предусмотрена возможность создавать только объекты типа TGLDummyCube, TGLCube, TGLSphere и TGLIcosahedron), назначить объектам материал из имеющейся библиотеки материалов GLMaterialLibrary1 и делать некоторые манипуляции с объектами – менять их позицию, масштабировать, вращать.
Теперь, сделаем модуль импорта для этого класса, как это описано в статье Использование классов с RemObjects PascalScript. Сгенерированный модуль uPSI_MyClassUnit.pas подключим к проекту и к списку плагинов компилятора PascalScript: procedure TMainForm.FormCreate(Sender: TObject); var Plugin :TPSPlugin; begin ... Plugin := TPSImport_MyClassUnit.Create(self); TPSPluginItem(ce.Plugins.Add).Plugin := Plugin; end;
Теперь напишем простой скрипт создания нового куба в сцене: program glscript00; var MySceneClass : TMySceneClass; begin MySceneClass := TMySceneClass.Create('GLDummyCube1','TGLCUBE'); MySceneClass.SetPosition(2,0,0); MySceneClass.SetScale(2); MySceneClass.SetMaterial('cube');
end. Запустим программу и выполним этот скрипт нажатием кнопки Do. На сцене появится цветной куб.
Разумеется, скрипты можно использовать не только для создания объектов сцены, но и для управления этими объектами. Немного доработаем проект (glscript01). В событие GLCadencer1Progress добавим код: procedure TMainForm.GLCadencer1Progress(Sender: TObject; const deltaTime, newTime: Double); begin if compiled then ce.ExecuteFunction([1, 90*deltaTime], 'RotateObject'); end; Функция RotateObject – это скриптовая процедура, которая будет принимать два параметра – номер оси вращения (1..3) и угол поворота. Разумеется, эту процедуру надо написать и включить в скрипт. Новый скрипт будет выглядеть так:
procedure RotateObject(a:integer; ang :single); begin MySceneClass .Rotate(a, ang); end; begin MySceneClass := TMySceneClass.Create('GLDummyCube1','TGLCUBE'); MySceneClass.SetPosition(2,0,0); MySceneClass.SetScale(2); MySceneClass.SetMaterial('cube'); end. Запустим программу и выполним этот скрипт нажатием кнопки Do. На сцене появится цветной куб. Включим вращение нажатием на элемент управления «Cadencer On/Off», рядом с кнопкой. Куб начнет вращаться.
Пример выполнения более сложного скрипта - glscript02. В нем создаются три объекта сцены и вращаются независимо: program glscript; var MySceneClass1, MySceneClass2, MySceneClass3 : TMySceneClass; procedure RotateObject(num, a :integer; ang :single); begin case num of 1: MySceneClass1.Rotate(a, ang); 2: MySceneClass2.Rotate(a, ang); 3: MySceneClass3.Rotate(a, ang); end end; begin MySceneClass1 := TMySceneClass.Create('GLDummyCube1','TGLCUBE'); MySceneClass1.SetPosition(1,0,0); MySceneClass1.SetScale(2); MySceneClass1.SetMaterial('cube');
MySceneClass2 := TMySceneClass.Create('MyCube1','TGLSphere'); MySceneClass2.SetPosition(0,3,0); MySceneClass2.SetScale(2); MySceneClass2.SetMaterial('sphere');
MySceneClass3 := TMySceneClass.Create('MySphere1','TGLIcosahedron'); MySceneClass3.SetPosition(0,0,2); MySceneClass3.SetScale(1); MySceneClass3.SetMaterial('icos'); end. Соответственно, в событии GLCadencer1Progress идут три вызова скриптовой функции: procedure TMainForm.GLCadencer1Progress(Sender: TObject; const deltaTime, newTime: Double); begin if compiled and executed then begin ce.ExecuteFunction([1, 1, 90*deltaTime], 'RotateObject'); ce.ExecuteFunction([2, 2, 90*deltaTime], 'RotateObject'); ce.ExecuteFunction([3, 3, 90*deltaTime], 'RotateObject'); end; end;
|