Viewables


I'm using a ContainerWindow to display viewables. Is there a way to have these viewables positioned in a nice gridded pattern, like the stationery and desk accessories in the desk drawers?


Class ContainerWindow inherits AcceptMorsel() from class Window. AcceptMorsel() will put the specified viewable in a default position, then call MovedContents(). ContainerWindow_MovedContents will then position the viewable based on the grid values you've specified in your ContainerWindow object.

To position a viewable within your container window, all you need to do is call AcceptMorsel() for each viewable as it's added to the container window's view hierarchy.


How do I create a bank of drawers that will be available in the stamper all the time, like the Sony bank?


If you just want your bank of stamps to be available in your package, you should create an instance of the SceneAdditions class. Fill in the stampBankNames field with a Text object that contains the names of your drawers. Fill in the stampBankContents field with a list of your stamps. Look at the SceneAdditions for the name cards with the Inspector to get a great example of how this should be done.

If you want to make your bank of drawers universally available, you need to add a Text object with names for all five drawers in your bank to the iStampDrawerNameList object list, and an ObjectList with the first stamp in each drawer to the iStampDrawerChoiceList object list. Make an class which overrides InstallInto, place it in the install/receivers lists, and do this in the InstallInto method:

Method void
SomeClass_InstallInto(ObjectID self, ObjectID newObject, Unsigned flags,
                      ObjectID parameter, ObjectID unusedObsolete)
{
#pragma unused (self, newObject, flags, parameter, unusedObsolete)

   // Add our drawer bank to the stamper.
   AddLast(iStampDrawerChoiceList, ipDrawers);
   // Add the names for our drawers
   AddLast(iStampDrawerNameList, ipDrawerNames); 
}

ipDrawers and ipDrawerNames are package indexicals. Their object definitions look like this:

ipDrawers:

Instance ViewChainList 8;
         length: 5;
         entry1: (Stamp 11);
         entry2: (Stamp 24);
         entry3: (Stamp 36);
         entry4: (Stamp 48);
         entry5: (Stamp 60);
End Instance;

ipDrawerNames:

Instance Text 9;
           text: 'Mincho\nGothic\nMincho small\nGothic small\nAnnotated\n';
End Instance;

Each viewable in the ViewChainList is the first in a chain of things in the drawers. So, Stamp 11 is the first stamp in drawer 1, Stamp 60 is the first stamp in drawer 5, etc. Each chain of stamps should have their next/previous fields set appropriately, and their superview and subview fields should be nilObject.


If I provide more stamps in the stamper, will instances of that stamp have their own copies of the stamp image?


Image instances are shared objects. You could make 400 copies of a stamp and they would all end up sharing the same image object. At least until you move one of the stamps to another context, in which case the image is copied to the new context to give the stamp something to refer to. If you move another 199 stamps into the same place they will all share the same new image object. After moving 200 of your 400 stamps into the new place, there would be 400 stamp instances and 2 image instances.


How can I make my own Animal?


Class Animal inherits from Animation. Like animations, the individual frames of animation are Image objects linked together by their next and previous fields. The following discussion examines the psychology of animals in more detail.

There are 10 different "behaviors" an animal can be in:

      behavior        value    description
        walk            1       walking
        run             2       running
        stop            3       stopped
        sleep           4       sleeping
        sitdown         5       sitting down
        pinchup         6       being dragged (picked up)
        gesture         7       response to swallowing something
        reply           8       response to being shown or tapped
        fall            9       falling (after drag)
        wakeup          10      waking up after sleep

The BehaviorAnimation_behaviorImages ObjectList contains a list of image chains to use for the various behavior settings. The behaviorDelays field contains a list of corresponding FrameDelays for the various settings.

The Animal_behaviorSpeeds field contains a DataList of Dots to use as horizontal and vertical velocities for the various behavior settings. The behaviorPeriods field contains a DataList of Dots to use to determine the time to stay in that behavior before moving to another behavior. This dot value, after randomization, is put in the animalPatience field. The animalPatience is determined by adding a random number in the range of 0 to dot.v to the base time in dot.h.

Here is a description of the various states an Animal can transition to in Idle, based on its current behavior upon entry to Animal_Idle:

     behavior on entry --> possible new behaviors on exit (random decision)
        fall                    stop if it reached the floor
        walk                    run, stop
        run                     stop, walk
        sleep                   wake up, sleep
        sit down                sleep, walk, sit down
        wake up                 walk, sit down
        stop                    sit down, walk, run
        gesture                 sit down
        reply                   sit down

When I use Copy() to create a new viewable, it sometimes isn't deletable. Yet, I can always delete viewables that I create with the copy tool. Why?


When Copy() is called on a Viewable, it also copies the viewFlags, so if the original doesn't have the canDelete flag set, the copy won't either. If you want the copy to be deletable, you should explicitly call:

SetCanDelete(newViewable, true)

Viewables created with one of the New() methods will be deletable by default because Viewable_Init sets the canDelete flag.

The user accessible ways of copying viewables will call SetCanDelete() themselves, to make copies deletable.


How do I display the circled question mark when I create a TitledWindow?


All you have to do is add the Window to your package root list's "Objects With Help" list (entry 9), and the help text in the "Help on Objects" list (entry 10), exactly like help for other types of objects.

Precise information on how to do this can be found in the Magic Cap Concepts chapter on Windows as well as in most of the samples (start with HelloWorld's Objects.Def file).


My package runs fine under Magic Cap 1.0, but under Magic Cap 1.5, I'm hitting assertions in the simulator about objects having the same color and altColor. However, this assertion doesn't fire for all of my viewables, even for some that have the same value in their color and altColor fields. What does this assertion mean?


Magic Cap 1.5 uses the color and altColor fields of viewables for colorization. Weird things happen if the two contain the same value. This assertion is letting you know that you've got this case. The code goes on to use black and white so that things look normal, but you should change your object definitions. This is sort of like setting the foreground and background color to the same RGB value and then calling CopyBits on the Mac.

The routine that the assertion lives in is DrawImageRotatedColored(). The two routines that call this routine using the color and altColor fields of viewables are Viewable_DrawShadowedImage and Control_Draw. If you have any viewables that get passed to either of these routines, you'll need to make sure that their color and altColor fields don't match. In other words, it's not the type of viewable, but possible call chains that a viewable is used in.