Przez ostatni rok wzmocniłem swój warsztat używanych narzędzi do projektowania. Trochę więcej o jednym z nich będzie dzisiaj, tj. o „Sketchup” firmy Google.
Poza flagowym oprogramowaniem „Designer” firmy Komandor S.A., w której pracuję i w której rozwijamy ten soft, istnieje szereg innych programów do projektowania. Najbardziej rozbudowanymi z nich są chyba obecnie AutoCad firmy Autodesk oraz wspomniany „Sketchup” firmy Google. Pierwszy z nich poszerzył swój wachlarz zastosowań właściwie już na każdą dziedzinę projektowania dedykując oddzielne wersje dla elektryków, konstruktorów maszyn, architektów itd, a drugi nastawił się na prostotę i komunikację z użytkownikiem i używany jest m.in. do „tworzenia świata” w GoogleMaps. Co ciekawe obie firmy nastawione są bardzo przyjaźnie do zewnętrznego środowiska developerów;) Do obu produktów każdy dopisać może swoją wtyczkę, którą bez problemu testować i używać może wspomagając swoją pracę, tudzież rozwijając samo oprogramowanie. I tak, AutoCad przyjmuje wtyczki napisane w .NET (lub wewnętrznych językach ObjectARX i AutoLisp), a GoogleSketchup odpowiednio w Ruby (a ostatnio też C++). Wsparcie, tutoriale, API i pomoce jak najbardziej dostarczane są oficjalnie na specjalnie stworzonych stronach dla developerów:
Developer Center AutoDesk
Google Sketchup Developers
Dla przykładu przedstawię poniżej bardzo prosty skrypt napisany w Ruby dla Sketchupa, który nawiąże komunikację z zewnętrznym, równie prostym serwerem, napisanym w C#.
Najpierw samokomentujący się kod dla klienta:
plugins_menu.add_item("Connect to server") { server_connection } #dodajemy naszą wtyczkę, która uruchomi metodę server_connection zdefiniowaną poniżej
require 'D:/Programy/Ruby186/lib/ruby/1.8/i386-mingw32/socket' # wskazujemy na standardową bibliotekę - będziemy potrzebować modułu socket.so
#metoda łączaca się z zewnętrznym serwerem, wysyłająca komunikat i wyświetlająca odpowiedź:
def server_connection
port = 2011 #ustalamy port połączenia
streamSock = Socket::new(Socket::AF_INET, Socket::SOCK_STREAM, 0) #tworzymy socket
myaddr = [Socket::AF_INET, port, 127, 0, 0, 1, 0, 0].pack("snCCCCNN") #tworzymy adres, będziemy łączyć się do localhosta, więc jest tu zaszyte 127.0.0.1
streamSock.connect( myaddr ) #łączymy się
streamSock.puts "Hello from GoogleSketchup!" #wysyłamy komunikat do serwera
responseMessage = streamSock.recv(100) #odbieramy odpowiedź z serwera
UI.messagebox(responseMessage) #wyświetlamy w okienku Sketchupa informację zwrotną:)
streamSock.close #zamykamy socket
end
Jedna UWAGA: Najnowszą wersją Ruby jest 1.9.2, ale (najnowszy) Sketchup 8 używa 1.8.6 i w związku z tym konieczne jest używanie modułu ‘socket’ właśnie z biblioteki skompilowanej w 1.8.6 (wyższa nie działa)
Poniżej kod dla serwera:
{
private TcpListener tcpListener;
private Thread listenThread;
private int port = 2011;
static void Main(string[] args)
{
Server serv = new Server();
}
public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, this.port);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] dataReceived = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(dataReceived, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
string messageRecived = encoder.GetString(dataReceived, 0, bytesRead);
string messageReply = "You said: " + messageRecived + "\nWe say: Welcome designer in our external server;)";
byte[] dataToSent = encoder.GetBytes(messageReply);
clientStream.Write(dataToSent, 0, dataToSent.Length);
}
tcpClient.Close();
}
}
Jedyne co trzeba zrobić to skompilować kod C#, uruchomić serwer, a potem zapisać skrypt klienta (z rozszerzeniem *.rb) do katalogu ‘Plugins’ tam, gdzie jest zainstalowany Sketchup (to wystarczający warunek, aby Sketchup przyjął nasz skrypt!), uruchomić Sketchup i kliknąć Plugins->Connect to server, aby dostać po oczach okienkiem:
Taka komunikacja, choć wymagająca jeszcze rozbudowania, może się przydać do pewnej obróbki danych tworzonych podczas projektowania, podczas której zewnętrzny serwer „pilnuje” lub informuje projektanta o poczynionych krokach na bieżąco;) Całość operacji moglibyśmy zaszyć dzięki temu w zewnętrznym serwerze, a skrypt w Sketchup potrzebny byłby nam w zasadzie jedynie do wysłania danych z programu do projektowania. Notabene analogicznie moglibyśmy zrobić z AutoCadem, ujednolicając sposób obróbki danych gdzieś na zewnątrz, ale o tym może wkrótce…

