How 2 mod script to allow zoom work right in orthographic view?

I found a nice “Model Viewer”, below, but it works in Perspective view; when I modify the Camera to Orthographic, the mouse-wheel zoom doesn’t zoom, but rather moves the model up/down.

How can I modify the script so that the zoom by mouse-wheel feature works correctly in Orthographic view?

Original Model Viewer, Perspective view:

Model Viewer moded to Orthorgraphic view:

(using Blender 2.49b)

Oh, and can anyone try to explain to me how the Model Viewer works (to cause model to rotate by LMB)?
I see a sensor for LMB, but it’s not connected to any controller (maybe it’s done in the “use them” section in the script? )

When you move, in orthographic view, the camera closer to the object the object would not scaled up. You must change in orthographic view the focal of the lens (ortho scaling). In Blender 2.5x you can change the scaling by using python (ortho_scale). But in Blender 2.49 this parameter is missing. So the only thing what you can do is to scale up the object.

The LMB sensor is connected to the Empty. You have only selected the camera and “Link” button on the controler was off. That was the reason why you can’t see the link to the empty controllers. So you have two options to see the link. Select both objects or enable the “Link” button on the controller.

Thank you!


  1. What is “Module Camera.zoom”?
  2. If I wanted to replace the gun(s) with the Monkey, similar size, how would I do that?
  3. Are the Curves used for anything?
  1. A module is similar to a normal script. But in addition, a module can contain several functions (def) or classes (class). A module must end with .py. To call a function in the Python module controller you must type in the ModuleName.FunctionName.
  2. Delete the gun(s) parent (Ctrl+P) the monky to the emtpy. The Object must have a scaling of 1.000. To a apply the scaling to a object press Ctrl+A.
  3. No.

Thanks a lot! I was misunderstanding “module”, but now I get it!

And, truely sorry for being so dense, hopefully one last question (fat chance, but we can hope, I guess):
To try to set scale to 1.000, I select monkey, press ctrl-A, get a popup menu, selected “Scale to ObData”, and nothing happened.
What obvious thing am I not getting now?

Ok, here’s what I’ve been able to do so far:
bring monkey into your zoom fix of the model viewer, centered around empty; make it child to empty; manually scale monkey to be reasonable size; make monkey smooth; get rid of one gun.
And here’s the blend of that:


  1. minor: can’t get rid of the other gun (if I do, can’t see monkey either);
  2. MAJOR: rotating the monkey is just a first experiment; my intention is to view a large set of model parts imported as .stl files, and they all have to be identically scaled, as they fit together, so I was hoping to be able to import them and then apply a specific (albiet yet to be determined) numeric scale to them all (or however many I import at any particular time to experiment with what I might want to do with them and then apply the same scale to rest as I import them); so manually scaleing them to some approximate size isn’t good.
  1. Delete the connection to the Python controller with the visibility script. The script calls an object which is not existing.
  2. I don’t see any problem with that.

Ok, I see a 3rd problem, which I’ll describe below.

Ok, I can make the remaining gun disappear by deleting both (there are two) connections to the Python controller with the visibility script, and then deleting the gun itself.

Ok, I think I see what you mean, maybe set the scale of model parts on import, but I’ll wait to try that until problem #3 below resolves.

Problem 3: model jerks if the first time LMB clicked is before mouse has been moved (initial position of cursor).

cursor is initially caused to be in center of screen, and any (even slightest) mouse movement repositions cursor to where it was on entry to BGE, from which point LMB makes reasonable model movement;
however, if LMB before any mouse movement, then the model jerks to some other orientation.

I see there is code in “mouselook” script that seems to intend to make such a jerky movement not happen, but I don’t understand it well enough to attempt to “fix” it,
so I’ll show it below, in the hopes that you might see what’s going wrong.

Here is the code I think is relevant, but I’m not sure it will display correctly, it looked ok when I copied to here:
[edit] (manually indented below, as it did NOT show correctly after post; hope this looks right)
[edit2] ok, that didn’t work either; how do I post code correctly?

############################### Get the mouse movement
def mouseMove(pos):

distance moved from screen center

