Commit Graph

410 Commits

Author SHA1 Message Date
Hans Goudey
4369429101 Cleanup: Move NOD_socket.h to C++
See #103343

Pull Request: https://projects.blender.org/blender/blender/pulls/109623
2023-07-02 21:01:57 +02:00
Jacques Lucke
f33d7bb598 Nodes: add nested node ids and use them for simulation state
The simulation state used by simulation nodes is owned by the modifier. Since a
geometry nodes setup can contain an arbitrary number of simulations, the modifier
has a mapping from `SimulationZoneID` to `SimulationZoneState`. This patch changes
what is used as `SimulationZoneID`.

Previously, the `SimulationZoneID` contained a list of `bNode::identifier` that described
the path from the root node tree to the simulation output node. This works ok in many
cases, but also has a significant problem: The `SimulationZoneID` changes when moving
the simulation zone into or out of a node group. This implies that any of these operations
loses the mapping from zone to simulation state, invalidating the cache or even baked data.

The goal of this patch is to introduce a single-integer ID that identifies a (nested) simulation
zone and is stable even when grouping and un-grouping. The ID should be stable even if the
node group containing the (nested) simulation zone is in a separate linked .blend file and
that linked file is changed.

In the future, the same kind of ID can be used to store e.g. checkpoint/baked/frozen data
in the modifier.

To achieve the described goal, node trees can now store an arbitrary number of nested node
references (an array of `bNestedNodeRef`). Each nested node reference has an ID that is
unique within the current node tree. The node tree does not store the entire path to the
nested node. Instead it only know which group node the nested node is in, and what the
nested node ID of the node is within that group. Grouping and un-grouping operations
have to update the nested node references to keep the IDs stable. Importantly though,
these operations only have to care about the two node groups that are affected. IDs in
higher level node groups remain unchanged by design.

A consequence of this design is that every `bNodeTree` now has a `bNestedNodeRef`
for every (nested) simulation zone. Two instances of the same simulation zone (because
a node group is reused) are referenced by two separate `bNestedNodeRef`. This is
important to keep in mind, because it also means that this solution doesn't scale well if
we wanted to use it to keep stable references to *all* nested nodes. I can't think of a
solution that fulfills the described requirements but scales better with more nodes. For
that reason, this solution should only be used when we want to store data for each
referenced nested node at the top level (like we do for simulations).

