diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index 0e9bc1f43..5b109bb6a 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -15,7 +15,7 @@ internal static class RevisionClass public const string Major = "3"; public const string Minor = "6"; public const string Build = "3"; - public const string Revision = "2613"; + public const string Revision = "2614"; public const string MainVersion = Major + "." + Minor; public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; diff --git a/Configuration/Version.defs b/Configuration/Version.defs index 9c3d8e8a2..184a5d32b 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ -%MINOR%=6 -%REVISION%=2613 %COREVERSION%=3 +%REVISION%=2614 +%MINOR%=6 %MAJOR%=3 diff --git a/InstallerSamples/Algorithms/Sqrt2.pas b/InstallerSamples/Algorithms/Sqrt2.pas new file mode 100644 index 000000000..dde6bdf70 --- /dev/null +++ b/InstallerSamples/Algorithms/Sqrt2.pas @@ -0,0 +1,4 @@ +## +var x := 2.0; +SeqGen(6,x,a → (a + x/a) / 2).Last.Println; +x.Sqrt.Print; \ No newline at end of file diff --git a/InstallerSamples/Graphics/Controls/cc15_ListView.pas b/InstallerSamples/Graphics/Controls/cc15_ListView.pas index 490f2e1f2..739359d7d 100644 --- a/InstallerSamples/Graphics/Controls/cc15_ListView.pas +++ b/InstallerSamples/Graphics/Controls/cc15_ListView.pas @@ -1,8 +1,11 @@ // Модуль Controls - замена графического окна элементом "ListView" uses Controls,GraphWPF; -type My = auto class - Поле1,Поле2: integer; +type My = class +public + auto property Поле1: integer; + auto property Поле2: integer; + constructor (п1,п2: integer) := (Поле1,Поле2) := (п1,п2); end; begin diff --git a/InstallerSamples/Graphics/WPFObjects/Shooter.pas b/InstallerSamples/Graphics/WPFObjects/Shooter.pas index 885a58baf..288c1f804 100644 --- a/InstallerSamples/Graphics/WPFObjects/Shooter.pas +++ b/InstallerSamples/Graphics/WPFObjects/Shooter.pas @@ -26,7 +26,7 @@ begin var kl,kr,ku,kd: boolean; - BeginFrameBasedAnimationTime(dt->begin + OnDrawFrame := dt -> begin Window.Title := 'Количество объектов: '+Objects.Count; // Перемещение игрока if kr then @@ -53,7 +53,7 @@ begin // Конец игры end; - end); + end; CreateTimerAndStart(100,procedure -> // Таймер убивания монстров и умирания объектов за пределами экрана begin diff --git a/InstallerSamples/Graphics/WPFObjects/ShooterWithInterface.pas b/InstallerSamples/Graphics/WPFObjects/ShooterWithInterface.pas new file mode 100644 index 000000000..79d52bfee --- /dev/null +++ b/InstallerSamples/Graphics/WPFObjects/ShooterWithInterface.pas @@ -0,0 +1,197 @@ +uses WPFObjects, Timers, Controls; + +type + BulletWPF = class(CircleWPF) end; + MonsterWPF = class(SquareWPF) end; + PlayerWPF = class(EllipseWPF) end; + TGameState = (Paused, Started, EndOfGame); + +var + // Состояние игры + GameState: TGameState := Paused; + // Глобальные интерфейсные объекты + sb: StatusBarWPF; + bstart, bstop, bnewgame: ButtonWPF; + // Глобальные игровые объекты + Player: PlayerWPF; + // Клавиатура + kl, kr, ku, kd: boolean; + + +procedure InitGame; +begin + Player := new PlayerWPF(GraphWindow.Center, 30, 50, RandomColor); + Player.Velocity := 100; + Player.Number := 0; + + loop 10 do + begin + var m := new MonsterWPF(750, Random(10, 550), 30, RandomColor); + m.Velocity := 50; + end; +end; + +procedure NewGame; +begin + sb.Text := ''; + Objects.Clear; + InitGame; +end; + +// Конец игры - игрок погиб +procedure GameOver; +begin + sb.Text := 'Игрок погиб'; + GameState := EndOfGame; + bstart.Enabled := False; + bstop.Enabled := False; + bnewgame.Enabled := True; + Player.Color := Colors.Black; +end; + +// Конец игры - победа! +procedure GameOverWin; +begin + sb.Text := 'Победа!'; + GameState := EndOfGame; + bstart.Enabled := False; + bstop.Enabled := False; + bnewgame.Enabled := True; + Player.Color := Colors.Yellow; +end; + +procedure InitInterface; +begin + Window.SetSize(1000, 600); + LeftPanel(200, Colors.Orange); + bstart := Button('Start'); + bstop := Button('Stop'); + bnewgame := Button('Новая игра'); + bstop.Enabled := False; + bstart.Enabled := False; + bstart.Click := procedure → begin + GameState := Started; + bstart.Enabled := False; + bstop.Enabled := True; + end; + bstop.Click := procedure → begin + GameState := Paused; + bstart.Enabled := True; + bstop.Enabled := False; + end; + bNewGame.Click := procedure → begin + GameState := Started; + bnewgame.Enabled := False; + bstart.Enabled := False; + bstop.Enabled := True; + NewGame; + end; + sb := StatusBar; +end; + +// Обработчик таймера убивания монстров и умирания объектов за пределами экрана +procedure KillMonstersHandler; +begin + if GameState <> Started then + exit; + // Удалить пули, вылетевшие за экран + Objects.DestroyAll(o → o.OutOfGraphWindow and not (o is PlayerWPF)); + // Удалить монстра, убитого пулей, вместе с пулей + foreach var o in Objects do + begin + if o is BulletWPF then + foreach var x in o.IntersectionList do + if x is MonsterWPF then + begin + x.Destroy; + o.Destroy; + Player.Number += 1; + break; + end; + end; +end; + +// Обработчик перерисовки экрана +procedure DrawFrame(dt: real); +begin + if GameState <> Started then exit; + Window.Title := 'Количество объектов: ' + Objects.Count; + +// Перемещение игрока + if kr then + Player.Dx := 1 + else if kl then + Player.Dx := -1 + else Player.Dx := 0; + if ku then + Player.Dy := -1 + else if kd then + Player.Dy := 1 + else Player.Dy := 0; + +// Перемещение остальных объектов + foreach var o in Objects do // все перемещаются в своём направлении со своей скоростью + begin + if o is MonsterWPF then + o.Direction := (Player.Center.X - o.Center.X, Player.Center.Y - o.Center.Y); + o.MoveTime(dt); + end; + +// Проверка гибели игрока + if Player.IntersectionList.Any(o → o is MonsterWPF) then + GameOver; + +// Проверка выигрыша игрока + if Player.Number >= 10 then + GameOverWin; +end; + +/// Обработчик таймера рождения монстров +procedure CreateMonstersHandler; +begin + if GameState <> Started then exit; + var x := if Random(2) = 0 then 750 else 50; + var m := new MonsterWPF(x, Random(10, 550), 30, RandomColor); + m.Velocity := 50; +end; + +begin + InitInterface; + + CreateTimerAndStart(100, KillMonstersHandler); + CreateTimerAndStart(1000, CreateMonstersHandler); + +// Обработчик перерисовки кадров + OnDrawFrame := DrawFrame; + +// Обработчики мыши и клавиатуры + OnMouseMove := (x, y, mb) → begin + if GameState <> Started then exit; + Player.RotateToPoint(x, y); + end; + + OnMouseDown := (x, y, mb) → begin + if GameState <> Started then exit; + var cc := new BulletWPF(Player.CenterTop, 5, Colors.Red); + cc.Direction := (x - Player.Center.X, y - Player.Center.Y); + cc.Velocity := 300; + end; + + OnKeyDown := k → begin + case k of + Key.w, Key.Up: begin ku := true; kd := false; end; + Key.s, Key.Down: begin kd := true; ku := false; end; + Key.a, Key.Left: begin kl := true; kr := false; end; + Key.d, Key.Right: begin kr := true; kl := false end; + end; + end; + + OnKeyUp := k → begin + case k of + Key.w, Key.Up: ku := false; + Key.s, Key.Down: kd := false; + Key.a, Key.Left: kl := false; + Key.d, Key.Right: kr := false; + end; + end; +end. \ No newline at end of file diff --git a/Release/pabcversion.txt b/Release/pabcversion.txt index e7f533f4e..d4efad4a8 100644 --- a/Release/pabcversion.txt +++ b/Release/pabcversion.txt @@ -1 +1 @@ -3.6.3.2613 +3.6.3.2614 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index 0f3aeaacc..2f685c665 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.6.3.2613' +!define VERSION '3.6.3.2614' diff --git a/TestSuite/CompilationSamples/GraphWPF.pas b/TestSuite/CompilationSamples/GraphWPF.pas index 8aec0dc6b..5ef18198f 100644 --- a/TestSuite/CompilationSamples/GraphWPF.pas +++ b/TestSuite/CompilationSamples/GraphWPF.pas @@ -1924,6 +1924,9 @@ public host1 := new Canvas; host := new MyVisualHost(); + // Попытка отсекать рисование частей объектов за пределами host. Актуально при наличии панелей. + // К сожалению, почему-то при использовании WPFObjects объекты GraphWPF становятся не видны + // Выход - в WPFObjects host1.ClipToBounds := False host1.ClipToBounds := True; host1.SizeChanged += (s,e) -> begin @@ -1944,6 +1947,8 @@ public RTbmap := new RenderTargetBitmap(Round(SystemParameters.PrimaryScreenWidth * scalex), Round(SystemParameters.PrimaryScreenHeight * scaley), dpiX, dpiY, PixelFormats.Pbgra32); im.Source := RTbmap; + // Рисуем на host + // Когда накопится много объектов, переносим их на im host1.Children.Add(im); host1.Children.Add(host); diff --git a/TestSuite/CompilationSamples/GraphWPFBase.pas b/TestSuite/CompilationSamples/GraphWPFBase.pas index db3ccf4a1..a12488aef 100644 --- a/TestSuite/CompilationSamples/GraphWPFBase.pas +++ b/TestSuite/CompilationSamples/GraphWPFBase.pas @@ -123,7 +123,7 @@ type property IsFixedSize: boolean read GetFixedSize write SetFixedSize; /// Очищает графическое окно белым цветом procedure Clear; virtual; - /// Очищает графическое окно цветом c + /// Очищает графическое окно указанным цветом procedure Clear(c: GColor); virtual; /// Устанавливает размеры клиентской части главного окна procedure SetSize(w, h: real); diff --git a/TestSuite/CompilationSamples/Timers.pas b/TestSuite/CompilationSamples/Timers.pas index 033027f39..c1a0c03c0 100644 --- a/TestSuite/CompilationSamples/Timers.pas +++ b/TestSuite/CompilationSamples/Timers.pas @@ -38,6 +38,7 @@ type property TimerProc: ()->() read _procedure write _procedure; end; +/// Создать и запустить таймер, вызывающий процедуру TimerProc каждые ms миллисекунд function CreateTimerAndStart(ms: integer; TimerProc: procedure): Timer; implementation diff --git a/TestSuite/CompilationSamples/WPFObjects.pas b/TestSuite/CompilationSamples/WPFObjects.pas index f8d46bbfa..79e02f9e7 100644 --- a/TestSuite/CompilationSamples/WPFObjects.pas +++ b/TestSuite/CompilationSamples/WPFObjects.pas @@ -140,6 +140,12 @@ type begin Result := l.GetEnumerator; end; + /// Очистить список игровых объектов + procedure Clear; + begin + for var i:=Count-1 downto 0 do + Destroy(Items[i]); + end; end; @@ -1597,12 +1603,14 @@ begin GraphWindow := GraphWPF.GraphWindow; host := new Canvas(); + host.ClipToBounds := True; {host.SizeChanged += (s,e) -> begin var sz := e.NewSize; host.DataContext := sz; end;} var g := MainWindow.Content as DockPanel; + (g.children[0] as Canvas).ClipToBounds := False; // SSM 04/08/20 - возвращаем в False иначе графику GraphWPF становится не видно g.children.Add(host); // Слой графики WPF - последний end; app.Dispatcher.Invoke(AdditionalInit); diff --git a/TestSuite/CompilationSamples/graph3d.pas b/TestSuite/CompilationSamples/graph3d.pas index bc33b6b0a..9ab008773 100644 --- a/TestSuite/CompilationSamples/graph3d.pas +++ b/TestSuite/CompilationSamples/graph3d.pas @@ -2206,15 +2206,15 @@ type procedure SetN(n: integer); function GetN: integer; protected - function CreateObject: Object3D; override := new PrismT(X, Y, Z, N, Radius, Height, Material.Clone); + function CreateObject: Object3D; override := new PrismT(X, Y, Z, Sides, Radius, Height, Material.Clone); public constructor(x, y, z: real; N: integer; r, h: real; m: Gmaterial); /// Радиус правильной призмы property Radius: real read GetR write SetR; /// Высота правильной призмы property Height: real read GetH write SetH; -/// Количество углов правильной призмы - property N: integer read GetN write SetN; +/// Количество боковых граней правильной призмы + property Sides: integer read GetN write SetN; /// Возвращает клон правильной призмы function Clone := (inherited Clone) as PrismT; end; @@ -2226,15 +2226,15 @@ type PyramidT = class(PrismT) private protected - function CreateObject: Object3D; override := new PyramidT(X, Y, Z, N, Radius, Height, Material.Clone); + function CreateObject: Object3D; override := new PyramidT(X, Y, Z, Sides, Radius, Height, Material.Clone); public constructor(x, y, z: real; N: integer; r, h: real; m: GMaterial); /// Радиус правильной пирамиды property Radius: real read GetR write SetR; /// Высота правильной пирамиды property Height: real read GetH write SetH; -/// Количество углов правильной пирамиды - property N: integer read GetN write SetN; +/// Количество боковых граней правильной пирамиды + property Sides: integer read GetN write SetN; /// Возвращает клон правильной пирамиды function Clone := (inherited Clone) as PyramidT; end; @@ -2288,8 +2288,8 @@ type begin var pc := new Point3DCollection; - var a := PartitionPoints(0, 2 * Pi, N).Select(x -> P3D(fr * cos(x), fr * sin(x), 0)).ToArray; - var b := PartitionPoints(0, 2 * Pi, N).Select(x -> P3D(fr * cos(x), fr * sin(x), fh)).ToArray; + var a := PartitionPoints(0, 2 * Pi, Sides).Select(x -> P3D(fr * cos(x), fr * sin(x), 0)).ToArray; + var b := PartitionPoints(0, 2 * Pi, Sides).Select(x -> P3D(fr * cos(x), fr * sin(x), fh)).ToArray; for var i := 0 to a.High - 1 do begin pc.Add(a[i]); @@ -2320,12 +2320,12 @@ type end; protected - function CreateObject: Object3D; override := new PrismTWireframe(X, Y, Z, N, Radius, Height, (model as LinesVisual3D).Thickness, (model as LinesVisual3D).Color); + function CreateObject: Object3D; override := new PrismTWireframe(X, Y, Z, Sides, Radius, Height, (model as LinesVisual3D).Thickness, (model as LinesVisual3D).Color); public function Points: Point3DCollection; virtual; begin - var a := PartitionPoints(0, 2 * Pi, N).Select(x -> P3D(fr * cos(x), fr * sin(x), 0)).SkipLast; - var b := PartitionPoints(0, 2 * Pi, N).Select(x -> P3D(fr * cos(x), fr * sin(x), fh)).SkipLast; + var a := PartitionPoints(0, 2 * Pi, Sides).Select(x -> P3D(fr * cos(x), fr * sin(x), 0)).SkipLast; + var b := PartitionPoints(0, 2 * Pi, Sides).Select(x -> P3D(fr * cos(x), fr * sin(x), fh)).SkipLast; var pc := new Point3DCollection(a + b); Result := pc; @@ -2338,8 +2338,8 @@ type property Radius: real read fr write SetR; /// Высота проволочной правильной призмы property Height: real read fh write SetH; -/// Количество углов проволочной правильной призмы - property N: integer read fn write SetN; +/// Количество боковых граней проволочной правильной призмы + property Sides: integer read fn write SetN; /// Цвет проволоки правильной призмы property Color: GColor read GetC write SetC; override; /// Толщина проволоки правильной призмы @@ -2352,13 +2352,13 @@ type /// Класс проволочной правильной пирамиды PyramidTWireframe = class(PrismTWireframe) protected - function CreateObject: Object3D; override := new PyramidTWireframe(X, Y, Z, N, Radius, Height, (model as LinesVisual3D).Thickness, (model as LinesVisual3D).Color); + function CreateObject: Object3D; override := new PyramidTWireframe(X, Y, Z, Sides, Radius, Height, (model as LinesVisual3D).Thickness, (model as LinesVisual3D).Color); private function CreatePoints: Point3DCollection; override; begin var pc := new Point3DCollection; - var a := PartitionPoints(0, 2 * Pi, N).Select(x -> P3D(fr * cos(x), fr * sin(x), 0)).ToArray; + var a := PartitionPoints(0, 2 * Pi, Sides).Select(x -> P3D(fr * cos(x), fr * sin(x), 0)).ToArray; var b := P3D(0, 0, fh); for var i := 0 to a.High - 1 do begin @@ -2377,8 +2377,8 @@ type property Radius: real read fr write SetR; /// Высота проволочной правильной пирамиды property Height: real read fh write SetH; -/// Количество углов проволочной правильной пирамиды - property N: integer read fn write SetN; +/// Количество боковых граней проволочной правильной пирамиды + property Sides: integer read fn write SetN; /// Цвет проволоки правильной пирамиды property Color: GColor read GetC write SetC; override; /// Толщина проволоки правильной пирамиды @@ -3373,15 +3373,15 @@ function FileModel3D(p: Point3D; fname: string; m: Material): FileModelT := File function Prism(x, y, z: real; Sides: integer; Height, Radius: real; m: Material): PrismT := Inv(()->PrismT.Create(x, y, z, Sides, Radius, Height, m)); -function Prism(p: Point3D; Sides: integer; Height, Radius: real; m: Material): PrismT := Prism(p.X, p.Y, p.Z, Sides, Radius, Height, m); +function Prism(p: Point3D; Sides: integer; Height, Radius: real; m: Material): PrismT := Prism(p.X, p.Y, p.Z, Sides, Height, Radius, m); function PrismWireFrame(x, y, z: real; Sides: integer; Height, Radius: real; Thickness: real; c: Color): PrismTWireFrame := Inv(()->PrismTWireFrame.Create(x, y, z, Sides, Radius, Height, thickness, c)); -function PrismWireFrame(p: Point3D; Sides: integer; Height, Radius: real; Thickness: real; c: Color): PrismTWireFrame := PrismWireFrame(p.x, p.y, p.z, Sides, Radius, Height, thickness, c); +function PrismWireFrame(p: Point3D; Sides: integer; Height, Radius: real; Thickness: real; c: Color): PrismTWireFrame := PrismWireFrame(p.x, p.y, p.z, Sides, Height, Radius, thickness, c); function Pyramid(x, y, z: real; Sides: integer; Height, Radius: real; m: Material): PyramidT := Inv(()->PyramidT.Create(x, y, z, Sides, Radius, Height, m)); -function Pyramid(p: Point3D; Sides: integer; Height, Radius: real; m: Material): PyramidT := Pyramid(p.X, p.Y, p.Z, Sides, Radius, Height, m); +function Pyramid(p: Point3D; Sides: integer; Height, Radius: real; m: Material): PyramidT := Pyramid(p.X, p.Y, p.Z, Sides, Height, Radius, m); function PyramidWireFrame(x, y, z: real; Sides: integer; Height, Radius: real; Thickness: real; c: Color): PyramidTWireFrame := Inv(()->PyramidTWireFrame.Create(x, y, z, Sides, Radius, Height, thickness, c)); diff --git a/bin/Lib/GraphWPF.pas b/bin/Lib/GraphWPF.pas index 2b3470104..c3d28ef2f 100644 --- a/bin/Lib/GraphWPF.pas +++ b/bin/Lib/GraphWPF.pas @@ -1924,6 +1924,9 @@ public host1 := new Canvas; host := new MyVisualHost(); + // Попытка отсекать рисование частей объектов за пределами host. Актуально при наличии панелей. + // К сожалению, почему-то при использовании WPFObjects объекты GraphWPF становятся не видны + // Выход - в WPFObjects host1.ClipToBounds := False host1.ClipToBounds := True; host1.SizeChanged += (s,e) -> begin @@ -1944,6 +1947,8 @@ public RTbmap := new RenderTargetBitmap(Round(SystemParameters.PrimaryScreenWidth * scalex), Round(SystemParameters.PrimaryScreenHeight * scaley), dpiX, dpiY, PixelFormats.Pbgra32); im.Source := RTbmap; + // Рисуем на host + // Когда накопится много объектов, переносим их на im host1.Children.Add(im); host1.Children.Add(host); diff --git a/bin/Lib/GraphWPFBase.pas b/bin/Lib/GraphWPFBase.pas index db3ccf4a1..a12488aef 100644 --- a/bin/Lib/GraphWPFBase.pas +++ b/bin/Lib/GraphWPFBase.pas @@ -123,7 +123,7 @@ type property IsFixedSize: boolean read GetFixedSize write SetFixedSize; /// Очищает графическое окно белым цветом procedure Clear; virtual; - /// Очищает графическое окно цветом c + /// Очищает графическое окно указанным цветом procedure Clear(c: GColor); virtual; /// Устанавливает размеры клиентской части главного окна procedure SetSize(w, h: real); diff --git a/bin/Lib/PABCSystem.pas b/bin/Lib/PABCSystem.pas index b254e7b7a..66c639f61 100644 --- a/bin/Lib/PABCSystem.pas +++ b/bin/Lib/PABCSystem.pas @@ -1760,7 +1760,7 @@ function CplxFromPolar(magnitude, phase: real): Complex; /// Возвращает квадратный корень из комплексного числа function Sqrt(c: Complex): Complex; /// Возвращает модуль комплексного числа -function Abs(c: Complex): Complex; +function Abs(c: Complex): real; /// Возвращает комплексно сопряженное число function Conjugate(c: Complex): Complex; /// Возвращает косинус комплексного числа diff --git a/bin/Lib/Timers.pas b/bin/Lib/Timers.pas index 033027f39..c1a0c03c0 100644 --- a/bin/Lib/Timers.pas +++ b/bin/Lib/Timers.pas @@ -38,6 +38,7 @@ type property TimerProc: ()->() read _procedure write _procedure; end; +/// Создать и запустить таймер, вызывающий процедуру TimerProc каждые ms миллисекунд function CreateTimerAndStart(ms: integer; TimerProc: procedure): Timer; implementation diff --git a/bin/Lib/WPFObjects.pas b/bin/Lib/WPFObjects.pas index f8d46bbfa..aa3663e39 100644 --- a/bin/Lib/WPFObjects.pas +++ b/bin/Lib/WPFObjects.pas @@ -140,6 +140,19 @@ type begin Result := l.GetEnumerator; end; + /// Очистить список игровых объектов + procedure Clear; + begin + for var i:=Count-1 downto 0 do + Destroy(Items[i]); + end; + /// Удалить все игровые объекты, удовлетворяющие условию + procedure DestroyAll(condition: ObjectWPF -> boolean); + begin + for var i := Count - 1 downto 0 do + if condition(Items[i]) then + Destroy(Items[i]); + end; end; @@ -1597,12 +1610,14 @@ begin GraphWindow := GraphWPF.GraphWindow; host := new Canvas(); + host.ClipToBounds := True; {host.SizeChanged += (s,e) -> begin var sz := e.NewSize; host.DataContext := sz; end;} var g := MainWindow.Content as DockPanel; + (g.children[0] as Canvas).ClipToBounds := False; // SSM 04/08/20 - возвращаем в False иначе графику GraphWPF становится не видно g.children.Add(host); // Слой графики WPF - последний end; app.Dispatcher.Invoke(AdditionalInit);