<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Get the Neighboring Keys from a Selected Key?]]></title><description><![CDATA[<p dir="auto">Hi,</p>
<p dir="auto">Is there a way to get the neighboring key from a selected key?<br />
My end goal is to set the key tangent of a selected key.<br />
Apparently, the value to be set is not in percentage but in actual value relative to the neighboring keys. Hence the question.</p>
<p dir="auto">Is this possible?</p>
<p dir="auto"><img src="/forum/assets/uploads/files/1706452450240-c7daf8e1-ce81-4ea4-8647-ed828b71398a-image.png" alt="c7daf8e1-ce81-4ea4-8647-ed828b71398a-image.png" class=" img-fluid img-markdown" /></p>
]]></description><link>http://developers.maxon.net/forum/topic/15353/get-the-neighboring-keys-from-a-selected-key</link><generator>RSS for Node</generator><lastBuildDate>Mon, 11 May 2026 00:38:50 GMT</lastBuildDate><atom:link href="http://developers.maxon.net/forum/topic/15353.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 28 Jan 2024 14:34:28 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Get the Neighboring Keys from a Selected Key? on Tue, 06 Feb 2024 10:01:22 GMT]]></title><description><![CDATA[<p dir="auto">Hi <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/ferdinand">@<bdi>ferdinand</bdi></a></p>
<p dir="auto">Apologies for the late response.</p>
<p dir="auto">RE: You should show me how you access that key.<br />
My bad. But it's on the previous thread you answered by manually selecting a keyframe and storign it in a variable.<br />
<a href="https://developers.maxon.net/forum/topic/15344/get-selected-keyframes/3" target="_blank" rel="noopener noreferrer nofollow ugc">https://developers.maxon.net/forum/topic/15344/get-selected-keyframes/3</a></p>
<p dir="auto">RE: I just showed you above how to operate with percentage values in Cinema 4D.<br />
My bad. I missed it. I was looking immediately at the declaration.</p>
<pre><code>keyA: c4d.CKey
keyB: c4d.CKey
</code></pre>
<p dir="auto">which I only want one key to be declared.</p>
<p dir="auto">===</p>
<p dir="auto">In summary, the GetNext() and GetPred() solved the problem in getting the Neighboring Keys from a Selected Key.</p>
]]></description><link>http://developers.maxon.net/forum/post/73703</link><guid isPermaLink="true">http://developers.maxon.net/forum/post/73703</guid><dc:creator><![CDATA[bentraje]]></dc:creator><pubDate>Tue, 06 Feb 2024 10:01:22 GMT</pubDate></item><item><title><![CDATA[Reply to Get the Neighboring Keys from a Selected Key? on Tue, 30 Jan 2024 12:35:16 GMT]]></title><description><![CDATA[<p dir="auto">Hey <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/bentraje">@<bdi>bentraje</bdi></a>,</p>
<blockquote>
<p dir="auto">In my case, I only want keyB declared (as it is being detected). and have a script determine the neighbor key (which is keyA). Is that possible?</p>
</blockquote>
<p dir="auto">You should show me how you access that key. I lined out the two methods how to access neighboring keys. When you have no index for the key, you can either live dangerously and just assume that <code>myKey.GetPred</code> will return the temporally previous key or sort them yourself.</p>
<pre><code class="language-py">import c4d

op: c4d.BaseObject | None  # The primary selected object in `doc`. Can be `None`.

def main() -&gt; None:
    """Called by Cinema 4D when the script is being executed.
    """
    if not op:
        return
    
    track: c4d.CTrack | None = op.GetFirstCTrack()
    if not track:
        return
    
    curve: c4d.CCurve = track.GetCurve()
    if (curve.GetKeyCount() &lt; 1):
        return
    
    key: c4d.CKey = curve.GetKey(0)
    while (key):
        print (key, key.GetTime().Get())
        key = key.GetNext()


if __name__ == '__main__':
    main()
