15 October 2002
Version 0.1.7

* Incorporated all changes from EVL's Version 0.1.5 (as of 3 Oct).
  These include:
   * Added 'heading' message and setHeading() function to ygCAVENavigator.
   * Added 'buttonUp' flags to ygCAVEWand
   * Added ambient & specular attributes to ygLight
   * Added pfChanged(), setPFChanged() functions to ygNode.
   * Added ygTexture class
   * ygSound's event 'StopPlaying' changed to simply 'stop'.
     'StartPlaying' event also changed to simply 'start' - the EVL 0.1.5
     version lacks a 'start' event.
   * Corrected ygVolUtil to use PFGS_WIREFRAME instead of PFEN_WIREFRAME.
   * Added pfBounds, pfCull, and pfTransform programs to src directory.
   Note: did _not_ include EVL changes to ygUser which eliminated other
   inherited messages.  The EVL version would get rid of the bogus
   errors whenever navigator messages are sent to a User, but I don't feel
   it's worth breaking the existing structure & losing use of certain messages.

* Changed PFUTEX_SHOW environment variable to YG_PF_SHOW_TEXTURES
* Added environment variables YG_PF_FORK_COMPUTE and YG_PF_INIT_SMOKES.
If these variables are set, the main program will fork a Performer compute
process and call pfuInitSmokes, respectively.  These two features were needed
by Alive on the Grid, but are not needed for most other applications.

* ygPrePFConfig() automatically adds YG_PATH to Performer's file path, so
setting PFPATH to the same value is no longer necessary.

* Added environment variable YG_PF_DBASE_CONVERTERS.  This variable can be
set to a space-separated list of model extensions (e.g. "flt iv obj"), and
ygPrePFConfig() will call pfdInitConverter for each extension listed.

* Removed most of the stuff from the 'modules' directory.  It now contains
just 7 basic classes that should be enough for getting started.  All other
modules should be distributed in a separate package.

* Back-ported some changes from my 0.2.1 development version:
   * Modified searching of YG_DSO_PATH to make sure that if more than one
    DSO for a particular name is found, the first one will be used (based
    on the order that directories are listed in YG_DSO_PATH).
   * Added support for module-initialization function.  If a module (DSO)
    'foo' contains a function named 'initialize_foo', this function will
    be called when the module is first loaded.
    In combination with YG_PRELOAD_CLASSES, this feature allows functions to
    be called before pfConfig().
    As with the 'construct_' function, this needs to be an 'extern "C"' function.
   * Added new DSO dependencies method.  Dependencies are listed in a string
    that will be included in the DSO. For example:
        char * add_Dependencies = "YG DSO Dependencies: value";
    With this method, a separate .ygdep file is not needed.
    ygdep files are still supported, for backwards-compatibility.
   * Added check for infinite loops in module dependencies.
   * Changed ygUser's 'showLocal' message to 'hideLocal' to hopefully make it
    a little clearer that you actually have to send the message to hide the
    avatar locally (i.e. the avatar is visible locally by default)
   * Added 'matrix' message to ygTransform - accepts full matrix as 16 numbers

* Modified ygEnvironment to better handle cases where 2 or more environment
nodes overlap.  Previously it was possible to leave an overlap zone and not
have the correct environment activated (because the node that should be
applied thought that it already was).  Now the correct environment will be
applied outside of overlap zones; inside an overlap, the last environment
node still 'wins'.