This is not a replacement for `ViewerPath` which can store a path to data in a node tree
without changing the node tree. Also `ViewerPath` can contain information like the loop
iteration that should be viewed (#109164). `bNestedNodeRef` can't differentiate between
different iterations of a loop. This also means that simulations can't be used inside of a
loop (loops inside of a simulation work fine though).

When baking, the new stable ID is now written to disk, which means that baked data is
not invalidated by grouping/un-grouping operations. Backward compatibility for baked
data is provided, but only works as long as the simulation zone has not been moved to
a different node group yet. Forward compatibility for the baked data is not provided
(so older versions can't load the data baked with a newer version of Blender).

Pull Request: https://projects.blender.org/blender/blender/pulls/109444
2023-07-01 11:54:32 +02:00
Hans Goudey
e570f13616 Cleanup: Move NOD_geometry.h to C++
Pull Request: https://projects.blender.org/blender/blender/pulls/109306
2023-06-23 22:15:42 +02:00
Campbell Barton
1a04a231ec Fix buffer overflow in BKE_bpath_foreach_path_fixed_process
It was assumed destination buffers were at least 1024 bytes which could
overflow by 256 bytes for sequencer directories. Resolve by passing the
destination buffer size to BKE_bpath_foreach_path_fixed_process.

Also remove strcpy use in foreach_path_clean_cb.
2023-06-23 10:09:01 +10:00
Damien Picard
58c6a278d3 I18n: remove context translation from node title
The node title was translated in two steps: first using the
BLT_I18NCONTEXT_ID_NODETREE context, and if that failed, using the
default context.

As far as I could find, the only node using this intentionally is the
Frame node, but its title is only displayed in the Add Menu.

However, at least one node has a bad translation because its name was
extracted independently with the NodeTree context: the compositing
Scale node uses a translation which is only appropriate in a vector
math context.

This commit removes the double translation step. If needed by
translators, a translation context in the node RNA could be introduced
at a later time.

Pull Request: https://projects.blender.org/blender/blender/pulls/108241
2023-06-21 16:43:19 +02:00
Brecht Van Lommel
4b4c95c402 Fix compositor node previews flickering when dragging sliders
Compositing jobs would get cancelled as you drag number sliders, and
would write back empty previews. Only sync previews for completed jobs.
2023-06-19 16:27:08 +02:00
Lukas Tönne
e32f85c03e Cleanup: Removed unused variables in bNodePanel
The flag in bNodePanel is anticipated to store settings such as whether
a panel is open or closed by default. It's not currently used, so for
now the flag is removed.

The next_panel_identifier in bNodeTree is also not needed any more. It
was used to set a unique identifier for each panel, which isn't needed.

Added comments to remaining fields in bNodePanel.

Pull Request: https://projects.blender.org/blender/blender/pulls/109028
2023-06-16 10:12:21 +02:00
Iliya Katueshenock
1571be0a47 Cleanup: Use float2 in nodeToView and nodeFromView
Use 2D float to represent node positions.

Pull Request: https://projects.blender.org/blender/blender/pulls/108956
2023-06-15 16:04:23 +02:00
Hans Goudey
63dae2a105 Nodes: Add rotation socket type, support in many geometry nodes
Add a quaternion rotation socket type, and using the recently added
rotation attribute type, support the type in most of the multi-type
geometry nodes, and modifier attribute inputs and outputs.

The socket is still exposed with an XYZ Euler default value.
In the future we can add modes to this rotation value similar
to object rotations.

Rotation values have no implicit conversions to other types.
Nodes to convert to and from rotation values will be added
in a follow-up commit.

For now, the new socket type is hidden behind and experimental
option, because we haven't chosen the final color for it yet.

Pull Request: https://projects.blender.org/blender/blender/pulls/108903
2023-06-14 20:30:10 +02:00
Lukas Tönne
8c2ad8bbd3 Nodes: Panel declarations for grouping sockets
Adds an optional list of panels to node trees. Each socket can be
assigned a panel. UI panels will be created in the future in the
modifier for these grouped sockets.

Panels are stored as a pointer array in node trees, next to socket
declarations. Each panel has a name, but it does not have to be unique.
In future a panel might also store whether it is visible by default and
similar information.

C API and RNA API are both added. Panels and their socket
assignments are accessible to users through another list in the "Group"
tab of the node editor sidebar.

Sockets in the same panel will remain together even when adding,
removing, or moving sockets or panels, renaming, etc.
A socket can be moved up or down within a panel but each panel
remains a contiguous block. Actual tree views may be created later.

Pull Request: https://projects.blender.org/blender/blender/pulls/108649
2023-06-14 18:02:40 +02:00
Jacques Lucke
7b61dcf6bc Geometry Nodes: deduplicate anonymous attribute analysis algorithm
Previously, there were two independent algorithms for analysing how anonymous
attributes are used in a node tree: One that just computed the `aal::RelationsInNode`
for an entire node tree and one that performed a more in depth analysis to
determine how far anonymous attributes should be propagated.

As it turns out, both operations can also be done at the same time and the result
can be cached on the node tree. This reduces the amount of code and allows for
better code reuse.

This simplification is likely only an intermediate step as things will probably have
to be refactored further to support e.g. serial loops (#108896).
2023-06-14 14:04:22 +02:00
Hans Goudey
decf089e06 Cleanup: Remove unused deprecated socket type
"SOCK_MESH" was used for a particle nodes experiment,
never in a released version of Blender as far as I know.
2023-06-07 08:31:46 -04:00
Campbell Barton
96bfcd0597 Cleanup: rename __SOCK_MESH to SOCK_MESH_DEPRECATED
Double underscores didn't communicate that this was deprecated,
and are typically for internal or platform defined identifiers and
shouldn't be used for public API's.
2023-06-07 17:53:08 +10:00
Iliya Katueshenock
8dc70b9e2e Cleanup: Correcting default cases in node.cc
Add all other enum items to switch statements instead of using default.

Pull Request: https://projects.blender.org/blender/blender/pulls/107339
2023-06-06 19:19:53 +02:00
Campbell Barton
9b97123bf9 Cleanup: spelling in comments, odd comment block spacing 2023-06-02 10:16:16 +10:00
Sergey Sharybin
c1bc70b711 Cleanup: Add a copyright notice to files and use SPDX format
A lot of files were missing copyright field in the header and
the Blender Foundation contributed to them in a sense of bug
fixing and general maintenance.

This change makes it explicit that those files are at least
partially copyrighted by the Blender Foundation.

Note that this does not make it so the Blender Foundation is
the only holder of the copyright in those files, and developers
who do not have a signed contract with the foundation still
hold the copyright as well.

Another aspect of this change is using SPDX format for the
header. We already used it for the license specification,
and now we state it for the copyright as well, following the
FAQ:

    https://reuse.software/faq/
2023-05-31 16:19:06 +02:00
Lukas Stockner
8cde7d8f8a Cycles: Merge Anisotropic BSDF node into Glossy BSDF node
Used to be https://archive.blender.org/developer/D17123.

Internally these are already using the same code path anyways, there's no point in maintaining two distinct nodes.

The obvious approach would be to add Anisotropy controls to the Glossy BSDF node and remove the Anisotropic BSDF node. However, that would break forward compability, since older Blender versions don't know how to handle the Anisotropy input on the Glossy BSDF node.

Therefore, this commit technically removes the Glossy BSDF node, uses versioning to replace them with an Anisotropic BSDF node, and renames that node to "Glossy BSDF".

That way, when you open a new file in an older version, all the nodes show up as Anisotropic BSDF nodes and render correctly.

This is a bit ugly internally since we need to preserve the old `idname` which now no longer matches the UI name, but that's not too bad.

Also removes the "Sharp" distribution option and replaces it with GGX, sets Roughness to zero and disconnects any input to the Roughness socket.

Pull Request: https://projects.blender.org/blender/blender/pulls/104445
2023-05-18 23:12:20 +02:00
Bastien Montagne
a9193a9ad2 Refactor ID liblinking on readfile to take ID pointer.
The usage of the lib pointer was cryptic to say the least, it was
essentialy used to allow or not local IDs results in the mapping
old_id_pointer -> new_id_pointer lookup result.

Now:
- Explicitely pass a boolean to allow or not local ID as result in
  lower-level code.
- Pass the 'self ID' pointer instead of its library to the whole
  liblinking code (that was already the case in a few places).

Note that naming of the 'self id' pointer is currently very inconsistent
throughout the readfile liblink code, this will have to be cleaned up in
a separate step later. For now, `self_id` has been chosen for new code
as it matches the terminology in lib_query code.

The later change can also allow finer handling of lookup on undo, based
on how it was re-read (or not), should the need for this arise.
2023-05-17 16:38:56 +02:00
Hans Goudey
859c0d9edf Cleanup: Remove redundant node type lookup function
Using the topology map gives a constant time lookup, since it has a map
of nodes per type. The collada code used the old function, but had been
ifdef'd for four years, so it's removed here.
2023-05-16 11:09:42 -04:00
Hans Goudey
d87547abd5 Cleanup: Remove unused node function for finding link
Nowadays it's much better to use the topology cache.
2023-05-16 09:44:41 -04:00
Hans Goudey
f3babec2df Cleanup: Undo move of functions in previous node cleanup commit
Functions were moved as part of f7388e3be5, which was
unnecessarily noisy. Instead of reverting, move the definitions back
to their original place in node.cc. Also move a few more things to
the blender::bke namespace.
2023-05-16 09:39:53 -04:00
Iliya Katueshenock
f7388e3be5 Cleanup: Move BKE_node.h to C++
See: https://projects.blender.org/blender/blender/issues/103343

Changes:
1. Added `BKE_node.hh` file. New file includes old one.
2. Functions moved to new file. Redundant `(void)`, `struct` are removed.
3. All cpp includes replaced from `.h` on `.hh`.
4. Everything in `BKE_node.hh` is on `blender::bke` namespace.
5. All implementation functions moved in namespace.
6. Function names (`BKE_node_*`) changed to `blender::bke::node_*`.
7. `eNodeSizePreset` now is a class, with renamed items.

Pull Request: https://projects.blender.org/blender/blender/pulls/107790
2023-05-15 15:14:22 +02:00
Campbell Barton
169dd2a2b4 Use UTF8 copy function to ensure valid UTF8 output 2023-05-13 17:38:48 +10:00
Campbell Barton
3958ae7241 Cleanup: use STRNCPY, SNPRINTF macros 2023-05-09 14:08:19 +10:00
Campbell Barton
df54b627b3 Cleanup: use of the term 'len' & 'maxlen'
Only use the term len & maxlen when they represent the length & maximum
length of a string. Instead of the available bytes to use.

Also include the data they're referencing as a suffix, otherwise it's
not always clear what the length is in reference to.
2023-05-07 16:46:37 +10:00
illua1
239c1194a0 Fix #107545: Mistakes in recent node.cc cleanup
1. Early return needs inverted null checking.
2. `BLO_expand` macros expect value, not a pointer.

Pull Request: https://projects.blender.org/blender/blender/pulls/107622
2023-05-04 16:32:15 +02:00
Jacques Lucke
0de54b84c6 Geometry Nodes: add simulation support
This adds support for building simulations with geometry nodes. A new
`Simulation Input` and `Simulation Output` node allow maintaining a
simulation state across multiple frames. Together these two nodes form
a `simulation zone` which contains all the nodes that update the simulation
state from one frame to the next.

A new simulation zone can be added via the menu
(`Simulation > Simulation Zone`) or with the node add search.

The simulation state contains a geometry by default. However, it is possible
to add multiple geometry sockets as well as other socket types. Currently,
field inputs are evaluated and stored for the preceding geometry socket in
the order that the sockets are shown. Simulation state items can be added
by linking one of the empty sockets to something else. In the sidebar, there
is a new panel that allows adding, removing and reordering these sockets.

The simulation nodes behave as follows:
* On the first frame, the inputs of the `Simulation Input` node are evaluated
  to initialize the simulation state. In later frames these sockets are not
  evaluated anymore. The `Delta Time` at the first frame is zero, but the
  simulation zone is still evaluated.
* On every next frame, the `Simulation Input` node outputs the simulation
  state of the previous frame. Nodes in the simulation zone can edit that
  data in arbitrary ways, also taking into account the `Delta Time`. The new
  simulation state has to be passed to the `Simulation Output` node where it
  is cached and forwarded.
* On a frame that is already cached or baked, the nodes in the simulation
  zone are not evaluated, because the `Simulation Output` node can return
  the previously cached data directly.

It is not allowed to connect sockets from inside the simulation zone to the
outside without going through the `Simulation Output` node. This is a necessary
restriction to make caching and sub-frame interpolation work. Links can go into
the simulation zone without problems though.

Anonymous attributes are not propagated by the simulation nodes unless they
are explicitly stored in the simulation state. This is unfortunate, but
currently there is no practical and reliable alternative. The core problem
is detecting which anonymous attributes will be required for the simulation
and afterwards. While we can detect this for the current evaluation, we can't
look into the future in time to see what data will be necessary. We intend to
make it easier to explicitly pass data through a simulation in the future,
even if the simulation is in a nested node group.

There is a new `Simulation Nodes` panel in the physics tab in the properties
editor. It allows baking all simulation zones on the selected objects. The
baking options are intentially kept at a minimum for this MVP. More features
for simulation baking as well as baking in general can be expected to be added
separately.

All baked data is stored on disk in a folder next to the .blend file. #106937
describes how baking is implemented in more detail. Volumes can not be baked
yet and materials are lost during baking for now. Packing the baked data into
the .blend file is not yet supported.

The timeline indicates which frames are currently cached, baked or cached but
invalidated by user-changes.

Simulation input and output nodes are internally linked together by their
`bNode.identifier` which stays the same even if the node name changes. They
are generally added and removed together. However, there are still cases where
"dangling" simulation nodes can be created currently. Those generally don't
cause harm, but would be nice to avoid this in more cases in the future.

Co-authored-by: Hans Goudey <h.goudey@me.com>
Co-authored-by: Lukas Tönne <lukas@blender.org>

Pull Request: https://projects.blender.org/blender/blender/pulls/104924
2023-05-03 13:18:59 +02:00
Campbell Barton
381de3bd9e Cleanup: format 2023-05-03 11:25:30 +10:00
illua1
71e4f48180 Nodes: Improve link drag search value moving
Now, when link drag search is used to create new input value nodes, it
also moves socket values into node storage. This means, by design, that
result of evaluation on node tree will not be changed. For data blocks,
the original value is set to null, thus avoiding the existence of
unused pointers.

Right now a few nodes (in shader in many cases) are implemented without
node storage, but by storing value in socket itself. Float value input
node is unsupported in this way too.

Pull Request: https://projects.blender.org/blender/blender/pulls/107470
2023-05-02 18:50:34 +02:00
Campbell Barton
6859bb6e67 Cleanup: format (with BraceWrapping::AfterControlStatement "MultiLine") 2023-05-02 09:37:49 +10:00
illua1
70504a35dd Cleanup: Type conversions in node.cc
Make sure that function style, reinterpret_cast, and static_cast are
used for all type conversions, without of casting to void *. Some other
related minor changes: add temporal variables, lost space, asserts for
case to avoid type conversions by using `->id` way.

Pull Request: https://projects.blender.org/blender/blender/pulls/107097
2023-04-25 14:38:24 +02:00
illua1
2166fd2685 Geometry Nodes: Delete value moving for drag and drop group inputs
Initially, this function was for node data. At Simon's suggestion, it
was extended to a node group inputs as well. However, this overlaps with
another function. It has been missing for a while, but has recently been
fixed by https://projects.blender.org/blender/blender/pulls/107179. Now this functionality is redundant.

Pull Request: https://projects.blender.org/blender/blender/pulls/107255
2023-04-24 03:54:59 +02:00
illua1
2f743b0a92 Cleanup: Replace manual flag checking with methods in node.cc
Not all flags have methods, and not all node primitive types have this.
Replacement of rather simple cases.

Pull Request: https://projects.blender.org/blender/blender/pulls/107055
2023-04-18 00:29:10 +02:00
illua1
9d4949f80b Cleanup: Reduce nesting in node.cc
Decompose most of the nesting in the code to make the code
more consistent along the line of program execution.
Mainly achieved through:
- Remove redundant else
- Invert condition
- Add temporary variable to redistribute and name conditions

Pull Request: https://projects.blender.org/blender/blender/pulls/105509
2023-04-16 22:53:09 +02:00
Max Schlecht
ad031029cf Fix #106467: Crash when loading files with custom node groups
Loading a blend file containing custom material node groups crashed Blender.
See #106467 for more information.

Pull Request: https://projects.blender.org/blender/blender/pulls/106559
2023-04-05 15:36:24 +02:00
illua1
d0604a1bb2 Fix #106530: Don't try to move unmovable node socket values
Missing checkings for unsupported cases.

Pull Request: https://projects.blender.org/blender/blender/pulls/106545
2023-04-04 14:23:40 +02:00
illua1
9726e4a0ad Nodes: Move data-block default values with link drag search
When creating nodes by dragging a link, it can be convenient to
transfer values from input socket. For reference values, like images,
this may be necessary to avoid unnecessary data-block users. This
patch starts adding such a system. At this moment this only makes sense
for one node (Image Input), but this can be extended to work with other
reference types, different non-reference types and support auto-casting
(if a float is transferred to the Integer Input node).

See task: https://projects.blender.org/blender/blender/issues/102854
Original patch: https://archive.blender.org/developer/D16735

Pull Request: https://projects.blender.org/blender/blender/pulls/105972
2023-04-03 19:33:39 +02:00
Hans Goudey
e7f395dd20 Nodes: Add dropdown to select group socket subtype
Previously the only way to control the subtype was to remove the group
input or output and create it again. This commit adds a dropdown to
change an existing socket, for supported socket types.

Based on a patch by Angus Stanton: https://developer.blender.org/D15715

It was necessary to fix the UI code slightly; the layout's context
wasn't being used in calls to an operator's enum items callback.

Pull Request: https://projects.blender.org/blender/blender/pulls/105614
2023-04-03 18:23:30 +02:00
Sergey Sharybin
a12a8a71bb Remove "All Rights Reserved" from Blender Foundation copyright code
The goal is to solve confusion of the "All rights reserved" for licensing
code under an open-source license.

The phrase "All rights reserved" comes from a historical convention that
required this phrase for the copyright protection to apply. This convention
is no longer relevant.

However, even though the phrase has no meaning in establishing the copyright
it has not lost meaning in terms of licensing.

This change makes it so code under the Blender Foundation copyright does
not use "all rights reserved". This is also how the GPL license itself
states how to apply it to the source code:

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software ...

This change does not change copyright notice in cases when the copyright
is dual (BF and an author), or just an author of the code. It also does
mot change copyright which is inherited from NaN Holding BV as it needs
some further investigation about what is the proper way to handle it.
2023-03-30 10:51:59 +02:00
Falk David
df0c2693b6 Refactor: Rename grease pencil files to legacy
This renames the `BKE_gpencil_*` as well as the `DNA_gpencil_types.h`
files to indicate that it's the legacy grease pencil.

Pull Request: https://projects.blender.org/blender/blender/pulls/105597
2023-03-13 10:42:51 +01:00
illua1
b756915206 Cleanup: Avoid recursion for node parenting
Don't call recursion where it's redundant. The recursive algorithm
can carry dangerous behavior due to stack growth and overflow. The
probability is low for something like the frame nodes. But using a loop
is cheap, providing O(N = const) memory cost. A loop through the links
in a singly linked list is sufficient. The use of 2D vectors for
location mapping and other things can be separate.

Pull Request #105394
2023-03-06 18:39:20 +01:00
Iliya Katueshenock
c066035907 Cleanup: Deduplicate node parent checking functions
Unify both functions in one, with a more telling name,
to be sure of the order of the arguments. Some functional
cleanup of the using code to make it more explicit.

Pull Request #105413
2023-03-03 22:38:49 +01:00
Iliya Katueshenock
d130f81a22 Cleanup: Use const arguments in node.cc
Cleanup, try to always use const.
Many function signatures still have incorrect argument order
(constants, mutables). But this is a larger other cleanup.

Pull Request #104937
2023-03-02 23:14:59 +01:00
Iliya Katueshenock
2cd7e70c18 Fix #104604: Potential crash when relinking node links
In the first loop is safe to remove the current element.
The second loop can remove any element, potentially the next.
This triggers a read after freed.

Pull Request #104897
2023-02-17 21:23:35 +01:00
Campbell Barton
91346755ce Cleanup: use '#' prefix for issues instead of 'T'
Match the convention from Gitea instead of Phabricator's T for tasks.
2023-02-12 14:56:05 +11:00
Iliya Katueshenock
d411be8a99 Cleanup: Use utility function to find groups in node tree
Add `contains_group` method in python api for `NodeTree` type, cleanup
`ntreeHasTree` function, reuse `ntreeHasTree` in more place in code.
The algorithm has been changed to not recheck trees by using set.

Performance gains from avoiding already checked node trees:
Based on tests, can say that for large files with a huge number
of trees, the response speed of opening the search menu in the
node editor increased by ~200 times (for really large projects
with 16 individual groups in 6 levels of nesting). Group insert
operations are also accelerated, but this is different in some cases.

Pull Request #104465
2023-02-10 17:30:55 +01:00
Iliya Katueshenock
2cfc4d7644 Fix #104383: don't update declaration for clipboard copy
When nodes are copied to the clipboard, they don't need their declaration.
For nodes with dynamic declaration that might depend on the node tree itself,
the declaration could not be build anyway, because the node-clipboard does
not have a node tree.

Pull Request #104432
2023-02-09 19:20:39 +01:00
Jacques Lucke
7208938707 Fix T104278: incorrect handling of unavailable linked node groups
The declaration of group nodes using unavailable linked groups contains
a `skip_updating_sockets` tag, which indicates that the node shouldn't
change. This information was not used properly further down the line.
2023-02-02 16:38:53 +01:00
Jacques Lucke
2a19810f97 Fix T104296: crash caused by incorrectly initialized group nodes
Versioning code in `do_versions_after_linking_260` inserted new group input
and output nodes. And (reasonably?) expected sockets to exist on those nodes.
However, `nodeAddStaticNode` did not initialize sockets on nodes with that use
`declare_dynamic` yet. This patch changes it so that `declare_dynamic` is used
in more places, which caused issues during file loading when node groups are
updated in somewhat arbitrary order (not in an order that is based on which
groups use which).

Differential Revision: https://developer.blender.org/D17183
2023-02-02 16:38:53 +01:00
Jacques Lucke
4a768a7857 Cleanup: remove unused variable 2023-01-26 13:31:41 +01:00