x = pos[0] - mouse.position[0]
y = pos[1] - mouse.position[1]

intialize mouse so it doesn’t jerk first time

if hasattr(GameLogic, ‘init’) == False:
x = 0
y = 0
GameLogic.init = True

return (x, y)

if lmb_init:
own[“pos”] = mouse.position

if lmb.positive:
pos = mouseMove(own[“pos”])
pos = [0, 0]


Here’s what I think I understand of the code (& I include this so you will see that I’m trying to understand what’s going on, from a position of NOT understanding Python):
I’m presuming that “def” means “define a function”, and that therefore the code down to and including the “return” will NOT execute until the function is called, but the two “if” statements immediately below the “return” (the second of which can call the function above it) WILL execute any time the script is entered.

If the script is entered for/from the first time the LMB is pressed (from Sensor “LMBInit”, with one pulse), then the first “if” statement after the “return” is true, and the indented statement under it is executed, which I think means a new variable section named “pos” within/under the “current controller owner” is given the x-y values of the current position of the mouse, and I think maybe that’s intended to be the position of the cursor (which might set the position of the cursor?).

Now, whether or not the script is being entered for the first time, the next “if” is evaluated, and I think it means “if the LMB has been pressed”, then go to the function, (which is where things get convoluted for me), and use the returned values to set the position of the cursor(?), or, if the LMB was not pressed, then set the cursor to the center of the screen(?).

Now it’s the action of the function mouseMove(pos) which I have difficulty following, but here’s what I see:

this function is only called if the LMB has been pressed, IF that’s what “if lmb.positive:” MEANS(I’m not sure that’s what it means!).
it then gets the x-y distance of the mouse from the center of the screen (that’s what the comment says it does, but I’m really not sure how the x-y of “pos” is the center of the screen, always?);

now the next section of code’s comment says “# intialize mouse so it doesn’t jerk first time”, but as best I can understand it, what it does is:
if there is no “attribute” (or variable section?) for “GameLogic” named “init”, then set x-y = 0, and create an “init” attribute for GameLogic;
so, when (next), the values x & y are returned to the calling statement, they can be either 0,0 (if the game was just entered?), or, the distance the mouse was moved from the center of the screen.

Which all means, I think: if the game was just entered, cursor is at center, and if LMB clicked, (and maybe “pos” has the actual original position of the mouse/cursor before the game was entered, which might be used to reposition the cursor to that position on move mouse?), then the function seems (to me) to be returning 0,0, which doesn’t seem to make sense to me, and the end result is that it does NOT prevent the “jerk” movement of the object on LMB click-before-move and then move.


To post a code, press the go advanced button. Press the # button and paste the code between the two CODE /CODE.

Yes, the code is not well written.
The problem is that on the startup of the game engine the the mouse position is 0 and when you move first time the mouse you get the actual position e.g. 432.So you get a big position difference. You can initialize the old position value (own[“pos”]) with the actual position before the script is calculating the difference. But there is a second problem. Sometime it could happen the the first values are negative. You can fix that when you make the value absolute ( abs() ).

###########################  Logic Bricks
# Get controller
controller = GameLogic.getCurrentController()
own = controller.owner
# Get sensor named Mouse
mouse = controller.sensors["Mouse"]
lmb = controller.sensors["LMB"]
lmb_init = controller.sensors["LMBinit"].positive
# Get the actuators
rotLeftRight = controller.actuators["LookLeftRight"]
rotUpDown = controller.actuators["LookUpDown"]
############################## init
if hasattr(GameLogic, 'init') == False:
 # intialize mouse so it doesn't jerk first time
 GameLogic.init = True
 own["pos"] = abs(mouse.position)
############################### Get the mouse movement
def mouseMove(pos):
 # distance moved from screen center    
 x = pos[0] - mouse.position[0]
 y = pos[1] - mouse.position[1]
 return (x, y)
if lmb_init:
 own["pos"] = mouse.position
print own["pos"]
if lmb.positive:
 pos = mouseMove(own["pos"])
 pos = [0, 0]