</code></pre>
<p dir="auto">I ran this on an object with a track where I deliberately did not created the keys in temporal order, and the output is sorted. I would however not bet on the fact that all track types will behave like this.</p>
<pre><code class="language-txt">&lt;c4d.CKey object at 0x0000017AB3612640&gt; 0.0
&lt;c4d.CKey object at 0x0000017AB3612B40&gt; 0.26666666666666666
&lt;c4d.CKey object at 0x0000017AB36123C0&gt; 0.7666666666666667
&lt;c4d.CKey object at 0x0000017AB3612840&gt; 1.2666666666666666
&lt;c4d.CKey object at 0x0000017AB36128C0&gt; 2.433333333333333
&lt;c4d.CKey object at 0x0000017AB36126C0&gt; 3.0
</code></pre>
<blockquote>
<p dir="auto">I just need the neighboring keys so I can normalize the tangents to a 0 to 1 value. For reference, houdini has set its tangent in 0 to 1 (or in percentage) so it can easily modified.</p>
</blockquote>
<p dir="auto">Without wanting to be rude, I just showed you above how to operate with percentage values in Cinema 4D.   Tangents in Cinema 4D are not normalized and operate in object space. The timeline is there no exception and I cannot change that for you.</p>
<p dir="auto">Cheers,<br />
Ferdinand</p>
]]></description><link>http://developers.maxon.net/forum/post/73647</link><guid isPermaLink="true">http://developers.maxon.net/forum/post/73647</guid><dc:creator><![CDATA[ferdinand]]></dc:creator><pubDate>Tue, 30 Jan 2024 12:35:16 GMT</pubDate></item><item><title><![CDATA[Reply to Get the Neighboring Keys from a Selected Key? on Tue, 30 Jan 2024 11:54:49 GMT]]></title><description><![CDATA[<p dir="auto">Hi <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/ferdinand">@<bdi>ferdinand</bdi></a></p>
<p dir="auto">Thanks for the response:</p>
<p dir="auto">Basically, in your script:<br />
keyA and keyB is already declared.</p>
<p dir="auto">In my case, I only want keyB declared (as it is being detected). and have a script determine the neighbor key (which is keyA).<br />
Is that possible?</p>
<p dir="auto">I just need the neighboring keys so I can normalize the tangents to a 0 to 1 value.</p>
<p dir="auto">For reference, houdini has set its tangent in 0 to 1 (or in percentage) so it can easily modified.</p>
<p dir="auto"><img src="/forum/assets/uploads/files/1706615685119-7a82cb58-f439-4a84-9a03-5422fbd53419-image.png" alt="image.png" class=" img-fluid img-markdown" /></p>
]]></description><link>http://developers.maxon.net/forum/post/73645</link><guid isPermaLink="true">http://developers.maxon.net/forum/post/73645</guid><dc:creator><![CDATA[bentraje]]></dc:creator><pubDate>Tue, 30 Jan 2024 11:54:49 GMT</pubDate></item><item><title><![CDATA[Reply to Get the Neighboring Keys from a Selected Key? on Tue, 30 Jan 2024 11:47:48 GMT]]></title><description><![CDATA[<p dir="auto">Hello <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/bentraje">@<bdi>bentraje</bdi></a>,</p>
<p dir="auto">thank you for reaching out to us. I am not quite sure how your (main) question is meant. You usually iterate over keys using an index via <a href="https://developers.maxon.net/docs/py/2024_2_0/modules/c4d/C4DAtom/GeListNode/BaseList2D/CCurve/index.html#c4d.CCurve" target="_blank" rel="noopener noreferrer nofollow ugc">CCurve.GetKeyCount()</a>. So the neighboring keys would be <code>i - 1</code> and <code>i + 1</code> plus some clamping so that you do not exceed the index boundaries. Because <code>CKey</code> is a <code>GeListNode</code>, you can also iterate through the list head with <code>GeListNode.GetNext</code> and so on. But I am not sure if keys are always temporally ordered under their list head (my hunch would be that they are not always temporally ordered).</p>
<p dir="auto">About your second question, yes, tangents are not expressed as percent values just as they are not in the Attribute Manager.<br />
<img src="/forum/assets/uploads/files/1706613928164-54171db1-fe31-46ba-b2a0-4b29ae8a8fd7-image-resized.png" alt="54171db1-fe31-46ba-b2a0-4b29ae8a8fd7-image.png" class=" img-fluid img-markdown" /></p>
<p dir="auto">When you have a key or tangent, you can form a point out of their time and value components, so that you can compute things using algebraic expressions.</p>
<pre><code># Two keys in a document.
keyA: c4d.CKey
keyB: c4d.CKey

# Computing values interpreting keys as 2D vectors. We construct (time, value) vectors for key 
# A and B and then compute the mean value, i.e., the point lying on the mid point of the segment
# which is connecting the two keys.
p: c4d.Vector = c4d.Vector(keyA.GetTime().Get(), keyA.GetValue(), 0)
q: c4d.Vector = c4d.Vector(keyA.GetTime().Get(), keyA.GetValue(), 0)
mid_vec: c4d.Vector = c4d.utils.MixVec(p, q, .5)
mid_time: c4d.BaseTime = c4d.BaseTime(mid.x)
mid_value: float = mid.y

# We could of course also do things manually, for example when we want to only operate on one axis.
# Here we compute 50% time mark between #keyA and #keyB.
mid_time_2: c4d.BaseTime = c4d.BaseTime(
    c4d.utils.MixValue(keyA.GetTime().Get(), keyB.GetTime().Get(), .5)
)
</code></pre>
<p dir="auto">But in general, I would advise against messing too much which tangents in a completely free manner, and instead rather rely on the presets. Good tangent behavior in a timeline can be tricky, as there are often special cases where you want things to behave differently. There is a reason why the tangent preset is not 'custom' by default.</p>
<p dir="auto">Cheers,<br />
Ferdinand</p>
]]></description><link>http://developers.maxon.net/forum/post/73644</link><guid isPermaLink="true">http://developers.maxon.net/forum/post/73644</guid><dc:creator><![CDATA[ferdinand]]></dc:creator><pubDate>Tue, 30 Jan 2024 11:47:48 GMT</pubDate></item></channel></rss>