Рассматриваются два примера. В первом 3ds Max получает данных с сайта, а во втором - передает порцию данных на сайт. При решении этих задач на стороне 3ds Max используется ActiveX и dotNet средства MAXScript, а на сайте - программы 3dsmaxget.php и 3dsmaxpost.php. Первая формирует для 3ds Max список студенческой группы, а вторая, используя данные, переданные 3ds Max, обновляет на сайте mySQL- таблицу persons, хранящую сведения о студентах.
Примеры являются частью системы дистанционного обучения курсу программирования на MAXScript, включающей web-приложение Семестр (входит в сайт 100byte.ru) и MAXScript-средства контроля текущей успеваемости студентов.
Приложение Семестр обеспечивает доступ к материалам курса, принимает от слушателей MAXScript-коды и 3ds Max-рисунки, обеспечивающие решение предусмотренных программой курса задач.
Проверка заданий выполняется в 3ds Max. Преподаватель получает список студентов, после выбора студента преподаватель просматривает список присланных студентом решений. Работы, не имеющие оценки, могут быть загружены в текущем 3ds Max-сеансе, затем проверены и оценены. Оценка сохраняется в mySQL-базе данных web-приложения Семестр и при необходимости может быть изменена.
Задания и текущая успеваемость отображаются на соответствующих вкладках приложения (см. рис. 1 и вкладки Отчеты и Занятия на 100byte.ru).
Рис. 1. Текущая успеваемость
Получаемый от 100byte.ru список студенческой группы показан на рис. 2.
Рис. 2. Список студентов
Для получения результата на стороне 3ds Max средствами MAXScript создаются секция httpSock с элементом управления ActiveXControl port и секция webBrowser с элементом управления dotNetControl wb.
Обе секции воспроизводятся как диалоги.
HttpSock-диалог обеспечивает доступ к файлу 3dsmaxget.php, хранящемся на 100byte.ru, и получение результата, формируемого при выполнении этого файла.
WebBrowser-диалог благодаря элементу dotNetControl wb исполняется как html-страница, на которой отображается полученный результат - ответ сайта 100byte.ru, формируемый 3dsmaxget.php.
Дополнительная информация о выполняемых действиях содержится в комментарии нижеприводимого MAXScript- и 3dsmaxget.php-кода.
MAXScript- код (исполняется в 3ds Max):
-- Секция httpSock
rollout httpSock "httpSock" width:80 height:40 (
ActiveXControl port "Microsoft.XMLHTTP" pos:[10, 5] width:60 height:30 \
setupEvents:false releaseOnClose:true
)
-- Секция webBrowser
rollout webBrowser "Students" width:820 height:600 (
dotNetControl wb "System.Windows.Forms.WebBrowser" pos:[10,10] width:800 height:580
)
-- Позиционируем httpSock диалог за пределами окна вывода
createDialog httpSock pos:[-100, -100]
createDialog webBrowser
-- Получаем ActiveXControl-элемент управления port секции httpSock
sP = httpSock.port
-- Открывает порт с параметром "GET" (будем только запрашивать результаты)
-- Результаты формируются на 100byte.ru программой 3dsmaxget.php
sP.open "GET" "http://100byte.ru/3dsmaxget.php" false
-- Формируем заголовок запроса так, чтобы всегда иметь обновленный результат
-- (в общем случае запрос к сайту выполняется неоднократно)
sP.setRequestHeader "If-Modified-Since" "Sat, 1 Jan 1900 00:00:00 GMT"
-- Пересылка запроса (инициируется выполнение 3dsmaxget.php)
sP.send()
-- Получаем 100byte.ru-ответ как значение свойства responseText объекта sP = httpSock.port
-- Демонстрируем результат (см. рис. 2) в диалоге webBrowser,
-- используя свойство documentText элемента управления dotNetControl wb
-- Необходимые преобразования результата обеспечивает объект dotNetObject
webBrowser.wb.documentText = dotNetObject "System.String" sP.responseText
3dsmaxget.php-код (исполняется на 100byte.ru):
<?php
// Выполняет запрос к таблице persons mySQL-базы данных web-приложения Семестр
function shStdnts($idg) {
// Текст запроса
// idg - номер студенческой группы, idn - код студента
// team - номер бригады, name - ФИО студента
// del = 1, если запись имеет пометку удаления
$sql = "select idn, team, name";
$sql .= " from persons where idg = '$idg' and del = 0 and team > 0 order by name";
// Выполняем запрос
$q = mysql_query($sql);
// Число строк в результате
$nr = mysql_num_rows($q);
if ($nr == 0)
echo "Список пуст";
else {
// Вывод результата (будет передан 3ds Max)
echo "Список студентов<br>";
echo '<table border = "1" rules = "all">';
// Вывод заголовка таблицы со списком студентов
ptTH(array("№", "Бригада", "ФИО"));
for ($r = 0; $r < $nr; $r++) {
$arrF = mysql_fetch_array($q, MYSQL_NUM);
$arrF[0] = $r + 1;
// Вывод очередной строки таблицы со списком студентов
ptRw($arrF, 0);
}
echo "</table>";
}
}
// Обеспечивает вывод заголовка формируемой таблицы
function ptTH($arrF) {
echo "<tr align = 'center'>";
foreach ($arrF as $value) echo "<th>" . $value . "</th>";
}
// Обеспечивает вывод строки формируемой таблицы
function ptRw($arrF) {
$sz = sizeof($arrF);
echo "<tr>";
for ($d = 0; $d < $sz; $d++) echo "<td>" . $arrF[$d] . "</td>";
}
// Основная часть php-программы
date_default_timezone_set("Europe/Moscow");
$idgHr = 17;
// Меняем реальные данные на их описание
$server = <имя сервера>;
$usr = <имя пользователя>;
$ps = <пароль>;
$db = <имя базы данных>;
// Устанавливаем соединение с сервером
$c_id = mysql_connect($server, $usr, $ps);
if ($c_id) {
// Устанавливаем кодовую страницу
mysql_set_charset("cp1251", $c_id);
// Получаем указатель на базу данных
$dbs = mysql_select_db($db);
// Формируем список студенческой группы
if ($dbs) shStdnts($idgHr);
}
?>
Передача данных иллюстрируется при помощи проверочного диалога, открываемого в 3ds Max (рис. 3).
Рис. 3. Изменение таблицы persons
Диалог содержит поля для ввода кода студента, его фамилии, имени и отчества. В качестве кода студента может быть взят, например, номер его студенческого билета.
После нажатия на кнопку ОК введенные данные поверяются и отправляются на 100byte.ru с целью внесения изменений в таблицу persons: будет добавлена новая запись, если нет строки с указанным в диалоге кодом, в противном случая найденная по коду запись будет изменена. Код группы и номер бригады в диалоге не определяются, а задаются в MAXScript-коде, что упрощает восприятие примера.
Для проверки результата можно, нажав на кнопку List, вывести состав студенческой группы. Порядок вывода описан в предыдущем разделе.
Данные, переданные 100byte.ru после нажатия на кнопку ОК, обрабатываются на 100byte.ru программой 3dsmaxpost.php. Эта программа принимает в массив $_POST переданные ей данные, обновляет таблицу persons и сообщает об удаче или, если обновление не состоялось, - об ошибке.
Передаваемые 100byte.ru данные объединяются в MAXScript в строку pst. Каждая порция данных снабжается в строке pst именем; имя и данные разделяются знаком "=", все имена, кроме первого, предваряются символом &:
pst = "idn=" + edtCd.text + "&nm=" + edtNm.text + "&idg=" + idg + "&tm=" + tm
Эти имена используются в 3dsmaxpost.php для извлечения из массива $_POST соответствующих данных:
$idn = (int) $_POST["idn"];
$nm = $_POST["nm"];
$idg = (int) $_POST["idg"];
$tm = (int) $_POST["tm"];
Прочие пояснения находятся в комментарии приводимых ниже MAXScript- и PHP-программах.
MAXScript- код (исполняется в 3ds Max):
global sP, webBrowser
rollout httpSock "httpSock" width:80 height:40 (
ActiveXControl port "Microsoft.XMLHTTP" pos:[10, 5] width:60 height:30 \
setupEvents:false releaseOnClose:true
)
rollout webBrowser "Students" width:820 height:600 (
dotNetControl wb "System.Windows.Forms.WebBrowser" pos:[10,10] width:800 height:580
)
createDialog httpSock pos:[-100, -100]
createDialog webBrowser
sP = httpSock.port
-- Секция st для ввода кода и ФИО студента и последующей отправки данных на 100byte.ru
rollout st "Table persons update" width:402 height:72 (
label lblCd "Student's ID" pos:[4,12] width:82 height:20
edittext edtCd "" pos:[90,10] width:90 height:20
label lblNm "Student's name" pos:[4,42] width:82 height:20
edittext edtNm "" pos:[90,40] width:223 height:20
button btnOK "OK" pos:[326,5] width:66 height:20
button btnLst "List" pos:[326,39] width:66 height:20
on btnOK pressed do (
if edtCd.text == "" or edtNm.text == "" then
messageBox "Miss data on enter"
else (
-- Обновляем таблицу persons
idg = "17"
tm = "90"
pst = "idn=" + edtCd.text + "&nm=" + edtNm.text + "&idg=" + idg + "&tm=" + tm
-- Открывает порт с параметром " POST" (будем передавать и получать данные)
-- Результаты формируются на 100byte.ru программой 3dsmaxpost.php
sP.open "POST" "http://100byte.ru/3dsmaxpost.php" false
-- Формируем заголовок посылаемого сообщения
sP.setRequestHeader "If-Modified-Since" "Sat, 1 Jan 1900 00:00:00 GMT"
sP.setrequestheader "Content-type" "application/x-www-form-urlencoded"
-- Отправляем данные сайту 100byte.ru
sP.send pst
-- Получаем и показываем 100byte.ru-ответ
messageBox sP.responseText
)
)
on btnLst pressed do (
-- Выводим список студентов
-- MAXScript-код, обеспечивающий вывод, приведен без комментария
sP.open "GET" "http://100byte.ru/3dsmaxget.php" false
sP.setRequestHeader "If-Modified-Since" "Sat, 1 Jan 1900 00:00:00 GMT"
sP.send()
webBrowser.wb.documentText = dotNetObject "System.String" sP.responseText
)
)
createDialog st pos:[100, 100]
3dsmaxpost.php-код (исполняется на 100byte.ru):
Приводится часть кода, отвечающего за обновление таблицы persons.
<?php
// Обновляет таблицу persons
function treatPersons($idn, $nm, $idg, $tm) {
// Проверяем, есть ли запись с кодом $idn в таблице persons
$nr = inDb($idn);
switch ($nr) {
// Запись будет добавлена
case 0 : $sql = "insert into persons (idn, name, idg, team) values ('$idn', '$nm', '$idg', '$tm')";
// Информация для 3ds Max
echo "Persons: record is added\n"; break;
// Запись будет изменена
case 1 : $sql = "update persons set name = '$nm', idg = '$idg', team= '$tm' where idn = '$idn'";
// Информация для 3ds Max
echo "Persons: record is modified\n"; break;
case -1 : return ""; break;
}
// Выполняем запрос
$q = mysql_query($sql);
if ($q)
echo "OK";
else
sayErr();
}
// Возвращает:
// 0, если записи с кодом idn нет в таблице persons;
// 1, если запись с кодом idn найдена таблице persons;
// -1, если возникла ошибка
function inDb($idn) {
$sql = "select idn from persons where idn = $idn";
$q = mysql_query($sql);
if ($q) {
$nr = mysql_num_rows($q);
return ($nr == 0) ? 0 : 1;
}
else
return sayErr();
}
function sayErr() {
echo mysql_errno() . ": " . mysql_error();
return -1;
}
date_default_timezone_set("Europe/Moscow");
// Получаем данные от 3ds Max
$idn = (int) $_POST["idn"];
$nm = $_POST["nm"];
$idg = (int) $_POST["idg"];
$tm = (int) $_POST["tm"];
$server = <имя сервера>;
$usr = <имя пользователя>;
$ps = <пароль>;
$db = <имя базы данных>;
// Устанавливаем соединение с сервером
$c_id = mysql_connect($server, $usr, $ps);
if ($c_id) {
mysql_set_charset("cp1251", $c_id);
$dbs = mysql_select_db($db);
// Обновляем таблицу persons
if ($dbs) treatPersons($idn, $nm, $idg, $tm);
}
?>
Отладку php-кода можно выполнить на локальном сервере, управляя им, например, средствами WampServer. При отладке достаточно создать базу данных с одной таблицей persons, имеющей поля del, idn, idg, team и name (назначение полей описано выше). Первым 4-м поля можно назначить тип INT, а последнему – VARCHAR.
При таком варианте отладки кода значение переменой $server может быть следующим:
$server = "localhost";
Дополнительную информацию о соединении httpSock.port и возвращаемом ответе можно извлечь из нижеприведенных свойств соединения (для их вывода использован MAXScript-метод showProperties):
showProperties httpSock.port
.status : integer, read-only
.statusText : string, read-only
.responseXML : IXMLDOMImplementation, read-only
.responseText : string, read-only
.responseBody : undefined, read-only
.responseStream : undefined, read-only
.readyState : integer, read-only
.onreadystatechange : undefined