diff --git a/doc/python_api/examples/bpy.types.RenderEngine.py b/doc/python_api/examples/bpy.types.RenderEngine.1.py similarity index 96% rename from doc/python_api/examples/bpy.types.RenderEngine.py rename to doc/python_api/examples/bpy.types.RenderEngine.1.py index 0b8795340ad..6c2558f85cf 100644 --- a/doc/python_api/examples/bpy.types.RenderEngine.py +++ b/doc/python_api/examples/bpy.types.RenderEngine.1.py @@ -5,8 +5,6 @@ Simple Render Engine import bpy import array -import gpu -from gpu_extras.presets import draw_texture_2d class CustomRenderEngine(bpy.types.RenderEngine): @@ -95,6 +93,10 @@ class CustomRenderEngine(bpy.types.RenderEngine): # Blender will draw overlays for selection and editing on top of the # rendered image automatically. def view_draw(self, context, depsgraph): + # Lazily import GPU module, so that the render engine works in + # background mode where the GPU module can't be imported by default. + import gpu + region = context.region scene = depsgraph.scene @@ -116,6 +118,8 @@ class CustomRenderEngine(bpy.types.RenderEngine): class CustomDrawData: def __init__(self, dimensions): + import gpu + # Generate dummy float image buffer self.dimensions = dimensions width, height = dimensions @@ -134,6 +138,7 @@ class CustomDrawData: del self.texture def draw(self): + from gpu_extras.presets import draw_texture_2d draw_texture_2d(self.texture, (0, 0), self.texture.width, self.texture.height) diff --git a/doc/python_api/examples/bpy.types.RenderEngine.2.py b/doc/python_api/examples/bpy.types.RenderEngine.2.py new file mode 100644 index 00000000000..e2bf261b261 --- /dev/null +++ b/doc/python_api/examples/bpy.types.RenderEngine.2.py @@ -0,0 +1,36 @@ +""" +GPU Render Engine ++++++++++++++++++ +""" + +import bpy + + +class CustomGPURenderEngine(bpy.types.RenderEngine): + bl_idname = "CUSTOM_GPU" + bl_label = "Custom GPU" + + # Request a GPU context to be created and activated for the render method. + # This may be used either to perform the rendering itself, or to allocate + # and fill a texture for more efficient drawing. + bl_use_gpu_context = True + + def render(self, depsgraph): + # Lazily import GPU module, since GPU context is only created on demand + # for rendering and does not exist on register. + import gpu + + # Perform rendering task. + pass + + +def register(): + bpy.utils.register_class(CustomGPURenderEngine) + + +def unregister(): + bpy.utils.unregister_class(CustomGPURenderEngine) + + +if __name__ == "__main__": + register() diff --git a/source/blender/blenkernel/intern/fmodifier.cc b/source/blender/blenkernel/intern/fmodifier.cc index 06c416261b0..5afac449d53 100644 --- a/source/blender/blenkernel/intern/fmodifier.cc +++ b/source/blender/blenkernel/intern/fmodifier.cc @@ -624,7 +624,7 @@ static float fcm_cycles_time( { const FMod_Cycles *data = (FMod_Cycles *)fcm->data; tFCMED_Cycles *storage = static_cast(storage_); - float prevkey[2], lastkey[2], cycyofs = 0.0f; + float firstkey[2], lastkey[2], cycyofs = 0.0f; short side = 0, mode = 0; int cycles = 0; float ofs = 0; @@ -642,11 +642,11 @@ static float fcm_cycles_time( /* calculate new evaltime due to cyclic interpolation */ if (fcu->bezt) { - const BezTriple *prevbezt = fcu->bezt; - const BezTriple *lastbezt = prevbezt + fcu->totvert - 1; + const BezTriple *firstbezt = &fcu->bezt[0]; + const BezTriple *lastbezt = &fcu->bezt[fcu->totvert - 1]; - prevkey[0] = prevbezt->vec[1][0]; - prevkey[1] = prevbezt->vec[1][1]; + firstkey[0] = firstbezt->vec[1][0]; + firstkey[1] = firstbezt->vec[1][1]; lastkey[0] = lastbezt->vec[1][0]; lastkey[1] = lastbezt->vec[1][1]; @@ -656,8 +656,8 @@ static float fcm_cycles_time( const FPoint *prevfpt = fcu->fpt; const FPoint *lastfpt = prevfpt + fcu->totvert - 1; - prevkey[0] = prevfpt->vec[0]; - prevkey[1] = prevfpt->vec[1]; + firstkey[0] = prevfpt->vec[0]; + firstkey[1] = prevfpt->vec[1]; lastkey[0] = lastfpt->vec[0]; lastkey[1] = lastfpt->vec[1]; @@ -667,12 +667,12 @@ static float fcm_cycles_time( * 1) if in data range, definitely don't do anything * 2) if before first frame or after last frame, make sure some cycling is in use */ - if (evaltime < prevkey[0]) { + if (evaltime < firstkey[0]) { if (data->before_mode) { side = -1; mode = data->before_mode; cycles = data->before_cycles; - ofs = prevkey[0]; + ofs = firstkey[0]; } } else if (evaltime > lastkey[0]) { @@ -690,17 +690,18 @@ static float fcm_cycles_time( /* find relative place within a cycle */ { /* calculate period and amplitude (total height) of a cycle */ - const float cycdx = lastkey[0] - prevkey[0]; - const float cycdy = lastkey[1] - prevkey[1]; + const float cycdx = lastkey[0] - firstkey[0]; + const float cycdy = lastkey[1] - firstkey[1]; /* check if cycle is infinitely small, to be point of being impossible to use */ if (cycdx == 0) { return evaltime; } - /* calculate the 'number' of the cycle */ - const float cycle = (float(side) * (evaltime - ofs) / cycdx); - + /* Calculate the 'number' of the cycle. Needs to be a double to combat precision issues like + * #119360. With floats it can happen that the `cycle` jumps to the next full number, while + * `cyct` below is still behind. */ + const double cycle = side * (double(evaltime) - double(ofs)) / double(cycdx); /* calculate the time inside the cycle */ const float cyct = fmod(evaltime - ofs, cycdx); @@ -730,10 +731,10 @@ static float fcm_cycles_time( /* special case for cycle start/end */ if (cyct == 0.0f) { - evaltime = (side == 1 ? lastkey[0] : prevkey[0]); + evaltime = (side == 1 ? lastkey[0] : firstkey[0]); if ((mode == FCM_EXTRAPOLATE_MIRROR) && (int(cycle) % 2)) { - evaltime = (side == 1 ? prevkey[0] : lastkey[0]); + evaltime = (side == 1 ? firstkey[0] : lastkey[0]); } } /* calculate where in the cycle we are (overwrite evaltime to reflect this) */ @@ -744,7 +745,7 @@ static float fcm_cycles_time( * (result of fmod will be negative, and with different phase). */ if (side < 0) { - evaltime = prevkey[0] - cyct; + evaltime = firstkey[0] - cyct; } else { evaltime = lastkey[0] - cyct; @@ -752,9 +753,9 @@ static float fcm_cycles_time( } else { /* the cycle is played normally... */ - evaltime = prevkey[0] + cyct; + evaltime = firstkey[0] + cyct; } - if (evaltime < prevkey[0]) { + if (evaltime < firstkey[0]) { evaltime += cycdx; } }