print pos 
######## Figure out how much to rotate camera and player ########
# Mouse sensitivity
sensitivity = 0.005
# Amount, direction and sensitivity
leftRight = pos[0] * sensitivity
upDown = pos[1] * sensitivity
# invert upDown
upDown = -upDown
leftRight = -leftRight
######### Use actuators to rotate camera and player #############
# Set the rotation values
rotLeftRight.dRot = [0, 0, leftRight]
rotUpDown.dRot = [0, upDown, 0]
rotLeftRight.useLocalDRot = False
rotUpDown.useLocalDRot = False  #d added this
# Use them

Or you can set the mouse position to middle of the screen in the cursor script, when you start the game engine. You must enable the Level button on the mouse over any sensor. That fix a second problem with the mouse cursor jumping to.

import GameLogic as GL
import Rasterizer as R
cont = GL.getCurrentController()
own = cont.owner
cursor = cont.actuators["CursorGraphics"].owner
if "init" not in own:
 own["init"] = True
 width = R.getWindowWidth()
 height = R.getWindowHeight()
 R.setMousePosition(width//2, height//2)  
mouse = cont.sensors["Mouse"]
if mouse.positive:
 pos = mouse.hitPosition
 cursor.position = [pos[0], pos[1], 0.1]
  1. All correct.
  2. Own[“pos”] is a property that sore the old position value. If the property don’t exist on the object it will be created from the script. Yes it reads out the cursor position and stores it in the Own[“pos”]. No the cursor will not set by the script. Rest correct.
    3.4.5. It calls the function which is calculation the difference between the old mouse value and the actual position. It does not set the mouse position. When the muse is released the difference will be set to 0.
  3. That is an initialization. The IF function checks if the global variable init (GameLogic.init) are not (==False) existing. If that so it initialize the local variable x and y with 0 and generate the global variable init (GameLogic.init). Next time when the script is called the global variable init are existing then the if statement will be not executed.
  4. Not correct. The script only calculate the mouse move difference between two mouse sensor pulses (LMBinit with true pulse and tab) .

P.S. I only change the mouse look that it work. I don’t polished the code. When I have time I make a easier to understanding script.

ok, thanks for indicating where I have somewhat understood the script code, and where I did not! That’s very helpful! I’m still trying to digest what you’ve said. :slight_smile:

Problems with the new mouselook script:

  1. Python didn’t like “own[“pos”] = abs(mouse.position)”, it threw an error, which I think meant that you can’t ask it to take an absolute value of a list of values, so I changed that to “own[“pos”] = abs(mouse.position[0]), abs(mouse.position[1])”, in the hopes that that was a reasonable and maybe even correct statement, & it seemed to work, your debug print statements were then reached and executed. (and once or twice I think I saw the results as would be expected, some minus values became positive).

  2. The script didn’t fix the “jerk” problem (at least not after my attempt at fix, above), here’s what I’m still seeing:
    a) on BGE entry, one of two things happens:
    – 1. the funny cursor starts in the middle of the screen, and stays there; or,
    – 2. the funny cursor starts in the middle of the screen, and then jumps to where the Blender cursor had been when “p” was pressed.

b) then, there are three different things that can occur in relation to pressing LMB:
– 1) when the funny cursor stays in the middle of the screen, if I press LMB, and then move the mouse, the cursor jumps to where it had been when “p” was pressed, and the model suddenly spins to some very different orientation in a jerk;
– 2) and when the funny cursor stays in the middle of the screen, but if I first move the mouse before I press LMB, and then press LMB and move the mouse, there’s no problem, the model moves as it should;
–3) or, when the funny cursor suddenly moves on BGE entry quickly “on its own” to where the Blender cursor was before press “P”, if I then press LMB and move the mouse, again there’s no problem, the model moves as it should.

Here’s my blend with your script replacing the original mouselook (when I first replaced it, I messed up, renamed the original to “WASmouselook”, named yours to “mouselook”, then tested it, no change in the problem at all; then I saw that by renaming it, the mouselook sensor picked up on the “new” name, “WASmouselook”, so the same original script was running! When I changed the sensor name, then it ran your script):

    1. No I have tried it. The script are working. When you copy the script you must check the tabs (or spaces) in the script under the functions and the if statements.
      I don’t looked on your file yet. But I uploaded my test file.

