Leaderboard
Popular Content
Showing content with the highest reputation on 08/30/24 in all areas
-
Castle Game Engine is a free and open-source game engine. Our strong features are: comfortable visual editor, many graphic effects (shader effects, mirrors, bump mapping, PBR...), support for many model formats (glTF, X3D, MD3, Spine JSON...), being cross-platform (desktop, mobile, console) and of course using fast, clean Object Pascal for both the engine development and your games! Details about the Delphi versions and platforms support are here. We are proud to present a big new release of Castle Game Engine, with lots of new features, improvements and fixes. The new engine version is available for download now. The highlights of the release are below. For more details, see the full release notes. The number of this release, “7.0-alpha.3”, is a signal that we’re on our road to the big 7.0 release (see the roadmap and plans and timeline). This release is dedicated to the late Eugene Loza. I miss you, dear friend. The most important highlights of this release are: Physics. New components for colliders and rigid bodies, ability to run physics simulation in the editor, joints, layers, forces. Many rendering improvements: Correct and automatic blending, both batching and occlusion culling easier to use and more powerful, fully modern rendering on new GPUs, better support for ancient systems with old GPUs. Also OpenGLES (Android, iOS, Nintendo Switch) rendering supports now almost all desktop rendering features: shadow volumes, shadow maps, 3D textures, occlusion query, anisotropic filtering, meshes with 32-bit indexes. Shadows using shadow volumes are trivial to activate. Work is under way to expose shadow maps through a trivial property as well. Visual Studio Code integration. Our own VS Code “Castle Game Engine” extension with code completion and syntax highlighting for all Pascal code and easy building / running / debugging of Castle Game Engine projects. Delphi integration improvements: TCastleControl available for VCL and FMX applications, Delphi packages with IDE support, Delphi Linux support and more. Support for Tiled maps with a new component that is comfortable to use and efficient to render. User Interface improvements: better default font, UI batching, image regions and 9-slices borders visually configurable, mask component. Many editor UX improvements: modern color picker, unified tools to edit UI and transformations, wireframe view, “Change Class” menu action, Sketchfab Importer, finding components by name, multi-selection. Improvements to views (formerly states): better API, automatic initialization of the published fields, opening the project greets you with UX to manage views. Mobile improvements: lots of Android services improvements, Castle Model Viewer Mobile and more Android applications released on Google Play, lots of general Android and iOS fixes and improvements to make porting your games to mobile trivial, safe borders. Loading and saving: cache, MD3 improvements, X3D 4.0 improvements, custom model formats registration, STL saving. Inspector (press F8 / 3 fingers in a debug build of any project) improvements: tweaking boolean properties at run-time, hot-reloading at run-time to iterate on your graphics. Float-based images (e.g. for precise terrains) full support at loading and rendering (formats: 16-bit PNG, float-based KTX, 16/32-bit TIFFs). A lot of new documentation and examples. We in particular recommend 2 new tutorial articles introducing most important engine concepts: Bad way to play chess, aka 3D physics fun. Support us We appreciate your support on Patreon. There are also other ways to support us and if you’re a company, we’re open to cooperation (write to michalis@castle-engine.io). By 2024, Michalis, the lead engine developer, spent most of his life on the engine and doesn’t plan to stop. Moreover, Michalis now works on the engine full-time counting only on your support. So anything you can give is really appreciated! Spread the word! We don’t do much marketing. Because we suck at marketing. Help us — spread the word about this new release! Post about it anywhere you can. Talk about it in your communities — online or in the Real World. Tell your family about it (they really want to know). Reuse this news post and screenshots freely. Have fun everyone and thank you for using the engine.
-
- release
- castle-engine
-
(and 2 more)
Tagged with:
-
Custom Managed Records and Default(T)
Stefan Glienke replied to rgdawson's topic in Algorithms, Data Structures and Class Design
There should not be any temp, nor assign call tbh. Check out this code: {$APPTYPE CONSOLE} uses SysUtils; type TMyRec = record x: Integer; class operator Initialize(out dest: TMyRec); class operator Finalize(var dest: TMyRec); class operator Assign(var left: TMyRec; const[ref] right: TMyRec); end; function MyDefault: TMyRec; begin Writeln('default - ', IntToHex(IntPtr(@Result))); Result.x := 0; end; class operator TMyRec.Initialize(out dest: TMyRec); begin Writeln('init - ', IntToHex(IntPtr(@dest))); end; class operator TMyRec.Finalize(var dest: TMyRec); begin Writeln('finalize - ', IntToHex(IntPtr(@dest))); end; class operator TMyRec.Assign(var left: TMyRec; const[ref] right: TMyRec); begin Writeln('assign'); end; procedure Main; var r: TMyRec; begin r := MyDefault; end; begin Main; end. Now we can argue why there is no assign call because we are assigning the result of the MyDefault function to r. But even though we have declared an assign operator it does what it always does with managed return type - passing it as hidden var parameter. I said this before and I say it again - CMR are broken as designed and personally I stay the heck away from them. I remember some years ago there was a question on SO about struct default ctors serving as default initializers and why C# does not have them and I don't remember if it was Jon or Eric explained that it would cause all kinds of trouble. Edit: Ah, here it is: https://stackoverflow.com/a/333840/587106 - eventually they added them in C# 10 but there is quite some extensive language spec - when I asked for the CMR spec it was all crickets. FWIW the Delphi implementation suffers from exactly the situation that Jon describes - allocate a dynamic array of some CMR and watch all the initializers run. Which is completely bonkers - C# 10 does not do any of that for array allocation - see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/parameterless-struct-constructors#array-allocation -
"Death to WITH" in your Delphi Code
Darian Miller posted a topic in Tips / Blogs / Tutorials / Videos
New blog post on WITH statements. The topic was recently discussed once again in the Delphi Developers Telegram group which triggered a blog post: https://ideasawakened.com/post/why-you-should-not-use-WITH-in-your-Delphi-code -
Custom Managed Records and Default(T)
Dalija Prasnikar replied to rgdawson's topic in Algorithms, Data Structures and Class Design
Yes, sorry. I missed the context you are replying to. We agree on the rest, and that was the point of my example. To show that custom managed are initialized/finalized even if not used and that there is extra initialization for Default call on implicit temporary variable. And compiler should be smart enough not to require any temporary variable at all. In any way thing is broken. -
Custom Managed Records and Default(T)
Remy Lebeau replied to rgdawson's topic in Algorithms, Data Structures and Class Design
I'm aware of that. You seem to have missed the point I was trying to make regarding rgdawson's earlier comment about the order of initialization/finalization. Default() creates a NEW INSTANCE, which is then assigned to the EXISTING instance, ie this code: procedure Main; var r: TMyRec; begin r := Default(TMyRec); end; SHOULD BE roughly equivalent to this: procedure Main; var r: TMyRec; // allocation only begin TMyRec.Initialize(r); try var temp: TMyRec; // allocation only TMyRec.Initialize(temp); try TMyRec.Assign(r, temp); finally TMyRec.Finalize(temp); end; finally TMyRec.Finalize(r); end; end; But what it is actually doing this more like this: procedure Main; var r: TMyRec; // allocation only begin TMyRec.Initialize(r); try var temp: TMyRec; // allocation only TMyRec.Initialize(temp); try TMyRec.Initialize(temp); // <-- SHOULD NOT BE HERE! TMyRec.Assign(r, temp); finally TMyRec.Finalize(temp); end; finally TMyRec.Finalize(r); end; end; Yes, because Default() is not being called. Exactly. r is initialized, then a temporary record is created and initialized TWICE (that's the bug), then the temp is assigned to r, then the temp and r are finalized. Here is the complete code I tested with, which makes it clearer which record is being initialized and finalized. You can clearly see the temporary record created by Default() is initialized twice: program CustomManagedRecordDefaultTest; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Classes; type Stringlist = record private FData: TStringList; function GetText: string; procedure SetText(const AValue: string); public class operator Initialize(out Dest: Stringlist); class operator Finalize(var Dest: Stringlist); class operator Assign(var Dest: Stringlist; const[ref] Source: Stringlist); property Text: string read GetText write SetText; end; class operator Stringlist.Initialize(out Dest: Stringlist); begin Dest.FData := TStringList.Create; WriteLn(IntToHex(IntPtr(@Dest)) + ' Initialized'); end; class operator Stringlist.Finalize(var Dest: Stringlist); begin Dest.FData.Free; WriteLn(IntToHex(IntPtr(@Dest)) + ' Finalized'); end; class operator Stringlist.Assign(var Dest: Stringlist; const[ref] Source: Stringlist); begin Dest.FData.Assign(Source.FData); WriteLn(IntToHex(IntPtr(@Source)) + ' Assigned to ' + IntToHex(IntPtr(@Dest))); end; function Stringlist.GetText: string; begin Result := FData.Text; end; procedure Stringlist.SetText(const AValue: string); begin FData.Text := AValue; end; function AllCaps(const Strings: Stringlist): Stringlist; var sl: Stringlist; begin WriteLn(' Strings=', IntToHex(IntPtr(@Strings)), ' sl=', IntToHex(IntPtr(@sl)), ' Result=', IntToHex(IntPtr(@Result))); WriteLn(' Calling: sl := Default(Stringlist)'); sl := Default(Stringlist); WriteLn(' Default Returned, sl Assigned'); sl.Text := UpperCase(sl.Text); WriteLn(' Returning sl'); Result := sl; end; procedure DoTest; var MyStrings, TheirStrings: Stringlist; begin WriteLn(' MyStrings=', IntToHex(IntPtr(@MyStrings)), ' TheirStrings=', IntToHex(IntPtr(@TheirStrings))); WriteLn(' Calling: MyStrings := AllCaps(TheirStrings)'); MyStrings := AllCaps(TheirStrings); WriteLn(' AllCaps Returned, MyStrings Assigned'); end; begin WriteLn('Calling: DoTest'); DoTest; WriteLn('DoTest Returned'); ReadLn; end. Calling: DoTest 008FFD0C Initialized 008FFD08 Initialized MyStrings=008FFD0C TheirStrings=008FFD08 Calling: MyStrings := AllCaps(TheirStrings) 008FFCC8 Initialized Strings=008FFD08 sl=008FFCC8 Result=008FFD0C Calling: sl := Default(Stringlist) 008FFCC4 Initialized // <-- TEMP CREATED AND INIT HERE 008FFCC4 Initialized // <-- TEMP INIT AGAIN! 008FFCC4 Assigned to 008FFCC8 008FFCC4 Finalized // <-- TEMP DESTROYED HERE Default Returned, sl Assigned Returning sl 008FFCC8 Assigned to 008FFD0C 008FFCC8 Finalized AllCaps Returned, MyStrings Assigned 008FFD08 Finalized 008FFD0C Finalized DoTest Returned -
Custom Managed Records and Default(T)
Dalija Prasnikar replied to rgdawson's topic in Algorithms, Data Structures and Class Design
Because whole point of custom managed records is automatic initialization/finalization. So if you merely declare such record as local variable and you don't ever use it, its initialization and finalization routines will run. Running following code makes the issue more obvious. type TMyRec = record x: Integer; class operator Initialize(out rec: TMyRec); class operator Finalize(var Dest: TMyRec); class operator Assign(var left, right: TMyRec); end; class operator TMyRec.Initialize(out rec: TMyRec); begin Writeln('init'); end; class operator TMyRec.Finalize(var Dest: TMyRec); begin Writeln('finalize'); end; class operator TMyRec.Assign(var left, right: TMyRec); begin Writeln('assign'); end; procedure Main; var r: TMyRec; begin r := Default(TMyRec); end; begin Main; end. If assignment is commented out then result will be init finalize But running code as-is will result with: init init init assign finalize finalize -
IOS Application to Test Flight and Transporter
Dave Nottage replied to FabDev's topic in Cross-platform
Yes, .IPA (not .API) files are built with this configuration. You'll need a Distribution Certificate and a Provisioning Profile to match. Please read here: https://docwiki.embarcadero.com/RADStudio/Athens/en/Deploying_Your_iOS_Application_for_Submission_to_the_App_Store -
pngimage.pas should never be compiled in 10.4.2. It is not even part of PngComponents as it already exists as Vcl.Imaging.pngimage.dcu in the Delphi library path. You should delete that pngimage.pas and probably pnglang.pas, too.
-
"Death to WITH" in your Delphi Code
Tommi Prami replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
This is why long long ago made feature request of compiler/AST assisted with-removed refactoring tool. It never happened. Made new one in the new Bug-tracker: https://embt.atlassian.net/servicedesk/customer/portal/1/RSS-1666 Please comment the bug report and give some pressure... -Tee- -
Yes, exactly, for example: uses ... {$IFDEF MSWINDOWS}, Winapi.Windows{$ENDIF} {$IFDEF ANDROID}, Androidapi.SomeOtherUnit{$ENDIF} ... ;
-
The Winapi.Windows unit is for Windows builds only. If the component is trying to use that unit in an Android build, then its code is not IFDEF'ed properly to separate any platform-specific code, and thus needs to be fixed accordingly.
-
What does this function mean? CharPrev / Range Check Error
Remy Lebeau replied to terran's topic in General Help
As I stated earlier, PChar(S[Length(S)]) is extracting the last single Char from the string and type-casting its value into a PChar pointer, which is wrong. You need to use the @ operator to get the address of that Char. But in any case, using S[Length(S)] doesn't take into account that a string contains encoded codeunits, so will NOT be the last full character if the character is encoded using multiple codeunits. CharPrev() takes the encoding into account. The code is getting a pointer to the null terminator and then moving the pointer backwards 1 full character regardless of how how many codeunits it actually takes. -
The problem will be that there are many different versions of this format. There is no one correct scheme. And I think he will receive more of these invoices in the future
-
Do you have an XML Schema file (typically file extention = .xsd) for the UBL 2.1 model invoice? If so you can use this with XML Mapper to generate a transform (at design time) which you then use in code so that it can populate a client dataset (at run time) with data from an incoming XML file. With this approach XML files that only contain partial amounts of data (as you anticipate) are handled correctly.
-
Custom Managed Records and Default(T)
Stefan Glienke replied to rgdawson's topic in Algorithms, Data Structures and Class Design
Already reported in 2021 -
This is a ZUGFeRD-UBL-Invoice My Repo LandrixSoftware/XRechnung-for-Delphi: XRechnung Implementation for Delphi (github.com) reads currently XRechnung in UBL and CII Format If you can wait a little longer, UBL support for all other ZUGFeRD formats will be available in September LandrixSoftware/ZUGFeRD-for-Delphi: ZUGFeRD / Factur-X Implementation for Delphi (github.com)
-
Are you aware of the XML mapper tool?
-
"Death to WITH" in your Delphi Code
JonRobertson replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
I've been working in Delphi 7 projects for the past year. Some are being migrated to 11.3+ and some are staying with Delphi 7. I always refactor with statements away by hand, but even that can be tricky. For example, I learned after refactoring several "with dataset do ... while not Eof do ; Next;" constructs, and overlooking one call to Next, that TForm has a public Next method, related to MDI children of a MDI parent. https://docwiki.embarcadero.com/Libraries/Alexandria/en/Vcl.Forms.TForm.Next Hello infinite loop! Now, go away. -
How to set Supported platforms for my component?
Remy Lebeau replied to dmitrybv's topic in Delphi IDE and APIs
By annotating it with the ComponentPlatforms attribute: https://docwiki.embarcadero.com/Libraries/en/System.Classes.ComponentPlatformsAttribute Not that I'm aware of. Which ways are you thinking of? When a component does not indicate any specific platforms, then it is available for all platforms, limited only by the framework it uses. A VCL component without ComponentPlatforms will support all platforms that VCL supports, namely Windows 32bit and 64bit. An FMX component without ComponentPlatforms will support all platforms that FMX supports. TDataSource derives directly from TComponent and has no affinity to either VCL or FMX, so it will support whichever framework your project is using, and thus whichever platforms that framework supports. -
"Death to WITH" in your Delphi Code
Lajos Juhász replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
There is no need for with in your example: procedure TMyForm.UpdateInventoryItem(const NewQty: Integer); var a: <the required type>; b: <the required type>; begin a:= dmStoreInventoryData; b:= A.tblUpdateItemForStore; B.Edit; B.FieldByName('Qty').AsInteger := NewQty; B.Post; end; With will not make this code any cleaner.