Levente Uzonyi uploaded a new version of Files to project The Trunk:
http://source.squeak.org/trunk/Files-ul.172.mcz
==================== Summary ====================
Name: Files-ul.172
Author: ul
Time: 10 October 2017, 12:21:24.555739 am
UUID: 0eb643b4-cff4-4874-8025-94d83d768448
Ancestors: Files-eem.171
- synchronize the underlying file stream of CurrentReadOnlySourceFiles and SourceFiles before read in RemoteString >> #text
=============== Diff against Files-eem.171 ===============
Item was changed:
----- Method: RemoteString>>text (in category 'accessing') -----
text
"Answer the receiver's string asText if remote files are enabled."
| theFile |
theFile := (CurrentReadOnlySourceFiles at: (sourceFileNumber ifNil: [ ^nil ])) ifNil: [ ^nil ].
+ theFile size <= filePositionHi ifTrue: [
+ "SourceFiles might have been appended to since theFile was opened. Flush the written data and reopen theFile to make it see the changes."
+ (SourceFiles at: sourceFileNumber) flush.
+ theFile reopen. "Currently the only way to re-read the size field of a read-only file on unix..." ].
theFile size < filePositionHi ifTrue: [
self error: 'RemoteString past end of file' ].
^theFile
position: filePositionHi;
nextChunkText!
Tobias Pape uploaded a new version of Help-Squeak-TerseGuide to project The Trunk:
http://source.squeak.org/trunk/Help-Squeak-TerseGuide-topa.7.mcz
==================== Summary ====================
Name: Help-Squeak-TerseGuide-topa.7
Author: topa
Time: 7 October 2017, 1:20:21.797484 pm
UUID: 043213fa-d7ab-49a1-ac2d-e370a65c54c7
Ancestors: Help-Squeak-TerseGuide-pre.6
Fix symbols
=============== Diff against Help-Squeak-TerseGuide-pre.6 ===============
Item was changed:
----- Method: TerseGuideHelp class>>symbol (in category 'pages') -----
symbol
^HelpTopic
title: 'Symbol'
contents:
'"************************************************************************
* Symbol: *
************************************************************************"
| b x y |
x := #Hello. "symbol assignment"
+ y := #Symbol, ''Concatenation''. "symbol concatenation (result is string)"
- y := ''String'', ''Concatenation''. "symbol concatenation (result is string)"
b := x isEmpty. "test if symbol is empty"
y := x size. "string size"
y := x at: 2. "char at location"
y := x copyFrom: 2 to: 4. "substring"
y := x indexOf: $e ifAbsent: [0]. "first position of character within string"
x do: [:a | Transcript show: a printString; cr]. "iterate over the string"
b := x allSatisfy: [:a | (a >= $a) & (a <= $z)]. "test if all elements meet condition"
y := x select: [:a | a > $a]. "return all elements that meet condition"
y := x asString. "convert symbol to string"
y := x asText. "convert symbol to text"
y := x asArray. "convert symbol to array"
y := x asOrderedCollection. "convert symbol to ordered collection"
y := x asSortedCollection. "convert symbol to sorted collection"
y := x asBag. "convert symbol to bag collection"
y := x asSet. "convert symbol to set collection"
'!
Marcel Taeumel uploaded a new version of ToolBuilder-Morphic to project The Trunk:
http://source.squeak.org/trunk/ToolBuilder-Morphic-mt.197.mcz
==================== Summary ====================
Name: ToolBuilder-Morphic-mt.197
Author: mt
Time: 5 October 2017, 8:50:50.594923 am
UUID: b60282f3-e8d4-4b4d-86e4-74ab5c91f62b
Ancestors: ToolBuilder-Morphic-tpr.196
To avoid confusion with the old "morphic/mvc open" pattern, rename the ToolBuilder-initiated opening for morphs from #morphicOpenWith: to #openAsTool. Drop the argument because that event check for "open window at hand" was really global and the tool builder does not have anything to do with it. Browse #currentEvent if you want to learn more about that.
Note that there is no need to hint about "morphic" in that selector because (1) "ToolBuilder-Morphic" is already a Morphic-specific package and (2) all the implementors are actual morphs.
=============== Diff against ToolBuilder-Morphic-tpr.196 ===============
Item was removed:
- ----- Method: DialogWindow>>morphicOpenWith: (in category '*ToolBuilder-Morphic-opening') -----
- morphicOpenWith: aMorphicToolBuilder
-
- ^ self
- moveToHand;
- getUserResponse!
Item was added:
+ ----- Method: DialogWindow>>openAsTool (in category '*ToolBuilder-Morphic-opening') -----
+ openAsTool
+
+ self flag: #fishy. "mt: Why does the dialog not return its Morphic form but data?"
+ ^ self
+ moveToHand;
+ getUserResponse!
Item was removed:
- ----- Method: MenuMorph>>morphicOpenWith: (in category '*ToolBuilder-Morphic-opening') -----
- morphicOpenWith: aMorphicToolBuilder
-
- self popUpInWorld: World.
- ^ super morphicOpenWith: aMorphicToolBuilder!
Item was added:
+ ----- Method: MenuMorph>>openAsTool (in category '*ToolBuilder-Morphic-opening') -----
+ openAsTool
+
+ self popUpInWorld: World.!
Item was removed:
- ----- Method: Morph>>morphicOpenWith: (in category '*ToolBuilder-Morphic-opening') -----
- morphicOpenWith: aMorphicToolBuilder
-
- ^ self openInWorld!
Item was added:
+ ----- Method: Morph>>openAsTool (in category '*ToolBuilder-Morphic-opening') -----
+ openAsTool
+
+ self openInWorld.!
Item was changed:
----- Method: MorphicToolBuilder>>open: (in category 'opening') -----
open: anObject
"Build and open the object. Answer the widget opened."
+ ^ (self build: anObject) openAsTool!
- ^ (self build: anObject) morphicOpenWith: self!
Item was removed:
- ----- Method: SystemWindow>>morphicOpenWith: (in category '*ToolBuilder-Morphic-opening') -----
- morphicOpenWith: aMorphicToolBuilder
-
- | morph |
- morph := self openInWorldExtent: self extent.
- (Project uiManager openToolsAttachedToMouseCursor
- and: [ | event |
- event := aMorphicToolBuilder currentEvent.
- event isMouse and: [event isMouseUp]])
- ifTrue: [
- morph setProperty: #initialDrop toValue: true.
- morph hasDropShadow: false.
- aMorphicToolBuilder currentHand attachMorph: morph].
- ^ morph
- !
Item was added:
+ ----- Method: SystemWindow>>openAsTool (in category '*ToolBuilder-Morphic-opening') -----
+ openAsTool
+ "Open this window as a tool, that is, honor the preferences such as #reuseWindows and #openToolsAttachedToMouseCursor."
+
+ | meOrSimilarWindow |
+ meOrSimilarWindow := self openInWorldExtent: self extent.
+ (Project uiManager openToolsAttachedToMouseCursor
+ and: [ | event |
+ event := self currentEvent.
+ event isMouse and: [event isMouseUp]])
+ ifTrue: [
+ meOrSimilarWindow setProperty: #initialDrop toValue: true.
+ meOrSimilarWindow hasDropShadow: false.
+ self currentHand attachMorph: meOrSimilarWindow].
+ ^ meOrSimilarWindow
+ !
Tobias Pape uploaded a new version of EToys to project The Trunk:
http://source.squeak.org/trunk/EToys-topa.307.mcz
==================== Summary ====================
Name: EToys-topa.307
Author: topa
Time: 4 October 2017, 2:50:50.655952 pm
UUID: c75ac142-2eb0-4153-b7f2-d1acd65e66b4
Ancestors: EToys-tpr.306
Fix and Improve WebCamMorph (try it!)
FYI: Windows-DLL is at https://github.com/OpenSmalltalk/opensmalltalk-vm/raw/Cog/platforms/win32/p…
Aside: make Tetris appear in objects -> games
=============== Diff against EToys-tpr.306 ===============
Item was added:
+ ----- Method: Player>>getShowFPS (in category '*Etoys-Squeakland-MorphicExtras-WebCam') -----
+ getShowFPS
+ ^ self getValueFromCostume: #getShowFPS!
Item was added:
+ ----- Method: Player>>getWebCamOrientation (in category '*Etoys-Squeakland-MorphicExtras-WebCam') -----
+ getWebCamOrientation
+ ^ self getValueFromCostume: #getWebCamOrientation!
Item was added:
+ ----- Method: Player>>setShowFPS: (in category '*Etoys-Squeakland-MorphicExtras-WebCam') -----
+ setShowFPS: aBoolean
+ self setCostumeSlot: #setShowFPS: toValue: aBoolean!
Item was added:
+ ----- Method: Player>>setWebCamOrientation: (in category '*Etoys-Squeakland-MorphicExtras-WebCam') -----
+ setWebCamOrientation: aSymbol
+ costume renderedMorph setWebCamOrientation: aSymbol!
Item was changed:
----- Method: Tetris class>>descriptionForPartsBin (in category 'parts bin') -----
descriptionForPartsBin
^ self partName: 'Tetris' translatedNoop
+ categories: {'Games' translatedNoop}
- categories: #()
documentation: 'Tetris, yes Tetris' translatedNoop!
Item was changed:
RectangleMorph subclass: #WebCamMorph
+ instanceVariableNames: 'camNum camIsOn frameExtent displayForm resolution useFrameSize captureDelayMs showFPS framesSinceLastDisplay lastDisplayTime fps orientation'
- instanceVariableNames: 'camNum camIsOn frameExtent displayForm resolution useFrameSize captureDelayMs'
classVariableNames: ''
poolDictionaries: ''
category: 'Etoys-Squeakland-MorphicExtras-WebCam'!
!WebCamMorph commentStamp: '<historical>' prior: 0!
INTRODUCTION
=========
WebCamMorph together with CameraPlugin (originally from MIT Scratch) provides an easy and cross platform way to use webcam input in Squeak and Etoys. The first version has been created specifically with Etoys in mind. To view a live feed simply drag a "WebCam" tile from the "WebCam" category in the objects tool. Open up a viewer on the morph and display the "camera settings" category to explore the following basic settings:
"camera is on": turn the camera on/off.
"camera number": usually the default of "1" is ok but if you have more than one camera connected then adjust between 1 and 9 for other instances of WebCamMorph.
"max fps": leave as is for now. It is unusual for webcams to capture at higher than 30fps. See later for further explanation of how fps is controlled.
"actual fps": read-only. Indicates the actual fps being achieved which can depend significantly on lighting conditions and capture resolution...
"resolution": webcams can have a range of resolutions but for simplicity three are supported: "low" (160x120), "medium" (320x240) and "high" (640x480). Adjust in good lighting to see if "actual fps" increases.
"use frame size": the resolution used for capturing can differ from the resolution used for display. If this setting is true then WebCamMorph is resized to match the camera resolution. If false then you are free to resize it however you want (via the "resize" halo button, use shift to preserve aspect ratio)
Beyond viewing a live feed WebCamMorph has been designed to support different uses including simple effects, time-lapse photography, stop-motion animation, character recognition, motion detection and more complex processing of every frame for feature detection. The following information is to help you understand how and why WebCamMorph operates so you can adjust it for your particular needs.
"FRAMES PER SECOND", LIGHTING & CAMERA RESOLUTION
==================================
The maximum possible frame rate depends on many factors, some of which are outside of our control. Frame rates differ between cameras and usually depend significantly on chosen resolution and lighting conditions. To ensure a balance between capturing every available frame and keeping everything else responsive, WebCamMorph dynamically adjusts the delay between capturing one frame and the next (does not apply when in "manual capture" mode, see later).
WebCams often include automatic compensation for lighting conditions. In low lighting it takes significantly more time for the camera to get a picture than it does in good lighting conditions. For example 30fps may be possible with good lighting compared to 7fps in low lighting. So for best capture rates ensure you have good lighting!!
Cameras have a "native" resolution at which frame rates are usually better than for other resolutions. Note though that the native resolution might be *higher*
than the *minimum* resolution available. It pays to experiment with different resolutions to find which one results in the highest frame rate. Use good lighting conditions when experimenting with resolutions.
"MANUAL CAPTURE" MODE
===============
In simply usage WebCamMorph automatically captures a frame and displays it. To support Etoys scripting a "manual capture" mode is provided where you or your script determines when to capture, when to apply effects (or not) and when to update the display. In between these steps you can do anything you want. Note that frames rates will be lower than that in automatic capture mode and that "skip frames" (described next) will need adjusting at very low capture rates.
Tip: In manual mode the camera can be turned off. It will be turned on automatically when required and return to it's previous state after a frame has been captured. For capture periods of five seconds or more turning the camera off may save power, which can especially useful when running off batteries. For smaller periods leaving the camera on will avoid some delays and could help speed up webcam related scripts.
"SKIP FRAMES"
========
Webcams and their drivers are typically designed for streaming live video and use internal buffering to help speed things up. At low capture rates the picture can appear to lag real-time because what you see is the next available buffer not the *latest* buffer. So for example if you capture a frame every ten seconds and there are three buffers being used then what you actually see may be thirty seconds old. We have little/no control over the number of buffers used and the actual number can vary between cameras and under different circumstances for the same camera. "skip frames" is provided to compensate for buffering so increase it when doing "manual" capturing until you see what you expect to see. Typically a setting of 8 is enough but I have had to use 20 with one particular camera in low lighting.
"SNAPSHOTS"
========
Where as "capturing" is the process of getting an image from the Camera into Squeak/Etoys, a "snapshot" preserves whatever is currently displayed (which may be the captured image after effects have been applied). To store snapshots you need to designate a "holder" which at the moment can be either a "holder" morph or a "movie" morph. Create one of these before proceeding. To assign a holder open up a viewer for WebCamMorph, display the "snapshot" category and click in the box at the right of the entry called "snapshot holder". The cursor will now resemble a cross-hair and can be clicked on the target holder/movie morph. To take a single snapshot at any time click (!!) on the left of "take snapshot". In auto-capture mode WebCamMorph can also be set to take multiple consecutive snapshots . First, before turning the camera on, set a sensible limit using "snapshot limit" (to avoid using all the computers memory) then set "auto snapshot" to true. When the camera is next turned on then s
napshots are taken for every frame until "snapshot limit" becomes zero. "snapshot limit" is automatically decremented but not reset to avoid problems (although you are free to reset it manually or via a script).
"EFFECTS" - WIP
=========
Similar to snapshots, a holder can be designated as the "effects holder". This holder is intended to be populated with "fx" morphs (coming soon) which will operate on captured frames prior to displaying. Stay tuned ;-)
CLEARING SNAPSHOT & EFFECTS HOLDERS
=========================
Keeping a link to snapshot or effects holders can tie up resources even after the target holders have been deleted and are no longer visible. To ensure this does not happen designate the WebCamMorph itself as the holder (for method see "snapshots" section above).
COMING SOON!!
=========
- Built-in basic effects such as brightness, contrast and hue.
- Image "fx" morphs for effects such as those found in MIT Scratch and many other types of effects/ image processing.
- More snapshot options, eg, store to file
- Demo projects
!
Item was changed:
----- Method: WebCamMorph class>>additionsToViewerCategories (in category 'scripting') -----
additionsToViewerCategories
"Answer a list of (<categoryName> <list of category specs>) pairs that characterize the phrases this kind of morph wishes to add to various Viewer categories."
^ #(
(#'camera' (
+ (slot resolution '160x120, 320x240, 640x480 or 1280x960'
- (slot resolution '160x120, 320x240 or 640x480'
WebCamResolution readWrite Player getWebCamResolution Player setWebCamResolution:)
+ (slot orientation 'Natural (mirrored) or navtive (as from the camera'
+ WebCamOrientation readWrite Player getWebCamOrientation Player setWebCamOrientation:)
(slot cameraIsOn 'Whether the camera is on/off' Boolean readWrite Player getWebCamIsOn Player setWebCamIsOn:)
(slot useFrameSize 'Resize the player to match the camera''s frame size'
Boolean readWrite Player getUseFrameSize Player setUseFrameSize:)
(slot lastFrame 'A player with the last frame' Player readOnly Player getLastFrame unused unused)
+ (slot showFPS 'Whether to show the samera''s frames per second' Boolean readWrite Player getShowFPS Player setShowFPS:)
))
)
!
Item was changed:
----- Method: WebCamMorph class>>resolutionFor: (in category 'scripting') -----
resolutionFor: aSymbol
+ (#(low medium high hd) includes: aSymbol) ifFalse: [^ 320@240].
- (#(#low #medium #high) includes: aSymbol) ifFalse: [^ 320@240].
+ ^ {160 @ 120. 320 @ 240. 640 @ 480. 1280 @ 960}
- ^ {160@120. 320@240. 640@480}
at: (WebCamResolution resolutions indexOf: aSymbol)
!
Item was changed:
----- Method: WebCamMorph>>addCustomMenuItems:hand: (in category 'menu') -----
addCustomMenuItems: aMenu hand: aHandMorph
+
- | item |
super addCustomMenuItems: aMenu hand: aHandMorph.
- item := (camIsOn == true)
- ifTrue: ['turn camera off' translated]
- ifFalse: ['turn camera on' translated].
aMenu
+ addUpdating: #cameraToggleString action: #toggleCameraOnOff;
+ addLine;
+ add: 'resolution...' translated subMenu: ([:menu |
+ WebCamResolution resolutions do: [:res |
+ menu
+ add: (resolution == res ifTrue: ['<on>'] ifFalse: ['<off>']), res translated
+ selector: #setWebCamResolution:
+ argument: res].
+ menu] value: (aMenu class new defaultTarget: aMenu defaultTarget));
+ add: 'orientation...' translated subMenu: ([:menu |
+ WebCamOrientation orientations do: [:ori |
+ menu
+ add: (orientation == ori ifTrue: ['<on>'] ifFalse: ['<off>']), ori translated
+ selector: #setWebCamOrientation:
+ argument: ori].
+ menu] value: (aMenu class new defaultTarget: aMenu defaultTarget));
+ addUpdating: #frameSizeToggleString action: #toggleUseFrameSize;
+ addUpdating: #showFPSToggleString action: #toggleShowFPS;
+ yourself
+ !
- add: item translated
- target: self
- action: #toggleCameraOnOff.
-
-
-
-
- !
Item was added:
+ ----- Method: WebCamMorph>>cameraToggleString (in category 'menu') -----
+ cameraToggleString
+
+ ^ camIsOn
+ ifTrue: ['<on>', 'turn camera off' translated]
+ ifFalse: ['<off>', 'turn camera on' translated].
+
+
+
+ !
Item was added:
+ ----- Method: WebCamMorph>>decreaseCaptureDelay (in category 'accessing') -----
+ decreaseCaptureDelay
+
+ captureDelayMs := (captureDelayMs - 1) min: 200.!
Item was changed:
----- Method: WebCamMorph>>delete (in category 'submorphs-add/remove') -----
delete
+ self class instanceCount > 1
+ ifFalse: [self off]
+ ifTrue: [
+ self stopStepping.
+ camIsOn := false].
- (self class instanceCount > 1)
- ifFalse:[self off]
- ifTrue:[self stopStepping. camIsOn := false].
super delete.!
Item was added:
+ ----- Method: WebCamMorph>>drawCameraImageOn: (in category 'drawing') -----
+ drawCameraImageOn: aCanvas
+ | scale offset |
+ offset := 0 @ 0.
+ scale := 1 @ 1.
+ bounds extent = displayForm extent
+ ifFalse: [scale := bounds extent / displayForm extent].
+ orientation == #natural
+ ifTrue: [
+ scale := scale x negated @ scale y.
+ offset := bounds width @ 0].
+ 1 @ 1 = scale
+ ifTrue: [aCanvas drawImage: displayForm at: bounds origin + offset]
+ ifFalse: [aCanvas
+ warpImage: displayForm
+ transform: (MatrixTransform2x3 withScale: scale)
+ at: bounds origin + offset].
+ !
Item was added:
+ ----- Method: WebCamMorph>>drawFPSOn: (in category 'drawing') -----
+ drawFPSOn: aCanvas
+ showFPS ifFalse: [^self].
+ aCanvas
+ drawString: 'FPS: ', fps asString
+ at: bounds bottomLeft + (5 @ -20)
+ font: Preferences windowTitleFont
+ color: Color white!
Item was changed:
----- Method: WebCamMorph>>drawOn: (in category 'drawing') -----
drawOn: aCanvas
+
useFrameSize ifTrue: [self extent: frameExtent].
+ self drawCameraImageOn: aCanvas.
+ self drawFPSOn: aCanvas.
+ self drawOverlayTextOn: aCanvas.
- aCanvas
- drawImage: (
- (self extent = displayForm extent)
- ifTrue: [displayForm]
- ifFalse: [displayForm scaledToSize: self extent]
- ) at: bounds origin.
!
Item was added:
+ ----- Method: WebCamMorph>>drawOverlayTextOn: (in category 'drawing') -----
+ drawOverlayTextOn: aCanvas
+ camIsOn ifTrue: [^self].
+ aCanvas
+ drawString: 'Camera is off' translated
+ at: bounds origin + (5 @ 2)
+ font: Preferences windowTitleFont
+ color: Color white.!
Item was added:
+ ----- Method: WebCamMorph>>frameSizeToggleString (in category 'menu') -----
+ frameSizeToggleString
+
+ ^ (useFrameSize ifTrue: ['<on>'] ifFalse: ['<off>']), 'use frame size' translated
+
+
+ !
Item was added:
+ ----- Method: WebCamMorph>>getShowFPS (in category 'e-toy - settings') -----
+ getShowFPS
+ ^ showFPS
+ !
Item was added:
+ ----- Method: WebCamMorph>>increaseCaptureDelay (in category 'accessing') -----
+ increaseCaptureDelay
+
+ captureDelayMs := (captureDelayMs + 1) max: 10.!
Item was changed:
----- Method: WebCamMorph>>initialize (in category 'initialization') -----
initialize
super initialize.
camNum := 1.
camIsOn := false.
+ showFPS := false.
+ captureDelayMs := 16. "stepTime"
+ fps := 60. "guess."
+ lastDisplayTime := 0.
+ framesSinceLastDisplay := 0.
- captureDelayMs := 0. "stepTime"
useFrameSize := false.
+ resolution := #medium.
+ orientation := #natural.
- resolution := #'medium'.
frameExtent := self class resolutionFor: resolution.
+ self initializeDisplayForm.
- displayForm := Form extent: frameExtent depth:32.
self extent: frameExtent.
self on.
!
Item was added:
+ ----- Method: WebCamMorph>>initializeDisplayForm (in category 'initialization') -----
+ initializeDisplayForm
+ | cameraExtent formExtent |
+
+ cameraExtent := CameraInterface frameExtent: camNum.
+ cameraExtent isZero
+ ifTrue: [formExtent := frameExtent]
+ ifFalse: [ | camRatio frameRatio |
+ formExtent := cameraExtent.
+ camRatio := cameraExtent x / cameraExtent y.
+ frameRatio := frameExtent x / frameExtent y.
+ camRatio ~= frameRatio ifTrue: [frameExtent := frameExtent x @ (frameExtent x * camRatio reciprocal)]].
+ displayForm := Form extent: formExtent depth: 32.
+ self extent: frameExtent.
+ !
Item was added:
+ ----- Method: WebCamMorph>>knownName (in category 'testing') -----
+ knownName
+
+ ^ CameraInterface cameraName: camNum !
Item was changed:
----- Method: WebCamMorph>>nextFrame (in category 'stepping and presenter') -----
nextFrame
+ | frameCount |
+ frameCount := CameraInterface getFrameForCamera: camNum into: displayForm bits.
+ frameCount = 0 ifTrue: [self increaseCaptureDelay].
+ frameCount > 2 ifTrue: [self decreaseCaptureDelay].
+ framesSinceLastDisplay := framesSinceLastDisplay + frameCount!
- CameraInterface getFrameForCamera: camNum into: displayForm bits.
- !
Item was changed:
----- Method: WebCamMorph>>on (in category 'accessing') -----
on
(CameraInterface cameraIsOpen: camNum)
ifTrue: [ ^camIsOn := true.].
+ (CameraInterface openCamera: camNum width: frameExtent x height: frameExtent y)
- (CameraInterface
- openCamera: camNum
- width: frameExtent x
- height: frameExtent y)
ifNil: [^false].
+ CameraInterface waitForCameraStart: camNum.
+ self initializeDisplayForm.
+ self extent: frameExtent.
- (Delay forSeconds: 2) wait.
- displayForm := Form extent: frameExtent depth:32.
camIsOn := true.
self startStepping.
!
Item was added:
+ ----- Method: WebCamMorph>>setShowFPS: (in category 'e-toy - settings') -----
+ setShowFPS: aBoolean
+ showFPS := aBoolean
+ !
Item was added:
+ ----- Method: WebCamMorph>>setWebCamOrientation: (in category 'e-toy - settings') -----
+ setWebCamOrientation: aSymbol
+
+ ((WebCamOrientation orientations) includes: aSymbol) ifFalse: [^ self].
+ orientation := aSymbol.
+
+
+ !
Item was added:
+ ----- Method: WebCamMorph>>showFPSToggleString (in category 'menu') -----
+ showFPSToggleString
+
+ ^ (showFPS ifTrue: ['<on>'] ifFalse: ['<off>']), 'show fps' translated
+
+
+ !
Item was added:
+ ----- Method: WebCamMorph>>toggleShowFPS (in category 'menu') -----
+ toggleShowFPS
+
+ showFPS := showFPS not.
+ !
Item was added:
+ ----- Method: WebCamMorph>>toggleUseFrameSize (in category 'menu') -----
+ toggleUseFrameSize
+
+ useFrameSize := useFrameSize not.
+ !
Item was changed:
----- Method: WebCamMorph>>updateDisplay (in category 'stepping and presenter') -----
updateDisplay
+ camIsOn ifTrue:[self nextFrame].
+ self updateFPS.
+ self changed.!
- camIsOn
- ifFalse: [displayForm getCanvas
- drawString: 'Camera is off' translated
- at: 5 @ 2
- font: Preferences windowTitleFont
- color: Color white.
- ]
- ifTrue:[self nextFrame].
- self changed.!
Item was added:
+ ----- Method: WebCamMorph>>updateFPS (in category 'stepping and presenter') -----
+ updateFPS
+
+ | now mSecs |
+ now := Time millisecondClockValue.
+ mSecs := now - lastDisplayTime.
+ (mSecs > 500 or: [mSecs < 0 "clock wrap-around"])
+ ifTrue: [
+ fps := (framesSinceLastDisplay * 1000) // mSecs.
+ lastDisplayTime := now.
+ framesSinceLastDisplay := 0].!
Item was added:
+ SymbolListType subclass: #WebCamOrientation
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'Etoys-Squeakland-MorphicExtras-WebCam'!
Item was added:
+ ----- Method: WebCamOrientation class>>initialize (in category 'as yet unclassified') -----
+ initialize
+ Vocabulary initialize.!
Item was added:
+ ----- Method: WebCamOrientation class>>orientations (in category 'as yet unclassified') -----
+ orientations
+ ^ #( native natural )!
Item was added:
+ ----- Method: WebCamOrientation>>initialize (in category 'as yet unclassified') -----
+ initialize
+ super initialize.
+ self vocabularyName: #WebCamOrientation.
+
+ self symbols: self class orientations.!
Item was added:
+ ----- Method: WebCamOrientation>>representsAType (in category 'as yet unclassified') -----
+ representsAType
+ ^true!
Item was changed:
----- Method: WebCamResolution class>>initialize (in category 'as yet unclassified') -----
initialize
+ Vocabulary initialize.!
- Vocabulary initialize!
Item was changed:
----- Method: WebCamResolution class>>resolutions (in category 'as yet unclassified') -----
resolutions
+ ^ #(#'low' #'medium' #'high' #'hd')
- ^ #(#'low' #'medium' #'high')
!
Tobias Pape uploaded a new version of Graphics to project The Trunk:
http://source.squeak.org/trunk/Graphics-topa.382.mcz
==================== Summary ====================
Name: Graphics-topa.382
Author: topa
Time: 4 October 2017, 2:43:10.503003 pm
UUID: 1f8b86d2-e987-40e3-84cd-8c689d87f60f
Ancestors: Graphics-mt.381
fix Point>>magnifyBy: to accept points
It already pretended to.
=============== Diff against Graphics-mt.381 ===============
Item was changed:
----- Method: Form>>magnifyBy: (in category 'scaling, rotation') -----
magnifyBy: scale
"Answer a Form created as a scaling of the receiver.
Scale may be a Float or even a Point, and may be greater or less than 1.0."
+ | effectiveScale |
+ effectiveScale := scale isPoint ifTrue: [scale r] ifFalse: [scale].
-
^ self magnify: self boundingBox by: scale
+ smoothing: (effectiveScale < 1 ifTrue: [2] ifFalse: [1])!
- smoothing: (scale < 1 ifTrue: [2] ifFalse: [1])!