You’re right, your test file works, no surprise there, thanks for uploding it, I’ll try to see what I did wrong.

both scripts needed:
ok, I think I finally got it: I had only copied your mouselook script over into my test file, because I misunderstood when you posted your mouselook script above with abs(), you said OR “you can set the mouse position to middle of the screen in the cursor script”, so I thought there were two different solutions, and started testing the first (mouselook) script all by itself, not realizing that apparently both were needed.

separate thread for solution to jerk on entry problem?
I wonder if the end of the thread relating to the jerk on entry problem should have its own thread, in case other people search for solution to same problem, & if so, can a part of a thread be split off into another thread, and how to do it?

Oh, and if so, how would I indicateProblem Solved” for the thread, as I’ve seen on other threads?

blends comparator program?
It took me a while to realize what I’d misunderstood; I wonder if there’s a “compare one Blend to another similar Blend file”, to spit out any differences? I think I’d have found my mistake faster if the computer were doing the labor of looking for differences is why I ask.

re: indentation:
I did notice that when I copy/pasted your script from the code displayed above here on this forum, that it had different indentations (less amount of indentation than a regular tab), and when I first saw that Python “if” statements didn’t have “end” statements, I concluded that any indentation allows proper parsing of “if” statements & their contents (I may have tested it to be sure), so my original copy/paste should have been ok, I think.

your mouselook script in my test file:
So anyway, I copied your mouselook script directly from your blend file into my test file, and the same jerk problem occurs, so I’m looking more carefully at my logic blocks in comparison to yours; so far no joy.
(see edit above: I neglected to also copy your cursor script into my test file; with it and mouselook, jerk problem is solved!)

abs error:
But I am still getting the same “abs” error from your test file, even though your test file operates fine; here’s what it looks like:

Compiled with Python version 2.6.2.
Checking for installed Python… got it!
Detected GL_ARB_texture_env_combine
Detected GL_ARB_texture_cube_map
Detected GL_ARB_multitexture
Detected GL_ARB_shader_objects
Detected GL_ARB_vertex_shader
Detected GL_ARB_fragment_shader
Detected GL_ARB_vertex_program
Detected GL_ARB_depth_texture
Detected GL_EXT_separate_specular_color
Blender Game Engine Started
Python script error from controller “mouselook#CONTR#1”:
Traceback (most recent call last):
File “mouselook”, line 20, in <module>
TypeError: bad operand type for abs(): ‘list’
Python script error from controller “mouselook#CONTR#1”:
Traceback (most recent call last):
File “mouselook”, line 32, in <module>
KeyError: ‘value = gameOb[key]: KX_GameObject, key “pos” does not exist’
Python script error from controller “mouselook#CONTR#1”:
Traceback (most recent call last):
File “mouselook”, line 32, in <module>
KeyError: ‘value = gameOb[key]: KX_GameObject, key “pos” does not exist’
Python script error from controller “mouselook#CONTR#1”:
Traceback (most recent call last):
File “mouselook”, line 32, in <module>
KeyError: ‘value = gameOb[key]: KX_GameObject, key “pos” does not exist’
Blender Game Engine Finished

To edit 1:
No you need only one of the two scripts.
The new mouselook script only fix the jerking problem. The new cursor script fix the jerking and the mouse cursor jump problem.
I put in both scripts in to the file so you have both. But you can use both new scrips.
To edit2:
I don’t know how to split a tread. But I think only a administrator can do this.
To mark the thread as “Solved” press the “Thread Tools” button on and select “Mark this thread as solved…”.
To edit 3:
No there is no compare function in Blender.
For the moment remove the abs().

Not sure why the single mouselook script doesn’t fix the jerk for me, but using the two together works fine, so I’ll just do that.

Regarding the abs() function, I make this change and the errors go away:
#own[“pos”] = abs(mouse.position) # was this
own[“pos”] = abs(mouse.position[0]) , abs(mouse.position[1]) # changed it to this

clue for me was: TypeError: bad operand type for abs(): ‘list’
makes me think Python doesn’t like to operate the absolute function on all the items in a list?
Just a guess, I don’t know Python.