* Modified ygNodeDB / ygDSOLoader to have just the DSOLoader keep track of
constructor pointers.  This change makes it possible for a module to list
built-in classes in its dependencies without causing problems (thus a module
writer doesn't have to keep track of which classes are built-in and which
aren't).

* Added optional second argument to "file" message of ygObject & staticObject.
The argument is a bool value which temporarily overrides the "cache" setting
(to allow loading uncached models with one message, instead of two).

* Added "reload" message to ygObject & staticObject.

* Made ygObject & staticObject include their cache-flag in their networked
data, so that clients will cache or not cache models the same as the master. 


-------------------------------------------------------------------------------
20 September 2002
Version 0.1.6

* Modified ygNetClient, so that the initial database download (downloadViaTCP())
is done over a different connection, rather than the TCP reflector connection
that is used for updates while the program is running.  By default, this connection
is to the same host ($YG_NET_SERVER), with 1 added to the port number (i.e. 3501
or $YG_NET_PORT + 1).  This can be changed by the environment variables
YG_NET_CACHE_SERVER & YG_NET_CACHE_PORT (although there's no reason to actually
use these variables at the moment).
 ygrepeater has been modified so that now the main process is simpler, just a
UDP & TCP reflector.  It passes copies of all incoming packets to a second thread
(through a large block of memory); this second thread takes care of parsing the
packets to keep a copy of the Yg database, and it creates the 'cache' socket
that downloadViaTCP() will connect to.
 The result of this should be that when new clients connect, existing clients will
_not_ be frozen.  The main reflector thread will continue on as normal.  If the
download takes a very long time, the shared memory buffer used to send packets from
the main to the cache thread may run out of space, in which case any more data that
would have been sent to the cache thread will be dropped, but the reflector will not
block.
 (Ugly tech detail: I created the class ygrepeaterQueue to handle passing data between
ygrepeater threads in a large malloc'ed buffer because all fancier IPC mechanisms -
pipes, message queues, sockets - have very limited buffer sizes, usually just a few
kilobytes of kernel memory.  For our types of applications, it needs to be capable of
buffering up several megabytes of data.)


* Modified ygNet / ygNetClient to add reset() function.  This is meant for cases
where the ygrepeater crashes and must be restarted, so that clients can reconnect
& re-synch without having to exit and start over from scratch.  ygNetClient::reset
will close & reopen its TCP socket (UDP being connectionless, nothing needs to be
done), and then re-downloads the current state of the database, and uploads all of
the keys that the local client owns.
 This function will be called in response to a 'netreset' command sent via sendMessage,
or typed at the command line.


* Modified the main program to read commands / messages from the keyboard (stdin),
in addition to a UDP socket.


* Added a function ygMakeValidNodeName(string), which will force a string to consist
only of letters, numbers, and underscores.  All other characters are converted to
underscores.  This function is applied to the base-string for all dummy names that
Yg assigns to unnamed nodes.
 Previously, some hosts would produce nodes with names such as 'mediastudy1.fal.buffalo.edu771'.
Such names would cause problems when sending messages to the nodes (and caused problems
for the pyNode classes).  Now, the name would become 'mediastudy1_fal_buffalo_edu771'.
 Names that are explicitly defined in a scene file are not affected.  e.g.
 	light foo.bar ()
will still create a node named "foo.bar".  In the future a warning (or perhaps a fatal
error) should be produced for these names.


* Tweaked ygTokenStream to better catch/report unclosed parentheses.  It will now
report the line number of the opening, unclosed parenthesis.


* Added ygNet::midframeProcess().  This function is called by ygNode::app().  If the
environment variable YG_NET_PROCESS_INTERVAL is set to a non-zero value, then
midframeProcess() will try to make sure that ygNet::process() is called once
every $YG_NET_PROCESS_INTERVAL seconds.  This is meant to prevent the network sockets
from being overloaded with incoming data in a high-bandwidth application.

* To go along with midframeProcess(), changed ygNet::storeKey() to immediately pass
the data to ygNetClient::put*() if we're not running in threaded mode, rather than
copying the data into the queue and then reading it back out again later in the
same thread.  This should space out the put()s better in high-bandwidth cases,
to hopefully reduce any loss of outgoing UDP packets.


-------------------------------------------------------------------------------
12 November 2001
Version 0.1.5

added function ygNode::isOfClass()

added volumeType() function to ygVolume and all subclasses.
defined constants YGVOL_INFINITE, YGVOL_POINT, YGVOL_BOX, YGVOL_SPHERE, and
YGVOL_CYLINDER for return values.

removed all dynamic_casts, replaced by calls to isOfClass() or volumeType().
This clears up the mysterious crashes that occur under some versions of Linux
& g++.


-------------------------------------------------------------------------------
Version 0.1.4 and earlier

added --noview argument to main program, to run 'server mode'

main program will accept multiple scene files on the command line,
so that User file (for example) can be loaded separately, rather
than #included

made main program remove all its nodes from the scene graph
when exiting

added virtual destructors to volume and node classes

added assignment operators to volume classes

added check to ygNodeDB::create - prints a warning message when someone
creates two nodes with the same name

added timing statistics collection to ygNode

added ygServerMode() (and ygSetServerMode()) for AEC show development -
so people can leave out code that doesn't need to be executed on the
view-less server

added ygFileRequest & ygFileServer for remote file uploads & downloads

added showLocal command to ygObject (and corrected its behavior in staticObject
so that it won't crash if called before an object is loaded)



-----
9 Aug:

modified network database refreshing to try to avoid calling acceptKey when
a key's data hasn't actually changed.  done by comparing a checksum of the
old & new data.  note: this is not done when a key is received the normal
way (as a result of netKeyChanged() on the master); in that case, acceptKey
is always called.

added Ygdrasil version number to all headers, so you can verify that you're
using the correct ones

-----
21 Aug

turned off net database refreshing by default

changed YG_NET_REFRESH_INTERVAL to a time value - number of seconds between
refreshes.  so, a reasonable setting would be something like
	setenv YG_NET_REFRESH_INTERVAL .1

added net.download debug flag

fixed ygUser's 'wands' netkey - wasn't clearing out the vector first when it
received a new value


-----
23 Aug

added fileserver.transfer debug flag, to print info when uploading & downloading
files

changed networking to allow transmission of any key via reliable or unreliable
connection.  specific keys can be controlled from the scene file via the
'reliableKey' and 'unreliableKey' messages.  e.g.
	flasher (unreliableKey(on))


-----
24 Aug

added YG_NET_DEFAULT_RELIABLE environment variable.  if this is set, all keys
(except matrices) will default to reliable transmission; otherwise, they
default to unreliable.


-----
31 Aug

added ygSimpleTransform class - transformation that consists only of translation
& rotation.

added COORD netkey type, for SimpleTransform

changed ygCAVETracker & ygUser to be derived from ygSimpleTransform

added 'cache' message to ygObject

added filename() function to ygObject

added several safety checks for NULL pointers to ygString

changed "matrix" netkey name in ygTransform to "m", to reduce network traffic

modified message sending in ygWorld - if a node does not exist locally, it will
not spend several seconds looking for it on the network, but just print an
immediate error message

